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/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 0646499..df8a526 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -940,12 +940,10 @@
   RecordDecl::field_iterator Field = field_begin();
   for (LambdaExpr::Capture *C = Lambda.Captures, *CEnd = C + Lambda.NumCaptures;
        C != CEnd; ++C, ++Field) {
-    if (C->capturesThis()) {
+    if (C->capturesThis())
       ThisCapture = *Field;
-      continue;
-    }
-
-    Captures[C->getCapturedVar()] = *Field;
+    else if (C->capturesVariable())
+      Captures[C->getCapturedVar()] = *Field;
   }
 }
 
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index 402d7b5..59e780a 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -811,7 +811,7 @@
 LambdaExpr::Capture::Capture(SourceLocation Loc, bool Implicit,
                              LambdaCaptureKind Kind, VarDecl *Var,
                              SourceLocation EllipsisLoc)
-  : VarAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
+  : DeclAndBits(Var, 0), Loc(Loc), EllipsisLoc(EllipsisLoc)
 {
   unsigned Bits = 0;
   if (Implicit)
@@ -828,15 +828,27 @@
   case LCK_ByRef:
     assert(Var && "capture must have a variable!");
     break;
+
+  case LCK_Init:
+    llvm_unreachable("don't use this constructor for an init-capture");
   }
-  VarAndBits.setInt(Bits);
+  DeclAndBits.setInt(Bits);
 }
 
+LambdaExpr::Capture::Capture(FieldDecl *Field)
+    : DeclAndBits(Field,
+                  Field->getType()->isReferenceType() ? 0 : Capture_ByCopy),
+      Loc(Field->getLocation()), EllipsisLoc() {}
+
 LambdaCaptureKind LambdaExpr::Capture::getCaptureKind() const {
-  if (capturesThis())
+  Decl *D = DeclAndBits.getPointer();
+  if (!D)
     return LCK_This;
 
-  return (VarAndBits.getInt() & Capture_ByCopy)? LCK_ByCopy : LCK_ByRef;
+  if (isa<FieldDecl>(D))
+    return LCK_Init;
+
+  return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef;
 }
 
 LambdaExpr::LambdaExpr(QualType T, 
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index 5b29c07..7e85880 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -1128,7 +1128,7 @@
 bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
   for (const_capture_iterator I = capture_begin(),
                               E = capture_end(); I != E; ++I) {
-    if (I->capturesThis())
+    if (!I->capturesVariable())
       continue;
 
     // This does not handle variable redeclarations. This should be
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 9203dc1..2edb078 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -1387,6 +1387,13 @@
         OS << '=';
       OS << C->getCapturedVar()->getName();
       break;
+
+    case LCK_Init:
+      if (C->getInitCaptureField()->getType()->isReferenceType())
+        OS << '&';
+      OS << C->getInitCaptureField()->getName();
+      PrintExpr(Node->getInitCaptureInit(C));
+      break;
     }
   }
   OS << ']';
diff --git a/lib/AST/StmtProfile.cpp b/lib/AST/StmtProfile.cpp
index 8ade242..4a3448c 100644
--- a/lib/AST/StmtProfile.cpp
+++ b/lib/AST/StmtProfile.cpp
@@ -822,9 +822,17 @@
                                  CEnd = S->explicit_capture_end();
        C != CEnd; ++C) {
     ID.AddInteger(C->getCaptureKind());
-    if (C->capturesVariable()) {
+    switch (C->getCaptureKind()) {
+    case LCK_This:
+      break;
+    case LCK_ByRef:
+    case LCK_ByCopy:
       VisitDecl(C->getCapturedVar());
       ID.AddBoolean(C->isPackExpansion());
+      break;
+    case LCK_Init:
+      VisitDecl(C->getInitCaptureField());
+      break;
     }
   }
   // Note: If we actually needed to be able to match lambda