Author: epilk Date: Tue Mar 26 16:21:19 2019 New Revision: 357040 URL: http://llvm.org/viewvc/llvm-project?rev=357040&view=rev Log: [Sema] Fix an assert when a block captures a constexpr local
MarkVarDeclODRUsed indirectly calls captureInBlock, which creates a copy expression. The copy expression is insulated in it's own ExpressionEvaluationContext, so it saves, mutates, and restores MaybeODRUseExprs as CleanupVarDeclMarking is iterating through it, leading to a crash. Fix this by iterating through a local copy of MaybeODRUseExprs. rdar://47493525 https://reviews.llvm.org/D59670 Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/test/SemaCXX/blocks.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=357040&r1=357039&r2=357040&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Tue Mar 26 16:21:19 2019 @@ -587,13 +587,13 @@ public: /// element type here is ExprWithCleanups::Object. SmallVector<BlockDecl*, 8> ExprCleanupObjects; - /// Store a list of either DeclRefExprs or MemberExprs - /// that contain a reference to a variable (constant) that may or may not - /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue - /// and discarded value conversions have been applied to all subexpressions - /// of the enclosing full expression. This is cleared at the end of each - /// full expression. - llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs; + /// Store a set of either DeclRefExprs or MemberExprs that contain a reference + /// to a variable (constant) that may or may not be odr-used in this Expr, and + /// we won't know until all lvalue-to-rvalue and discarded value conversions + /// have been applied to all subexpressions of the enclosing full expression. + /// This is cleared at the end of each full expression. + using MaybeODRUseExprSet = llvm::SmallPtrSet<Expr *, 2>; + MaybeODRUseExprSet MaybeODRUseExprs; std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope; @@ -1029,7 +1029,7 @@ public: /// context (i.e. the number of TypoExprs created). unsigned NumTypos; - llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs; + MaybeODRUseExprSet SavedMaybeODRUseExprs; /// The lambdas that are present within this context, if it /// is indeed an unevaluated context. Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=357040&r1=357039&r2=357040&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Mar 26 16:21:19 2019 @@ -15690,7 +15690,12 @@ ExprResult Sema::ActOnConstantExpression } void Sema::CleanupVarDeclMarking() { - for (Expr *E : MaybeODRUseExprs) { + // Iterate through a local copy in case MarkVarDeclODRUsed makes a recursive + // call. + MaybeODRUseExprSet LocalMaybeODRUseExprs; + std::swap(LocalMaybeODRUseExprs, MaybeODRUseExprs); + + for (Expr *E : LocalMaybeODRUseExprs) { VarDecl *Var; SourceLocation Loc; if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) { @@ -15707,10 +15712,10 @@ void Sema::CleanupVarDeclMarking() { /*MaxFunctionScopeIndex Pointer*/ nullptr); } - MaybeODRUseExprs.clear(); + assert(MaybeODRUseExprs.empty() && + "MarkVarDeclODRUsed failed to cleanup MaybeODRUseExprs?"); } - static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc, VarDecl *Var, Expr *E) { assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) && Modified: cfe/trunk/test/SemaCXX/blocks.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/blocks.cpp?rev=357040&r1=357039&r2=357040&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/blocks.cpp (original) +++ cfe/trunk/test/SemaCXX/blocks.cpp Tue Mar 26 16:21:19 2019 @@ -145,3 +145,11 @@ namespace test6c { A::foo(); }); } } + +namespace test7 { +struct S {}; +void f() { + constexpr S s; + auto some_block = ^{ (void)s; }; +} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits