Per latest drafting, switch to implementing init-captures as if by declaring
and capturing a variable declaration, and complete the implementation of them.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191605 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index ccfbeeb..b15208b 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -7971,14 +7971,17 @@
         // It isn't possible to write this directly, but it is possible to
         // end up in this situation with "auto x(some_pack...);"
         Diag(CXXDirectInit->getLocStart(),
-             diag::err_auto_var_init_no_expression)
+             VDecl->isInitCapture() ? diag::err_init_capture_no_expression
+                                    : diag::err_auto_var_init_no_expression)
           << VDecl->getDeclName() << VDecl->getType()
           << VDecl->getSourceRange();
         RealDecl->setInvalidDecl();
         return;
       } else if (CXXDirectInit->getNumExprs() > 1) {
         Diag(CXXDirectInit->getExpr(1)->getLocStart(),
-             diag::err_auto_var_init_multiple_expressions)
+             VDecl->isInitCapture()
+                 ? diag::err_init_capture_multiple_expressions
+                 : diag::err_auto_var_init_multiple_expressions)
           << VDecl->getDeclName() << VDecl->getType()
           << VDecl->getSourceRange();
         RealDecl->setInvalidDecl();
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 569bfdf..08048d5 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -494,13 +494,12 @@
   }
 }
 
-FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
-                                  IdentifierInfo *Id, Expr *InitExpr) {
-  LambdaScopeInfo *LSI = getCurLambda();
-
+VarDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
+                                IdentifierInfo *Id, Expr *Init) {
   // C++1y [expr.prim.lambda]p11:
-  //   The type of [the] member corresponds to the type of a hypothetical
-  //   variable declaration of the form "auto init-capture;"
+  //   An init-capture behaves as if it declares and explicitly captures
+  //   a variable of the form
+  //     "auto init-capture;"
   QualType DeductType = Context.getAutoDeductType();
   TypeLocBuilder TLB;
   TLB.pushTypeSpec(DeductType).setNameLoc(Loc);
@@ -511,69 +510,38 @@
   }
   TypeSourceInfo *TSI = TLB.getTypeSourceInfo(Context, DeductType);
 
-  InitializationKind InitKind = InitializationKind::CreateDefault(Loc);
-  Expr *Init = InitExpr;
-  if (ParenListExpr *Parens = dyn_cast<ParenListExpr>(Init)) {
-    if (Parens->getNumExprs() == 1) {
-      Init = Parens->getExpr(0);
-      InitKind = InitializationKind::CreateDirect(
-          Loc, Parens->getLParenLoc(), Parens->getRParenLoc());
-    } else {
-      // C++1y [dcl.spec.auto]p3:
-      //   In an initializer of the form ( expression-list ), the
-      //   expression-list shall be a single assignment-expression.
-      if (Parens->getNumExprs() == 0)
-        Diag(Parens->getLocStart(), diag::err_init_capture_no_expression)
-          << Id;
-      else if (Parens->getNumExprs() > 1)
-        Diag(Parens->getExpr(1)->getLocStart(),
-             diag::err_init_capture_multiple_expressions)
-          << Id;
-      return 0;
-    }
-  } else if (isa<InitListExpr>(Init))
-    // We do not need to distinguish between direct-list-initialization
-    // and copy-list-initialization here, because we will always deduce
-    // std::initializer_list<T>, and direct- and copy-list-initialization
-    // always behave the same for such a type.
-    // FIXME: We should model whether an '=' was present.
-    InitKind = InitializationKind::CreateDirectList(Loc);
-  else
-    InitKind = InitializationKind::CreateCopy(Loc, Loc);
-  QualType DeducedType;
-  if (DeduceAutoType(TSI, Init, DeducedType) == DAR_Failed) {
-    if (isa<InitListExpr>(Init))
-      Diag(Loc, diag::err_init_capture_deduction_failure_from_init_list)
-          << Id << Init->getSourceRange();
-    else
-      Diag(Loc, diag::err_init_capture_deduction_failure)
-          << Id << Init->getType() << Init->getSourceRange();
-  }
-  if (DeducedType.isNull())
-    return 0;
+  // Create a dummy variable representing the init-capture. This is not actually
+  // used as a variable, and only exists as a way to name and refer to the
+  // init-capture.
+  // FIXME: Pass in separate source locations for '&' and identifier.
+  VarDecl *NewVD = VarDecl::Create(Context, CurContext->getLexicalParent(), Loc,
+                                   Loc, Id, TSI->getType(), TSI, SC_Auto);
+  NewVD->setInitCapture(true);
+  NewVD->setReferenced(true);
+  NewVD->markUsed(Context);
 
