Defer capture initialization for captured regions until after we've left
the captured region scope.
This removes a case where we would build expressions (and mark
declarations odr-used) in the wrong scope.
Remove the now-unused 'capture initializer' field on sema::Capture
(except for 'this' captures, which still need to be cleaned up).
No functionality change intended (except that we now very slightly more
precisely determine whether we need to use a capture or not when another
captured region encloses an OpenMP captured region).
llvm-svn: 362179
diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp
index 357e257a..7a9a801b 100644
--- a/clang/lib/Sema/SemaStmt.cpp
+++ b/clang/lib/Sema/SemaStmt.cpp
@@ -4223,7 +4223,7 @@
return RD;
}
-static void
+static bool
buildCapturedStmtCaptureList(Sema &S, CapturedRegionScopeInfo *RSI,
SmallVectorImpl<CapturedStmt::Capture> &Captures,
SmallVectorImpl<Expr *> &CaptureInits) {
@@ -4237,7 +4237,7 @@
if (Cap.isThisCapture()) {
Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
CapturedStmt::VCK_This));
- CaptureInits.push_back(Cap.getInitExpr());
+ CaptureInits.push_back(Cap.getThisInitExpr());
continue;
} else if (Cap.isVLATypeCapture()) {
Captures.push_back(
@@ -4248,13 +4248,25 @@
if (S.getLangOpts().OpenMP && RSI->CapRegionKind == CR_OpenMP)
S.setOpenMPCaptureKind(Field, Cap.getVariable(), RSI->OpenMPLevel);
- Captures.push_back(CapturedStmt::Capture(Cap.getLocation(),
+
+ VarDecl *Var = Cap.getVariable();
+ SourceLocation Loc = Cap.getLocation();
+
+ // FIXME: For a non-reference capture, we need to build an expression to
+ // perform a copy here!
+ ExprResult Init = S.BuildDeclarationNameExpr(
+ CXXScopeSpec(), DeclarationNameInfo(Var->getDeclName(), Loc), Var);
+ if (Init.isInvalid())
+ return true;
+
+ Captures.push_back(CapturedStmt::Capture(Loc,
Cap.isReferenceCapture()
? CapturedStmt::VCK_ByRef
: CapturedStmt::VCK_ByCopy,
- Cap.getVariable()));
- CaptureInits.push_back(Cap.getInitExpr());
+ Var));
+ CaptureInits.push_back(Init.get());
}
+ return false;
}
void Sema::ActOnCapturedRegionStart(SourceLocation Loc, Scope *CurScope,
@@ -4347,25 +4359,31 @@
void Sema::ActOnCapturedRegionError() {
DiscardCleanupsInEvaluationContext();
PopExpressionEvaluationContext();
+ PopDeclContext();
+ PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo();
+ CapturedRegionScopeInfo *RSI = cast<CapturedRegionScopeInfo>(ScopeRAII.get());
- CapturedRegionScopeInfo *RSI = getCurCapturedRegion();
RecordDecl *Record = RSI->TheRecordDecl;
Record->setInvalidDecl();
SmallVector<Decl*, 4> Fields(Record->fields());
ActOnFields(/*Scope=*/nullptr, Record->getLocation(), Record, Fields,
SourceLocation(), SourceLocation(), ParsedAttributesView());
-
- PopDeclContext();
- PopFunctionScopeInfo();
}
StmtResult Sema::ActOnCapturedRegionEnd(Stmt *S) {
- CapturedRegionScopeInfo *RSI = getCurCapturedRegion();
+ // Leave the captured scope before we start creating captures in the
+ // enclosing scope.
+ DiscardCleanupsInEvaluationContext();
+ PopExpressionEvaluationContext();
+ PopDeclContext();
+ PoppedFunctionScopePtr ScopeRAII = PopFunctionScopeInfo();
+ CapturedRegionScopeInfo *RSI = cast<CapturedRegionScopeInfo>(ScopeRAII.get());
SmallVector<CapturedStmt::Capture, 4> Captures;
SmallVector<Expr *, 4> CaptureInits;
- buildCapturedStmtCaptureList(*this, RSI, Captures, CaptureInits);
+ if (buildCapturedStmtCaptureList(*this, RSI, Captures, CaptureInits))
+ return StmtError();
CapturedDecl *CD = RSI->TheCapturedDecl;
RecordDecl *RD = RSI->TheRecordDecl;
@@ -4377,11 +4395,5 @@
CD->setBody(Res->getCapturedStmt());
RD->completeDefinition();
- DiscardCleanupsInEvaluationContext();
- PopExpressionEvaluationContext();
-
- PopDeclContext();
- PopFunctionScopeInfo();
-
return Res;
}