First pass of semantic analysis for init-captures: check the initializer, build
a FieldDecl from it, and propagate both into the closure type and the
LambdaExpr.

You can't do much useful with them yet -- you can't use them within the body
of the lambda, because we don't have a representation for "the this of the
lambda, not the this of the enclosing context". We also don't have support or a
representation for a nested capture of an init-capture yet, which was intended
to work despite not being allowed by the current standard wording.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181985 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp
index 4e11bb4..d647be3 100644
--- a/lib/Sema/SemaLambda.cpp
+++ b/lib/Sema/SemaLambda.cpp
@@ -18,6 +18,7 @@
 #include "clang/Sema/Scope.h"
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaInternal.h"
+#include "TypeLocBuilder.h"
 using namespace clang;
 using namespace sema;
 
@@ -429,6 +430,88 @@
   }
 }
 
+FieldDecl *Sema::checkInitCapture(SourceLocation Loc, bool ByRef,
+                                  IdentifierInfo *Id, Expr *InitExpr) {
+  LambdaScopeInfo *LSI = getCurLambda();
+
+  // 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;"
+  QualType DeductType = Context.getAutoDeductType();
+  TypeLocBuilder TLB;
+  TLB.pushTypeSpec(DeductType).setNameLoc(Loc);
+  if (ByRef) {
+    DeductType = BuildReferenceType(DeductType, true, Loc, Id);
+    assert(!DeductType.isNull() && "can't build reference to auto");
+    TLB.push<ReferenceTypeLoc>(DeductType).setSigilLoc(Loc);
+  }
+
+  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(TLB.getTemporaryTypeLoc(DeductType),
+                     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;
+
+  //   [...] 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, TLB.getTypeSourceInfo(Context, DeductType), LSI->Lambda,
+      Loc, /*Mutable*/ false, /*BitWidth*/ 0, ICIS_NoInit,
+      Loc, AS_public, /*PrevDecl*/ 0, /*Declarator*/ 0);
+  LSI->Lambda->addDecl(NewFD);
+
+  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());
+    }
+  }
+
+  return NewFD;
+}
+
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
                                         Declarator &ParamInfo,
                                         Scope *CurScope) {
@@ -514,7 +597,10 @@
     = enterLambdaScope(Method, Intro.Range, Intro.Default, ExplicitParams,
                        ExplicitResultType,
                        !Method->isConst());
- 
+
+  // Distinct capture names, for diagnostics.
+  llvm::SmallSet<IdentifierInfo*, 8> CaptureNames;
+
   // Handle explicit captures.
   SourceLocation PrevCaptureLoc
     = Intro.Default == LCD_None? Intro.Range.getBegin() : Intro.DefaultLoc;
@@ -559,16 +645,32 @@
       continue;
     }
 
-    // FIXME: C++1y [expr.prim.lambda]p11
+    assert(C->Id && "missing identifier for capture");
+
     if (C->Init.isInvalid())
       continue;
     if (C->Init.isUsable()) {
-      Diag(C->Loc, diag::err_lambda_init_capture_unsupported);
+      // 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;
+
+      if (C->Init.get()->containsUnexpandedParameterPack())
+        ContainsUnexpandedParameterPack = true;
+
+      FieldDecl *NewFD = 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;
     }
 
-    assert(C->Id && "missing identifier for capture");
-
     // 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 &.
@@ -586,6 +688,9 @@
       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);
@@ -599,14 +704,27 @@
         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); each such lookup shall find a 
-    //   variable with automatic storage duration declared in the reaching 
-    //   scope of the local lambda expression.
-    // 
-    // Note that the 'reaching scope' check happens in tryCaptureVariable().
     VarDecl *Var = R.getAsSingle<VarDecl>();
+
+    // 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)) {
+      if (Var && LSI->isCaptured(Var)) {
+        Diag(C->Loc, diag::err_capture_more_than_once)
+          << C->Id << SourceRange(LSI->getCapture(Var).getLocation())
+          << FixItHint::CreateRemoval(
+               SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
+      } else
+        // Previous capture was an init-capture: no fixit.
+        Diag(C->Loc, diag::err_capture_more_than_once) << C->Id;
+      continue;
+    }
+
+    // C++11 [expr.prim.lambda]p10:
+    //   [...] each such lookup shall find a variable with automatic storage
+    //   duration declared in the reaching scope of the local lambda expression.
+    // Note that the 'reaching scope' check happens in tryCaptureVariable().
     if (!Var) {
       Diag(C->Loc, diag::err_capture_does_not_name_variable) << C->Id;
       continue;
@@ -622,18 +740,6 @@
       continue;
     }
 
-    // C++11 [expr.prim.lambda]p8:
-    //   An identifier or this shall not appear more than once in a 
-    //   lambda-capture.
-    if (LSI->isCaptured(Var)) {
-      Diag(C->Loc, diag::err_capture_more_than_once) 
-        << C->Id
-        << SourceRange(LSI->getCapture(Var).getLocation())
-        << FixItHint::CreateRemoval(
-             SourceRange(PP.getLocForEndOfToken(PrevCaptureLoc), C->Loc));
-      continue;
-    }
-
     // C++11 [expr.prim.lambda]p23:
     //   A capture followed by an ellipsis is a pack expansion (14.5.3).
     SourceLocation EllipsisLoc;
@@ -853,11 +959,17 @@
         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, 
                                              Kind, Var, From.getEllipsisLoc()));
-      CaptureInits.push_back(From.getCopyExpr());
+      CaptureInits.push_back(From.getInitExpr());
     }
 
     switch (LSI->ImpCaptureStyle) {