r357040 - [Sema] Fix an assert when a block captures a constexpr local

Erik Pilkington via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 26 16:21:20 PDT 2019


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; };
+}
+}




More information about the cfe-commits mailing list