-  //   [...] a non-static data member named by the identifier is declared in
-  //   the closure type. This member is not a bit-field and not mutable.
-  // Core issue: the member is (probably...) public.
-  FieldDecl *NewFD = CheckFieldDecl(
-      Id, DeducedType, TSI, LSI->Lambda,
-      Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
-      Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
-  LSI->Lambda->addDecl(NewFD);
+  // We do not need to distinguish between direct-list-initialization
+  // and copy-list-initialization here, because we will always deduce
+  // std::initializer_list<T>, and direct- and copy-list-initialization
+  // always behave the same for such a type.
+  // FIXME: We should model whether an '=' was present.
+  bool DirectInit = isa<ParenListExpr>(Init) || isa<InitListExpr>(Init);
+  AddInitializerToDecl(NewVD, Init, DirectInit, /*ContainsAuto*/true);
+  return NewVD;
+}
 
-  if (CurContext->isDependentContext()) {
-    LSI->addInitCapture(NewFD, InitExpr);
-  } else {
-    InitializedEntity Entity = InitializedEntity::InitializeMember(NewFD);
-    InitializationSequence InitSeq(*this, Entity, InitKind, Init);
-    if (!InitSeq.Diagnose(*this, Entity, InitKind, Init)) {
-      ExprResult InitResult = InitSeq.Perform(*this, Entity, InitKind, Init);
-      if (!InitResult.isInvalid())
-        LSI->addInitCapture(NewFD, InitResult.take());
-    }
-  }
+FieldDecl *Sema::buildInitCaptureField(LambdaScopeInfo *LSI, VarDecl *Var) {
+  FieldDecl *Field = FieldDecl::Create(
+      Context, LSI->Lambda, Var->getLocation(), Var->getLocation(),
+      0, Var->getType(), Var->getTypeSourceInfo(), 0, false, ICIS_NoInit);
+  Field->setImplicit(true);
+  Field->setAccess(AS_private);
+  LSI->Lambda->addDecl(Field);
 
-  return NewFD;
+  LSI->addCapture(Var, /*isBlock*/false, Var->getType()->isReferenceType(),
+                  /*isNested*/false, Var->getLocation(), SourceLocation(),
+                  Var->getType(), Var->getInit());
+  return Field;
 }
 
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
@@ -732,62 +700,56 @@
 
     if (C->Init.isInvalid())
       continue;
-    if (C->Init.isUsable()) {
-      // C++11 [expr.prim.lambda]p8:
-      //   An identifier or this shall not appear more than once in a
-      //   lambda-capture.
-      if (!CaptureNames.insert(C->Id))
-        Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
 
+    VarDecl *Var;
+    if (C->Init.isUsable()) {
       if (C->Init.get()->containsUnexpandedParameterPack())
         ContainsUnexpandedParameterPack = true;
 
-      FieldDecl *NewFD = checkInitCapture(C->Loc, C->Kind == LCK_ByRef,
-                                          C->Id, C->Init.take());
+      Var = checkInitCapture(C->Loc, C->Kind == LCK_ByRef,
+                             C->Id, C->Init.take());
       // C++1y [expr.prim.lambda]p11:
-      //   Within the lambda-expression's lambda-declarator and
-      //   compound-statement, the identifier in the init-capture
-      //   hides any declaration of the same name in scopes enclosing
-      //   the lambda-expression.
-      if (NewFD)
-        PushOnScopeChains(NewFD, CurScope, false);
-      continue;
-    }
-
-    // C++11 [expr.prim.lambda]p8:
-    //   If a lambda-capture includes a capture-default that is &, the 
-    //   identifiers in the lambda-capture shall not be preceded by &.
-    //   If a lambda-capture includes a capture-default that is =, [...]
-    //   each identifier it contains shall be preceded by &.
-    if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
-      Diag(C->Loc, diag::err_reference_capture_with_reference_default)
-        << FixItHint::CreateRemoval(
-             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
-      continue;
-    } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
-      Diag(C->Loc, diag::err_copy_capture_with_copy_default)
-        << FixItHint::CreateRemoval(
-             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
-      continue;
-    }
-
-    // C++11 [expr.prim.lambda]p10:
-    //   The identifiers in a capture-list are looked up using the usual
-    //   rules for unqualified name lookup (3.4.1)
-    DeclarationNameInfo Name(C->Id, C->Loc);
-    LookupResult R(*this, Name, LookupOrdinaryName);
-    LookupName(R, CurScope);
-    if (R.isAmbiguous())
-      continue;
-    if (R.empty()) {
-      // FIXME: Disable corrections that would add qualification?
-      CXXScopeSpec ScopeSpec;
-      DeclFilterCCC<VarDecl> Validator;
-      if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+      //   An init-capture behaves as if it declares and explicitly
+      //   captures a variable [...] whose declarative region is the
+      //   lambda-expression's compound-statement
+      if (Var)
+        PushOnScopeChains(Var, CurScope, false);
+    } else {
+      // C++11 [expr.prim.lambda]p8:
+      //   If a lambda-capture includes a capture-default that is &, the 
+      //   identifiers in the lambda-capture shall not be preceded by &.
+      //   If a lambda-capture includes a capture-default that is =, [...]
+      //   each identifier it contains shall be preceded by &.
+      if (C->Kind == LCK_ByRef && Intro.Default == LCD_ByRef) {
+        Diag(C->Loc, diag::err_reference_capture_with_reference_default)
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
         continue;
-    }
+      } else if (C->Kind == LCK_ByCopy && Intro.Default == LCD_ByCopy) {
+        Diag(C->Loc, diag::err_copy_capture_with_copy_default)
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+        continue;
+      }
 
-    VarDecl *Var = R.getAsSingle<VarDecl>();
+      // C++11 [expr.prim.lambda]p10:
+      //   The identifiers in a capture-list are looked up using the usual
+      //   rules for unqualified name lookup (3.4.1)
+      DeclarationNameInfo Name(C->Id, C->Loc);
+      LookupResult R(*this, Name, LookupOrdinaryName);
+      LookupName(R, CurScope);
+      if (R.isAmbiguous())
+        continue;
+      if (R.empty()) {
+        // FIXME: Disable corrections that would add qualification?
+        CXXScopeSpec ScopeSpec;
+        DeclFilterCCC<VarDecl> Validator;
+        if (DiagnoseEmptyLookup(CurScope, ScopeSpec, R, Validator))
+          continue;
+      }
+
+      Var = R.getAsSingle<VarDecl>();
+    }
 
     // C++11 [expr.prim.lambda]p8:
     //   An identifier or this shall not appear more than once in a
@@ -799,7 +761,8 @@
           << FixItHint::CreateRemoval(
                SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
       } else
-        // Previous capture was an init-capture: no fixit.
+        // Previous capture captured something different (one or both was
+        // an init-cpature): no fixit.
         Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
       continue;
     }
