Skip to content
This repository was archived by the owner on Mar 28, 2020. It is now read-only.

Commit c72b1b5

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@357040 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 9b51993 commit c72b1b5

File tree

3 files changed

+24
-11
lines changed

3 files changed

+24
-11
lines changed

include/clang/Sema/Sema.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -536,13 +536,13 @@ class Sema {
536536
/// element type here is ExprWithCleanups::Object.
537537
SmallVector<BlockDecl*, 8> ExprCleanupObjects;
538538

539-
/// Store a list of either DeclRefExprs or MemberExprs
540-
/// that contain a reference to a variable (constant) that may or may not
541-
/// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue
542-
/// and discarded value conversions have been applied to all subexpressions
543-
/// of the enclosing full expression. This is cleared at the end of each
544-
/// full expression.
545-
llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs;
539+
/// Store a set of either DeclRefExprs or MemberExprs that contain a reference
540+
/// to a variable (constant) that may or may not be odr-used in this Expr, and
541+
/// we won't know until all lvalue-to-rvalue and discarded value conversions
542+
/// have been applied to all subexpressions of the enclosing full expression.
543+
/// This is cleared at the end of each full expression.
544+
using MaybeODRUseExprSet = llvm::SmallPtrSet<Expr *, 2>;
545+
MaybeODRUseExprSet MaybeODRUseExprs;
546546

547547
std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope;
548548

@@ -982,7 +982,7 @@ class Sema {
982982
/// context (i.e. the number of TypoExprs created).
983983
unsigned NumTypos;
984984

985-
llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs;
985+
MaybeODRUseExprSet SavedMaybeODRUseExprs;
986986

987987
/// The lambdas that are present within this context, if it
988988
/// is indeed an unevaluated context.

lib/Sema/SemaExpr.cpp

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15604,7 +15604,12 @@ ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
1560415604
}
1560515605

1560615606
void Sema::CleanupVarDeclMarking() {
15607-
for (Expr *E : MaybeODRUseExprs) {
15607+
// Iterate through a local copy in case MarkVarDeclODRUsed makes a recursive
15608+
// call.
15609+
MaybeODRUseExprSet LocalMaybeODRUseExprs;
15610+
std::swap(LocalMaybeODRUseExprs, MaybeODRUseExprs);
15611+
15612+
for (Expr *E : LocalMaybeODRUseExprs) {
1560815613
VarDecl *Var;
1560915614
SourceLocation Loc;
1561015615
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
@@ -15621,10 +15626,10 @@ void Sema::CleanupVarDeclMarking() {
1562115626
/*MaxFunctionScopeIndex Pointer*/ nullptr);
1562215627
}
1562315628

15624-
MaybeODRUseExprs.clear();
15629+
assert(MaybeODRUseExprs.empty() &&
15630+
"MarkVarDeclODRUsed failed to cleanup MaybeODRUseExprs?");
1562515631
}
1562615632

15627-
1562815633
static void DoMarkVarDeclReferenced(Sema &SemaRef, SourceLocation Loc,
1562915634
VarDecl *Var, Expr *E) {
1563015635
assert((!E || isa<DeclRefExpr>(E) || isa<MemberExpr>(E)) &&

test/SemaCXX/blocks.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,3 +145,11 @@ namespace test6c {
145145
A::foo(); });
146146
}
147147
}
148+
149+
namespace test7 {
150+
struct S {};
151+
void f() {
152+
constexpr S s;
153+
auto some_block = ^{ (void)s; };
154+
}
155+
}

0 commit comments

Comments
 (0)