forked from OSchip/llvm-project
[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 llvm-svn: 357040
This commit is contained in:
parent
e6eef49f05
commit
14f6d1527c
|
@ -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.
|
||||
|
|
|
@ -15690,7 +15690,12 @@ ExprResult Sema::ActOnConstantExpression(ExprResult Res) {
|
|||
}
|
||||
|
||||
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)) &&
|
||||
|
|
|
@ -145,3 +145,11 @@ namespace test6c {
|
|||
A::foo(); });
|
||||
}
|
||||
}
|
||||
|
||||
namespace test7 {
|
||||
struct S {};
|
||||
void f() {
|
||||
constexpr S s;
|
||||
auto some_block = ^{ (void)s; };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue