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