diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Expr.cpp | 7 | ||||
-rw-r--r-- | clang/lib/AST/ExprCXX.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Analysis/Consumed.cpp | 6 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.cpp | 5 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaCoroutine.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExpr.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 16 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 30 | ||||
-rw-r--r-- | clang/lib/Sema/SemaLambda.cpp | 11 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Sema/SemaStmt.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 1 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 3 |
17 files changed, 109 insertions, 51 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 4c0492c3935..dc87c0a8e26 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2890,7 +2890,6 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, case CXXThrowExprClass: case CXXNewExprClass: case CXXDeleteExprClass: - case ExprWithCleanupsClass: case CoawaitExprClass: case CoyieldExprClass: // These always have a side-effect. @@ -2903,6 +2902,12 @@ bool Expr::HasSideEffects(const ASTContext &Ctx, return Finder.hasSideEffects(); } + case ExprWithCleanupsClass: + if (IncludePossibleEffects) + if (cast<ExprWithCleanups>(this)->cleanupsHaveSideEffects()) + return true; + break; + case ParenExprClass: case ArraySubscriptExprClass: case OMPArraySectionExprClass: diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp index 031332d7ce6..a13033d4746 100644 --- a/clang/lib/AST/ExprCXX.cpp +++ b/clang/lib/AST/ExprCXX.cpp @@ -1023,6 +1023,7 @@ bool LambdaExpr::isMutable() const { } ExprWithCleanups::ExprWithCleanups(Expr *subexpr, + bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) : Expr(ExprWithCleanupsClass, subexpr->getType(), subexpr->getValueKind(), subexpr->getObjectKind(), @@ -1030,16 +1031,19 @@ ExprWithCleanups::ExprWithCleanups(Expr *subexpr, subexpr->isInstantiationDependent(), subexpr->containsUnexpandedParameterPack()), SubExpr(subexpr) { + ExprWithCleanupsBits.CleanupsHaveSideEffects = CleanupsHaveSideEffects; ExprWithCleanupsBits.NumObjects = objects.size(); for (unsigned i = 0, e = objects.size(); i != e; ++i) getTrailingObjects<CleanupObject>()[i] = objects[i]; } ExprWithCleanups *ExprWithCleanups::Create(const ASTContext &C, Expr *subexpr, + bool CleanupsHaveSideEffects, ArrayRef<CleanupObject> objects) { void *buffer = C.Allocate(totalSizeToAlloc<CleanupObject>(objects.size()), llvm::alignOf<ExprWithCleanups>()); - return new (buffer) ExprWithCleanups(subexpr, objects); + return new (buffer) + ExprWithCleanups(subexpr, CleanupsHaveSideEffects, objects); } ExprWithCleanups::ExprWithCleanups(EmptyShell empty, unsigned numObjects) diff --git a/clang/lib/Analysis/Consumed.cpp b/clang/lib/Analysis/Consumed.cpp index 9df23923b01..f2a7d904a54 100644 --- a/clang/lib/Analysis/Consumed.cpp +++ b/clang/lib/Analysis/Consumed.cpp @@ -466,9 +466,15 @@ class ConsumedStmtVisitor : public ConstStmtVisitor<ConsumedStmtVisitor> { MapType PropagationMap; InfoEntry findInfo(const Expr *E) { + if (auto Cleanups = dyn_cast<ExprWithCleanups>(E)) + if (!Cleanups->cleanupsHaveSideEffects()) + E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } ConstInfoEntry findInfo(const Expr *E) const { + if (auto Cleanups = dyn_cast<ExprWithCleanups>(E)) + if (!Cleanups->cleanupsHaveSideEffects()) + E = Cleanups->getSubExpr(); return PropagationMap.find(E->IgnoreParens()); } void insertInfo(const Expr *E, const PropagationInfo &PI) { diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 8ad1a4d29cd..803b39907dd 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -764,6 +764,12 @@ public: return Visit(DIE->getExpr()); } + llvm::Constant *VisitExprWithCleanups(ExprWithCleanups *E) { + if (!E->cleanupsHaveSideEffects()) + return Visit(E->getSubExpr()); + return nullptr; + } + llvm::Constant *VisitMaterializeTemporaryExpr(MaterializeTemporaryExpr *E) { return Visit(E->GetTemporaryExpr()); } diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp index e7708e044d2..d7697bfc9be 100644 --- a/clang/lib/Sema/Sema.cpp +++ b/clang/lib/Sema/Sema.cpp @@ -88,7 +88,7 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, ConstSegStack(nullptr), CodeSegStack(nullptr), CurInitSeg(nullptr), VisContext(nullptr), IsBuildingRecoveryCallExpr(false), - ExprNeedsCleanups(false), LateTemplateParser(nullptr), + Cleanup{}, LateTemplateParser(nullptr), LateTemplateParserCleanup(nullptr), OpaqueParser(nullptr), IdResolver(pp), StdInitializerList(nullptr), CXXTypeInfoDecl(nullptr), MSVCGuidDecl(nullptr), @@ -124,7 +124,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, // Tell diagnostics how to render things from the AST library. Diags.SetArgToStringFn(&FormatASTNodeDiagnosticArgument, &Context); - ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, false, nullptr, false); + ExprEvalContexts.emplace_back(PotentiallyEvaluated, 0, CleanupInfo{}, nullptr, + false); FunctionScopes.push_back(new FunctionScopeInfo(Diags)); diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index df32dbdb150..d27500d3f13 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -641,8 +641,8 @@ void CastOperation::CheckDynamicCast() { // If we're dynamic_casting from a prvalue to an rvalue reference, we need // to materialize the prvalue before we bind the reference to it. if (SrcExpr.get()->isRValue()) - SrcExpr = new (Self.Context) MaterializeTemporaryExpr( - SrcType, SrcExpr.get(), /*IsLValueReference*/false); + SrcExpr = Self.CreateMaterializeTemporaryExpr( + SrcType, SrcExpr.get(), /*IsLValueReference*/ false); SrcPointee = SrcType; } @@ -1649,8 +1649,8 @@ static TryCastResult TryConstCast(Sema &Self, ExprResult &SrcExpr, if (NeedToMaterializeTemporary) // This is a const_cast from a class prvalue to an rvalue reference type. // Materialize a temporary to store the result of the conversion. - SrcExpr = new (Self.Context) MaterializeTemporaryExpr( - SrcType, SrcExpr.get(), /*IsLValueReference*/ false); + SrcExpr = Self.CreateMaterializeTemporaryExpr(SrcType, SrcExpr.get(), + /*IsLValueReference*/ false); return TC_Success; } diff --git a/clang/lib/Sema/SemaCoroutine.cpp b/clang/lib/Sema/SemaCoroutine.cpp index 4b4fd6b16a0..c8715fff415 100644 --- a/clang/lib/Sema/SemaCoroutine.cpp +++ b/clang/lib/Sema/SemaCoroutine.cpp @@ -244,7 +244,7 @@ ExprResult Sema::BuildCoawaitExpr(SourceLocation Loc, Expr *E) { // If the expression is a temporary, materialize it as an lvalue so that we // can use it multiple times. if (E->getValueKind() == VK_RValue) - E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); + E = CreateMaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); @@ -311,7 +311,7 @@ ExprResult Sema::BuildCoyieldExpr(SourceLocation Loc, Expr *E) { // If the expression is a temporary, materialize it as an lvalue so that we // can use it multiple times. if (E->getValueKind() == VK_RValue) - E = new (Context) MaterializeTemporaryExpr(E->getType(), E, true); + E = CreateMaterializeTemporaryExpr(E->getType(), E, true); // Build the await_ready, await_suspend, await_resume calls. ReadySuspendResumeResult RSS = buildCoawaitCalls(*this, Loc, E); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index deb8d15c8ff..0e9e9e55ff0 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -11647,7 +11647,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, assert(ExprCleanupObjects.size() == ExprEvalContexts.back().NumCleanupObjects && "Leftover temporaries in function"); - assert(!ExprNeedsCleanups && "Unaccounted cleanups in function"); + assert(!Cleanup.exprNeedsCleanups() && "Unaccounted cleanups in function"); assert(MaybeODRUseExprs.empty() && "Leftover expressions for odr-use checking"); } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 3a33319c376..755d99d54b3 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -712,7 +712,7 @@ ExprResult Sema::DefaultLvalueConversion(Expr *E) { // balance that. if (getLangOpts().ObjCAutoRefCount && E->getType().getObjCLifetime() == Qualifiers::OCL_Weak) - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); ExprResult Res = ImplicitCastExpr::Create(Context, T, CK_LValueToRValue, E, nullptr, VK_RValue); @@ -4580,15 +4580,15 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc, // bound temporaries; see the comment in PR5810. // We don't need to do that with block decls, though, because // blocks in default argument expression can never capture anything. - if (isa<ExprWithCleanups>(Param->getInit())) { + if (auto Init = dyn_cast<ExprWithCleanups>(Param->getInit())) { // Set the "needs cleanups" bit regardless of whether there are // any explicit objects. - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(Init->cleanupsHaveSideEffects()); // Append all the objects to the cleanup list. Right now, this // should always be a no-op, because blocks in default argument // expressions should never be able to capture anything. - assert(!cast<ExprWithCleanups>(Param->getInit())->getNumObjects() && + assert(!Init->getNumObjects() && "default argument expression has capturing blocks?"); } @@ -5603,7 +5603,7 @@ void Sema::maybeExtendBlockObject(ExprResult &E) { E = ImplicitCastExpr::Create(Context, E.get()->getType(), CK_ARCExtendBlockObject, E.get(), /*base path*/ nullptr, VK_RValue); - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); } /// Prepare a conversion of the given expression to an ObjC object @@ -10389,8 +10389,8 @@ QualType Sema::CheckAddressOfOperand(ExprResult &OrigOp, SourceLocation OpLoc) { if (sfinae) return QualType(); // Materialize the temporary as an lvalue so that we can take its address. - OrigOp = op = new (Context) - MaterializeTemporaryExpr(op->getType(), OrigOp.get(), true); + OrigOp = op = + CreateMaterializeTemporaryExpr(op->getType(), OrigOp.get(), true); } else if (isa<ObjCSelectorExpr>(op)) { return Context.getPointerType(op->getType()); } else if (lval == Expr::LV_MemberFunction) { @@ -11603,7 +11603,8 @@ Sema::ActOnStmtExpr(SourceLocation LPLoc, Stmt *SubStmt, if (hasAnyUnrecoverableErrorsInThisFunction()) DiscardCleanupsInEvaluationContext(); - assert(!ExprNeedsCleanups && "cleanups within StmtExpr not correctly bound!"); + assert(!Cleanup.exprNeedsCleanups() && + "cleanups within StmtExpr not correctly bound!"); PopExpressionEvaluationContext(); // FIXME: there are a variety of strange constraints to enforce here, for @@ -12071,7 +12072,8 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, // Leave the expression-evaluation context. if (hasAnyUnrecoverableErrorsInThisFunction()) DiscardCleanupsInEvaluationContext(); - assert(!ExprNeedsCleanups && "cleanups within block not correctly bound!"); + assert(!Cleanup.exprNeedsCleanups() && + "cleanups within block not correctly bound!"); PopExpressionEvaluationContext(); BlockScopeInfo *BSI = cast<BlockScopeInfo>(FunctionScopes.back()); @@ -12162,7 +12164,7 @@ ExprResult Sema::ActOnBlockStmtExpr(SourceLocation CaretLoc, if (Result->getBlockDecl()->hasCaptures()) { // First, this expression has a new cleanup object. ExprCleanupObjects.push_back(Result->getBlockDecl()); - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); // It also gets a branch-protected scope if any of the captured // variables needs destruction. @@ -12799,10 +12801,9 @@ void Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl, bool IsDecltype) { - ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), - ExprNeedsCleanups, LambdaContextDecl, - IsDecltype); - ExprNeedsCleanups = false; + ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup, + LambdaContextDecl, IsDecltype); + Cleanup.reset(); if (!MaybeODRUseExprs.empty()) std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs); } @@ -12853,12 +12854,12 @@ void Sema::PopExpressionEvaluationContext() { if (Rec.isUnevaluated() || Rec.Context == ConstantEvaluated) { ExprCleanupObjects.erase(ExprCleanupObjects.begin() + Rec.NumCleanupObjects, ExprCleanupObjects.end()); - ExprNeedsCleanups = Rec.ParentNeedsCleanups; + Cleanup = Rec.ParentCleanup; CleanupVarDeclMarking(); std::swap(MaybeODRUseExprs, Rec.SavedMaybeODRUseExprs); // Otherwise, merge the contexts together. } else { - ExprNeedsCleanups |= Rec.ParentNeedsCleanups; + Cleanup.mergeFrom(Rec.ParentCleanup); MaybeODRUseExprs.insert(Rec.SavedMaybeODRUseExprs.begin(), Rec.SavedMaybeODRUseExprs.end()); } @@ -12877,7 +12878,7 @@ void Sema::DiscardCleanupsInEvaluationContext() { ExprCleanupObjects.erase( ExprCleanupObjects.begin() + ExprEvalContexts.back().NumCleanupObjects, ExprCleanupObjects.end()); - ExprNeedsCleanups = false; + Cleanup.reset(); MaybeODRUseExprs.clear(); } diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index fdaa005108a..d5e944fa110 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -5644,7 +5644,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { if (!ReturnsRetained && E->getType()->isObjCARCImplicitlyUnretainedType()) return E; - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); CastKind ck = (ReturnsRetained ? CK_ARCConsumeObject : CK_ARCReclaimReturnedObject); @@ -5697,7 +5697,7 @@ ExprResult Sema::MaybeBindToTemporary(Expr *E) { return E; // We need a cleanup, but we don't need to remember the temporary. - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); } CXXTemporary *Temp = CXXTemporary::Create(Context, Destructor); @@ -5724,14 +5724,16 @@ Expr *Sema::MaybeCreateExprWithCleanups(Expr *SubExpr) { unsigned FirstCleanup = ExprEvalContexts.back().NumCleanupObjects; assert(ExprCleanupObjects.size() >= FirstCleanup); - assert(ExprNeedsCleanups || ExprCleanupObjects.size() == FirstCleanup); - if (!ExprNeedsCleanups) + assert(Cleanup.exprNeedsCleanups() || + ExprCleanupObjects.size() == FirstCleanup); + if (!Cleanup.exprNeedsCleanups()) return SubExpr; auto Cleanups = llvm::makeArrayRef(ExprCleanupObjects.begin() + FirstCleanup, ExprCleanupObjects.size() - FirstCleanup); - Expr *E = ExprWithCleanups::Create(Context, SubExpr, Cleanups); + auto *E = ExprWithCleanups::Create( + Context, SubExpr, Cleanup.cleanupsHaveSideEffects(), Cleanups); DiscardCleanupsInEvaluationContext(); return E; @@ -5742,7 +5744,7 @@ Stmt *Sema::MaybeCreateStmtWithCleanups(Stmt *SubStmt) { CleanupVarDeclMarking(); - if (!ExprNeedsCleanups) + if (!Cleanup.exprNeedsCleanups()) return SubStmt; // FIXME: In order to attach the temporaries, wrap the statement into @@ -5848,7 +5850,7 @@ ExprResult Sema::ActOnDecltypeExpression(Expr *E) { return ExprError(); // We need a cleanup, but we don't need to remember the temporary. - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); } // Possibly strip off the top CXXBindTemporaryExpr. diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 56161c7a4d2..598ae2098aa 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -4067,7 +4067,7 @@ Sema::CheckObjCARCConversion(SourceRange castRange, QualType castType, castExpr = ImplicitCastExpr::Create(Context, castExpr->getType(), CK_ARCConsumeObject, castExpr, nullptr, VK_RValue); - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); return ACR_okay; } @@ -4310,7 +4310,7 @@ ExprResult Sema::BuildObjCBridgedCast(SourceLocation LParenLoc, TSInfo, SubExpr); if (MustConsume) { - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); Result = ImplicitCastExpr::Create(Context, T, CK_ARCConsumeObject, Result, nullptr, VK_RValue); } diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 95c25de7aa8..2bd5217d215 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -4807,8 +4807,8 @@ static void checkIndirectCopyRestoreSource(Sema &S, Expr *src) { // If isWeakAccess to true, there will be an implicit // load which requires a cleanup. if (S.getLangOpts().ObjCAutoRefCount && isWeakAccess) - S.ExprNeedsCleanups = true; - + S.Cleanup.setExprNeedsCleanups(true); + if (iik == IIK_okay) return; S.Diag(src->getExprLoc(), diag::err_arc_nonlocal_writeback) @@ -6182,6 +6182,22 @@ static void CheckForNullPointerDereference(Sema &S, const Expr *E) { } } +MaterializeTemporaryExpr * +Sema::CreateMaterializeTemporaryExpr(QualType T, Expr *Temporary, + bool BoundToLvalueReference) { + auto MTE = new (Context) + MaterializeTemporaryExpr(T, Temporary, BoundToLvalueReference); + + // Order an ExprWithCleanups for lifetime marks. + // + // TODO: It'll be good to have a single place to check the access of the + // destructor and generate ExprWithCleanups for various uses. Currently these + // are done in both CreateMaterializeTemporaryExpr and MaybeBindToTemporary, + // but there may be a chance to merge them. + Cleanup.setExprNeedsCleanups(false); + return MTE; +} + ExprResult InitializationSequence::Perform(Sema &S, const InitializedEntity &Entity, @@ -6446,7 +6462,7 @@ InitializationSequence::Perform(Sema &S, return ExprError(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = new (S.Context) MaterializeTemporaryExpr( + MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( Entity.getType().getNonReferenceType(), CurInit.get(), Entity.getType()->isLValueReferenceType()); @@ -6466,7 +6482,7 @@ InitializationSequence::Perform(Sema &S, MTE->getType()->isObjCLifetimeType()) || (MTE->getStorageDuration() == SD_Automatic && MTE->getType().isDestructedType())) - S.ExprNeedsCleanups = true; + S.Cleanup.setExprNeedsCleanups(true); CurInit = MTE; break; @@ -6858,9 +6874,9 @@ InitializationSequence::Perform(Sema &S, << CurInit.get()->getSourceRange(); // Materialize the temporary into memory. - MaterializeTemporaryExpr *MTE = new (S.Context) - MaterializeTemporaryExpr(CurInit.get()->getType(), CurInit.get(), - /*BoundToLvalueReference=*/false); + MaterializeTemporaryExpr *MTE = S.CreateMaterializeTemporaryExpr( + CurInit.get()->getType(), CurInit.get(), + /*BoundToLvalueReference=*/false); // Maybe lifetime-extend the array temporary's subobjects to match the // entity's lifetime. diff --git a/clang/lib/Sema/SemaLambda.cpp b/clang/lib/Sema/SemaLambda.cpp index d1d002b5d41..ae768b62677 100644 --- a/clang/lib/Sema/SemaLambda.cpp +++ b/clang/lib/Sema/SemaLambda.cpp @@ -1500,7 +1500,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, SourceRange IntroducerRange; bool ExplicitParams; bool ExplicitResultType; - bool LambdaExprNeedsCleanups; + CleanupInfo LambdaCleanup; bool ContainsUnexpandedParameterPack; SmallVector<VarDecl *, 4> ArrayIndexVars; SmallVector<unsigned, 4> ArrayIndexStarts; @@ -1510,7 +1510,7 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, IntroducerRange = LSI->IntroducerRange; ExplicitParams = LSI->ExplicitParams; ExplicitResultType = !LSI->HasImplicitReturnType; - LambdaExprNeedsCleanups = LSI->ExprNeedsCleanups; + LambdaCleanup = LSI->Cleanup; ContainsUnexpandedParameterPack = LSI->ContainsUnexpandedParameterPack; CallOperator->setLexicalDeclContext(Class); @@ -1591,9 +1591,8 @@ ExprResult Sema::BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, CheckCompletedCXXClass(Class); } - if (LambdaExprNeedsCleanups) - ExprNeedsCleanups = true; - + Cleanup.mergeFrom(LambdaCleanup); + LambdaExpr *Lambda = LambdaExpr::Create(Context, Class, IntroducerRange, CaptureDefault, CaptureDefaultLoc, Captures, @@ -1714,7 +1713,7 @@ ExprResult Sema::BuildBlockForLambdaConversion(SourceLocation CurrentLocation, // Create the block literal expression. Expr *BuildBlock = new (Context) BlockExpr(Block, Conv->getConversionType()); ExprCleanupObjects.push_back(Block); - ExprNeedsCleanups = true; + Cleanup.setExprNeedsCleanups(true); return BuildBlock; } diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 291b9fa0189..5f28aa37e66 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -3801,6 +3801,10 @@ bool OpenMPIterationSpaceChecker::CheckInit(Stmt *S, bool EmitDiags) { } return true; } + if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) + if (!ExprTemp->cleanupsHaveSideEffects()) + S = ExprTemp->getSubExpr(); + InitSrcRange = S->getSourceRange(); if (Expr *E = dyn_cast<Expr>(S)) S = E->IgnoreParens(); @@ -3988,6 +3992,10 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) { SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_incr) << LCDecl; return true; } + if (auto *ExprTemp = dyn_cast<ExprWithCleanups>(S)) + if (!ExprTemp->cleanupsHaveSideEffects()) + S = ExprTemp->getSubExpr(); + IncrementSrcRange = S->getSourceRange(); S = S->IgnoreParens(); if (auto UO = dyn_cast<UnaryOperator>(S)) { diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index d2d4098d177..7156cd2a9ad 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -1518,6 +1518,10 @@ namespace { // variables Increment and DRE. bool ProcessIterationStmt(Sema &S, Stmt* Statement, bool &Increment, DeclRefExpr *&DRE) { + if (auto Cleanups = dyn_cast<ExprWithCleanups>(Statement)) + if (!Cleanups->cleanupsHaveSideEffects()) + Statement = Cleanups->getSubExpr(); + if (UnaryOperator *UO = dyn_cast<UnaryOperator>(Statement)) { switch (UO->getOpcode()) { default: return false; @@ -2472,6 +2476,10 @@ static void DiagnoseForRangeReferenceVariableCopies(Sema &SemaRef, QualType VariableType = VD->getType(); + if (auto Cleanups = dyn_cast<ExprWithCleanups>(InitExpr)) + if (!Cleanups->cleanupsHaveSideEffects()) + InitExpr = Cleanups->getSubExpr(); + const MaterializeTemporaryExpr *MTE = dyn_cast<MaterializeTemporaryExpr>(InitExpr); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 15e289f6f8e..abb885e81b2 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1448,6 +1448,7 @@ void ASTStmtReader::VisitExprWithCleanups(ExprWithCleanups *E) { E->getTrailingObjects<BlockDecl *>()[i] = ReadDeclAs<BlockDecl>(Record, Idx); + E->ExprWithCleanupsBits.CleanupsHaveSideEffects = Record[Idx++]; E->SubExpr = Reader.ReadSubExpr(); } diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 5382b4af922..911ac478b81 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1430,7 +1430,8 @@ void ASTStmtWriter::VisitExprWithCleanups(ExprWithCleanups *E) { Record.push_back(E->getNumObjects()); for (unsigned i = 0, e = E->getNumObjects(); i != e; ++i) Record.AddDeclRef(E->getObject(i)); - + + Record.push_back(E->cleanupsHaveSideEffects()); Record.AddStmt(E->getSubExpr()); Code = serialization::EXPR_EXPR_WITH_CLEANUPS; } |