@@ -838,10 +801,14 @@
     } else if (Var->isParameterPack()) {
       ContainsUnexpandedParameterPack = true;
     }
-    
-    TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
-                                                 TryCapture_ExplicitByVal;
-    tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+
+    if (C->Init.isUsable()) {
+      buildInitCaptureField(LSI, Var);
+    } else {
+      TryCaptureKind Kind = C->Kind == LCK_ByRef ? TryCapture_ExplicitByRef :
+                                                   TryCapture_ExplicitByVal;
+      tryCaptureVariable(Var, C->Loc, Kind, EllipsisLoc);
+    }
   }
   finishLambdaExplicitCaptures(LSI);
 
@@ -1042,12 +1009,6 @@
         continue;
       }
 
-      if (From.isInitCapture()) {
-        Captures.push_back(LambdaExpr::Capture(From.getInitCaptureField()));
-        CaptureInits.push_back(From.getInitExpr());
-        continue;
-      }
-
       VarDecl *Var = From.getVariable();
       LambdaCaptureKind Kind = From.isCopyCapture()? LCK_ByCopy : LCK_ByRef;
       Captures.push_back(LambdaExpr::Capture(From.getLocation(), IsImplicit, 
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 5510bc2..b71aafe 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3928,10 +3928,14 @@
 void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
   if (isa<InitListExpr>(Init))
     Diag(VDecl->getLocation(),
-         diag::err_auto_var_deduction_failure_from_init_list)
+         VDecl->isInitCapture()
+             ? diag::err_init_capture_deduction_failure_from_init_list
+             : diag::err_auto_var_deduction_failure_from_init_list)
       << VDecl->getDeclName() << VDecl->getType() << Init->getSourceRange();
   else
-    Diag(VDecl->getLocation(), diag::err_auto_var_deduction_failure)
+    Diag(VDecl->getLocation(),
+         VDecl->isInitCapture() ? diag::err_init_capture_deduction_failure
+                                : diag::err_auto_var_deduction_failure)
       << VDecl->getDeclName() << VDecl->getType() << Init->getType()
       << Init->getSourceRange();
 }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 8f4c009..8d384b9 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -3369,6 +3369,7 @@
   NewVar->setInitStyle(OldVar->getInitStyle());
   NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
   NewVar->setConstexpr(OldVar->isConstexpr());
+  NewVar->setInitCapture(OldVar->isInitCapture());
   NewVar->setPreviousDeclInSameBlockScope(
       OldVar->isPreviousDeclInSameBlockScope());
   NewVar->setAccess(OldVar->getAccess());
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 6559ded..5b019a9 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -8313,7 +8313,9 @@
     if (!C->isInitCapture())
       continue;
     InitCaptureExprs[C - E->capture_begin()] =
-        getDerived().TransformExpr(E->getInitCaptureInit(C));
+        getDerived().TransformInitializer(
+            C->getCapturedVar()->getInit(),
+            C->getCapturedVar()->getInitStyle() == VarDecl::CallInit);
   }
 
   // Introduce the context of the call operator.
@@ -8353,14 +8355,15 @@
         Invalid = true;
         continue;
       }
-      FieldDecl *OldFD = C->getInitCaptureField();
-      FieldDecl *NewFD = getSema().checkInitCapture(
-          C->getLocation(), OldFD->getType()->isReferenceType(),
-          OldFD->getIdentifier(), Init.take());
-      if (!NewFD)
+      VarDecl *OldVD = C->getCapturedVar();
+      VarDecl *NewVD = getSema().checkInitCapture(
+          C->getLocation(), OldVD->getType()->isReferenceType(),
+          OldVD->getIdentifier(), Init.take());
+      if (!NewVD)
         Invalid = true;
       else
-        getDerived().transformedLocalDecl(OldFD, NewFD);
+        getDerived().transformedLocalDecl(OldVD, NewVD);
+      getSema().buildInitCaptureField(LSI, NewVD);
       continue;
     }