r191605 - Per latest drafting, switch to implementing init-captures as if by declaring

Richard Smith richard-llvm at metafoo.co.uk
Fri Sep 27 21:02:40 PDT 2013


Author: rsmith
Date: Fri Sep 27 23:02:39 2013
New Revision: 191605

URL: http://llvm.org/viewvc/llvm-project?rev=191605&view=rev
Log:
Per latest drafting, switch to implementing init-captures as if by declaring
and capturing a variable declaration, and complete the implementation of them.

Added:
    cfe/trunk/test/CodeGenCXX/cxx1y-init-captures.cpp
    cfe/trunk/test/PCH/cxx1y-init-captures.cpp
Modified:
    cfe/trunk/include/clang/AST/Decl.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Basic/Lambda.h
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/AST/StmtPrinter.cpp
    cfe/trunk/lib/AST/StmtProfile.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
    cfe/trunk/test/Analysis/lambdas.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
    cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp

Modified: cfe/trunk/include/clang/AST/Decl.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Decl.h (original)
+++ cfe/trunk/include/clang/AST/Decl.h Fri Sep 27 23:02:39 2013
@@ -707,12 +707,16 @@ private:
     /// \brief Whether this variable is (C++0x) constexpr.
     unsigned IsConstexpr : 1;
 
+    /// \brief Whether this variable is the implicit variable for a lambda
+    /// init-capture.
+    unsigned IsInitCapture : 1;
+
     /// \brief Whether this local extern variable's previous declaration was
     /// declared in the same block scope. This controls whether we should merge
     /// the type of this declaration with its previous declaration.
     unsigned PreviousDeclInSameBlockScope : 1;
   };
-  enum { NumVarDeclBits = 13 };
+  enum { NumVarDeclBits = 14 };
 
   friend class ASTDeclReader;
   friend class StmtIteratorBase;
@@ -1132,6 +1136,10 @@ public:
   bool isConstexpr() const { return VarDeclBits.IsConstexpr; }
   void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; }
 
+  /// Whether this variable is the implicit variable for a lambda init-capture.
+  bool isInitCapture() const { return VarDeclBits.IsInitCapture; }
+  void setInitCapture(bool IC) { VarDeclBits.IsInitCapture = IC; }
+
   /// Whether this local extern variable declaration's previous declaration
   /// was declared in the same block scope. Only correct in C++.
   bool isPreviousDeclInSameBlockScope() const {

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Fri Sep 27 23:02:39 2013
@@ -1388,9 +1388,6 @@ public:
             LambdaCaptureKind Kind, VarDecl *Var = 0,
             SourceLocation EllipsisLoc = SourceLocation());
 
-    /// \brief Create a new init-capture.
-    Capture(FieldDecl *Field);
-
     /// \brief Determine the kind of capture.
     LambdaCaptureKind getCaptureKind() const;
 
@@ -1404,7 +1401,9 @@ public:
     }
 
     /// \brief Determine whether this is an init-capture.
-    bool isInitCapture() const { return getCaptureKind() == LCK_Init; }
+    bool isInitCapture() const {
+      return capturesVariable() && getCapturedVar()->isInitCapture();
+    }
 
     /// \brief Retrieve the declaration of the local variable being
     /// captured.
@@ -1416,16 +1415,6 @@ public:
       return cast<VarDecl>(DeclAndBits.getPointer());
     }
 
-    /// \brief Retrieve the field for an init-capture.
-    ///
-    /// This works only for an init-capture.  To retrieve the FieldDecl for
-    /// a captured variable or for a capture of \c this, use
-    /// LambdaExpr::getLambdaClass and CXXRecordDecl::getCaptureFields.
-    FieldDecl *getInitCaptureField() const {
-      assert(getCaptureKind() == LCK_Init && "no field for non-init-capture");
-      return cast<FieldDecl>(DeclAndBits.getPointer());
-    }
-
     /// \brief Determine whether this was an implicit capture (not
     /// written between the square brackets introducing the lambda).
     bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; }
@@ -1573,16 +1562,6 @@ public:
     return capture_init_begin() + NumCaptures;    
   }
 
-  /// \brief Retrieve the initializer for an init-capture.
-  Expr *getInitCaptureInit(capture_iterator Capture) {
-    assert(Capture >= explicit_capture_begin() &&
-           Capture <= explicit_capture_end() && Capture->isInitCapture());
-    return capture_init_begin()[Capture - capture_begin()];
-  }
-  const Expr *getInitCaptureInit(capture_iterator Capture) const {
-    return const_cast<LambdaExpr*>(this)->getInitCaptureInit(Capture);
-  }
-
   /// \brief Retrieve the set of index variables used in the capture 
   /// initializer of an array captured by copy.
   ///

Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
+++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Fri Sep 27 23:02:39 2013
@@ -825,7 +825,7 @@ template<typename Derived>
 bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(
     LambdaExpr *LE, const LambdaExpr::Capture *C) {
   if (C->isInitCapture())
-    TRY_TO(TraverseStmt(LE->getInitCaptureInit(C)));
+    TRY_TO(TraverseDecl(C->getCapturedVar()));
   return true;
 }
 

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Sep 27 23:02:39 2013
@@ -5074,7 +5074,7 @@ let CategoryName = "Lambda Issue" in {
   def err_init_capture_multiple_expressions : Error<
     "initializer for lambda capture %0 contains multiple expressions">;
   def err_init_capture_deduction_failure : Error<
-    "cannot deduce type for lambda capture %0 from initializer of type %1">;
+    "cannot deduce type for lambda capture %0 from initializer of type %2">;
   def err_init_capture_deduction_failure_from_init_list : Error<
     "cannot deduce type for lambda capture %0 from initializer list">;
 }

Modified: cfe/trunk/include/clang/Basic/Lambda.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Lambda.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Lambda.h (original)
+++ cfe/trunk/include/clang/Basic/Lambda.h Fri Sep 27 23:02:39 2013
@@ -34,8 +34,7 @@ enum LambdaCaptureDefault {
 enum LambdaCaptureKind {
   LCK_This,   ///< Capturing the \c this pointer
   LCK_ByCopy, ///< Capturing by copy (a.k.a., by value)
-  LCK_ByRef,  ///< Capturing by reference
-  LCK_Init    ///< C++1y "init-capture", value specified by an expression
+  LCK_ByRef   ///< Capturing by reference
 };
 
 } // end namespace clang

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Fri Sep 27 23:02:39 2013
@@ -347,21 +347,17 @@ public:
     // variables of reference type are captured by reference, and other
     // variables are captured by copy.
     enum CaptureKind {
-      Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_ThisOrInit
+      Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_This
     };
 
-    // The variable being captured (if we are not capturing 'this', and whether
-    // this is a nested capture; the expression is only required if we are
-    // capturing ByVal and the variable's type has a non-trivial copy
-    // constructor, or for an initialized capture.
-    typedef llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested;
-
-    // The variable being captured, or the implicitly-generated field for
-    // an init-capture.
-    llvm::PointerUnion<VarAndNested, FieldDecl*> VarOrField;
-
-    // Expression to initialize a field of the given type, and the kind of
-    // capture (if this is a capture and not an init-capture).
+    /// The variable being captured (if we are not capturing 'this') and whether
+    /// this is a nested capture.
+    llvm::PointerIntPair<VarDecl*, 1, bool> VarAndNested;
+
+    /// Expression to initialize a field of the given type, and the kind of
+    /// capture (if this is a capture and not an init-capture). The expression
+    /// is only required if we are capturing ByVal and the variable's type has
+    /// a non-trivial copy constructor.
     llvm::PointerIntPair<Expr*, 2, CaptureKind> InitExprAndCaptureKind;
 
     /// \brief The source location at which the first capture occurred.
@@ -378,7 +374,7 @@ public:
     Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested,
             SourceLocation Loc, SourceLocation EllipsisLoc,
             QualType CaptureType, Expr *Cpy)
-        : VarOrField(VarAndNested(Var, IsNested)),
+        : VarAndNested(Var, IsNested),
           InitExprAndCaptureKind(Cpy, Block ? Cap_Block :
                                       ByRef ? Cap_ByRef : Cap_ByCopy),
           Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {}
@@ -386,23 +382,15 @@ public:
     enum IsThisCapture { ThisCapture };
     Capture(IsThisCapture, bool IsNested, SourceLocation Loc,
             QualType CaptureType, Expr *Cpy)
-        : VarOrField(VarAndNested(0, IsNested)),
-          InitExprAndCaptureKind(Cpy, Cap_ThisOrInit),
+        : VarAndNested(0, IsNested),
+          InitExprAndCaptureKind(Cpy, Cap_This),
           Loc(Loc), EllipsisLoc(), CaptureType(CaptureType) {}
 
-    Capture(FieldDecl *Field, Expr *Init)
-        : VarOrField(Field), InitExprAndCaptureKind(Init, Cap_ThisOrInit),
-          Loc(), EllipsisLoc(), CaptureType() {}
-
     bool isThisCapture() const {
-      return InitExprAndCaptureKind.getInt() == Cap_ThisOrInit &&
-             VarOrField.is<VarAndNested>();
+      return InitExprAndCaptureKind.getInt() == Cap_This;
     }
     bool isVariableCapture() const {
-      return InitExprAndCaptureKind.getInt() != Cap_ThisOrInit;
-    }
-    bool isInitCapture() const {
-      return VarOrField.is<FieldDecl*>();
+      return InitExprAndCaptureKind.getInt() != Cap_This;
     }
     bool isCopyCapture() const {
       return InitExprAndCaptureKind.getInt() == Cap_ByCopy;
@@ -413,13 +401,10 @@ public:
     bool isBlockCapture() const {
       return InitExprAndCaptureKind.getInt() == Cap_Block;
     }
-    bool isNested() { return VarOrField.dyn_cast<VarAndNested>().getInt(); }
+    bool isNested() { return VarAndNested.getInt(); }
 
     VarDecl *getVariable() const {
-      return VarOrField.dyn_cast<VarAndNested>().getPointer();
-    }
-    FieldDecl *getInitCaptureField() const {
-      return VarOrField.dyn_cast<FieldDecl*>();
+      return VarAndNested.getPointer();
     }
     
     /// \brief Retrieve the location at which this variable was captured.
@@ -473,10 +458,6 @@ public:
   void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType,
                       Expr *Cpy);
 
-  void addInitCapture(FieldDecl *Field, Expr *Init) {
-    Captures.push_back(Capture(Field, Init));
-  }
-
   /// \brief Determine whether the C++ 'this' is captured.
   bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; }
   

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Fri Sep 27 23:02:39 2013
@@ -4458,10 +4458,13 @@ public:
                         bool ExplicitResultType,
                         bool Mutable);
 
-  /// \brief Check and build an init-capture with the specified name and
-  /// initializer.
-  FieldDecl *checkInitCapture(SourceLocation Loc, bool ByRef,
-                              IdentifierInfo *Id, Expr *Init);
+  /// \brief Check an init-capture and build the implied variable declaration
+  /// with the specified name and initializer.
+  VarDecl *checkInitCapture(SourceLocation Loc, bool ByRef,
+                            IdentifierInfo *Id, Expr *Init);
+
+  /// \brief Build the implicit field for an init-capture.
+  FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var);
 
   /// \brief Note that we have finished the explicit captures for the
   /// given lambda.

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Fri Sep 27 23:02:39 2013
@@ -992,6 +992,7 @@ void CXXRecordDecl::getCaptureFields(
     else if (C->capturesVariable())
       Captures[C->getCapturedVar()] = *Field;
   }
+  assert(Field == field_end());
 }
 
 TemplateParameterList * 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Fri Sep 27 23:02:39 2013
@@ -905,26 +905,15 @@ LambdaExpr::Capture::Capture(SourceLocat
   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");
   }
   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 {
   Decl *D = DeclAndBits.getPointer();
   if (!D)
     return LCK_This;
 
-  if (isa<FieldDecl>(D))
-    return LCK_Init;
-
   return (DeclAndBits.getInt() & Capture_ByCopy) ? LCK_ByCopy : LCK_ByRef;
 }
 

Modified: cfe/trunk/lib/AST/StmtPrinter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtPrinter.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtPrinter.cpp (original)
+++ cfe/trunk/lib/AST/StmtPrinter.cpp Fri Sep 27 23:02:39 2013
@@ -1460,24 +1460,18 @@ void StmtPrinter::VisitLambdaExpr(Lambda
       break;
 
     case LCK_ByRef:
-      if (Node->getCaptureDefault() != LCD_ByRef)
+      if (Node->getCaptureDefault() != LCD_ByRef || C->isInitCapture())
         OS << '&';
       OS << C->getCapturedVar()->getName();
       break;
 
     case LCK_ByCopy:
-      if (Node->getCaptureDefault() != LCD_ByCopy)
-        OS << '=';
       OS << C->getCapturedVar()->getName();
       break;
-
-    case LCK_Init:
-      if (C->getInitCaptureField()->getType()->isReferenceType())
-        OS << '&';
-      OS << C->getInitCaptureField()->getName();
-      PrintExpr(Node->getInitCaptureInit(C));
-      break;
     }
+
+    if (C->isInitCapture())
+      PrintExpr(C->getCapturedVar()->getInit());
   }
   OS << ']';
 

Modified: cfe/trunk/lib/AST/StmtProfile.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtProfile.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtProfile.cpp (original)
+++ cfe/trunk/lib/AST/StmtProfile.cpp Fri Sep 27 23:02:39 2013
@@ -881,9 +881,6 @@ StmtProfiler::VisitLambdaExpr(const Lamb
       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

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Sep 27 23:02:39 2013
@@ -7971,14 +7971,17 @@ void Sema::AddInitializerToDecl(Decl *Re
         // 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();

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Fri Sep 27 23:02:39 2013
@@ -494,13 +494,12 @@ void Sema::deduceClosureReturnType(Captu
   }
 }
 
-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 @@ FieldDecl *Sema::checkInitCapture(Source
   }
   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;
-
-  //   [...] 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);
-
-  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());
-    }
-  }
+  // 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);
+
+  // 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;
+}
 
-  return NewFD;
+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);
+
+  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 @@ void Sema::ActOnStartOfLambdaDefinition(
 
     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;
-    }
+      //   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;
+      }
 
-    // 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))
+      // 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;
+      }
 
-    VarDecl *Var = R.getAsSingle<VarDecl>();
+      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 @@ void Sema::ActOnStartOfLambdaDefinition(
           << 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 @@ void Sema::ActOnStartOfLambdaDefinition(
     } 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 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
         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, 

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Sep 27 23:02:39 2013
@@ -3928,10 +3928,14 @@ TypeSourceInfo* Sema::SubstAutoTypeSourc
 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();
 }

Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Fri Sep 27 23:02:39 2013
@@ -3369,6 +3369,7 @@ void Sema::BuildVariableInstantiation(
   NewVar->setInitStyle(OldVar->getInitStyle());
   NewVar->setCXXForRangeDecl(OldVar->isCXXForRangeDecl());
   NewVar->setConstexpr(OldVar->isConstexpr());
+  NewVar->setInitCapture(OldVar->isInitCapture());
   NewVar->setPreviousDeclInSameBlockScope(
       OldVar->isPreviousDeclInSameBlockScope());
   NewVar->setAccess(OldVar->getAccess());

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Fri Sep 27 23:02:39 2013
@@ -8313,7 +8313,9 @@ TreeTransform<Derived>::TransformLambdaS
     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 @@ TreeTransform<Derived>::TransformLambdaS
         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;
     }
 

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Fri Sep 27 23:02:39 2013
@@ -945,6 +945,7 @@ ASTDeclReader::RedeclarableResult ASTDec
   VD->VarDeclBits.CXXForRangeDecl = Record[Idx++];
   VD->VarDeclBits.ARCPseudoStrong = Record[Idx++];
   VD->VarDeclBits.IsConstexpr = Record[Idx++];
+  VD->VarDeclBits.IsInitCapture = Record[Idx++];
   VD->VarDeclBits.PreviousDeclInSameBlockScope = Record[Idx++];
   Linkage VarLinkage = Linkage(Record[Idx++]);
   VD->setCachedLinkage(VarLinkage);
@@ -1223,17 +1224,12 @@ void ASTDeclReader::ReadCXXDefinitionDat
         *ToCapture++ = Capture(Loc, IsImplicit, Kind, 0, SourceLocation());
         break;
       case LCK_ByCopy:
-      case LCK_ByRef: {
+      case LCK_ByRef:
         VarDecl *Var = ReadDeclAs<VarDecl>(Record, Idx);
         SourceLocation EllipsisLoc = ReadSourceLocation(Record, Idx);
         *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc);
         break;
       }
-      case LCK_Init:
-        FieldDecl *Field = ReadDeclAs<FieldDecl>(Record, Idx);
-        *ToCapture++ = Capture(Field);
-        break;
-      }
     }
   }
 }

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Fri Sep 27 23:02:39 2013
@@ -5144,7 +5144,7 @@ void ASTWriter::AddCXXDefinitionData(con
       case LCK_This:
         break;
       case LCK_ByCopy:
-      case LCK_ByRef: {
+      case LCK_ByRef:
         VarDecl *Var =
             Capture.capturesVariable() ? Capture.getCapturedVar() : 0;
         AddDeclRef(Var, Record);
@@ -5153,11 +5153,6 @@ void ASTWriter::AddCXXDefinitionData(con
                           Record);
         break;
       }
-      case LCK_Init:
-        FieldDecl *Field = Capture.getInitCaptureField();
-        AddDeclRef(Field, Record);
-        break;
-      }
     }
   }
 }

Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Fri Sep 27 23:02:39 2013
@@ -705,6 +705,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl
   Record.push_back(D->isCXXForRangeDecl());
   Record.push_back(D->isARCPseudoStrong());
   Record.push_back(D->isConstexpr());
+  Record.push_back(D->isInitCapture());
   Record.push_back(D->isPreviousDeclInSameBlockScope());
   Record.push_back(D->getLinkageInternal());
 
@@ -747,6 +748,7 @@ void ASTDeclWriter::VisitVarDecl(VarDecl
       !isa<ParmVarDecl>(D) &&
       !isa<VarTemplateSpecializationDecl>(D) &&
       !D->isConstexpr() &&
+      !D->isInitCapture() &&
       !D->isPreviousDeclInSameBlockScope() &&
       !D->getMemberSpecializationInfo())
     AbbrevToUse = Writer.getDeclVarAbbrev();
@@ -1633,6 +1635,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs()
   Abv->Add(BitCodeAbbrevOp(0));                       // isCXXForRangeDecl
   Abv->Add(BitCodeAbbrevOp(0));                       // isARCPseudoStrong
   Abv->Add(BitCodeAbbrevOp(0));                       // isConstexpr
+  Abv->Add(BitCodeAbbrevOp(0));                       // isInitCapture
   Abv->Add(BitCodeAbbrevOp(0));                       // isPrevDeclInSameScope
   Abv->Add(BitCodeAbbrevOp(0));                       // Linkage
   Abv->Add(BitCodeAbbrevOp(0));                       // HasInit
@@ -1713,6 +1716,7 @@ void ASTWriter::WriteDeclsBlockAbbrevs()
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong
   Abv->Add(BitCodeAbbrevOp(0));                         // isConstexpr
+  Abv->Add(BitCodeAbbrevOp(0));                         // isInitCapture
   Abv->Add(BitCodeAbbrevOp(0));                         // isPrevDeclInSameScope
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage
   Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasInit

Modified: cfe/trunk/test/Analysis/lambdas.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/lambdas.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/lambdas.cpp (original)
+++ cfe/trunk/test/Analysis/lambdas.cpp Fri Sep 27 23:02:39 2013
@@ -10,7 +10,7 @@ void f(X x) { (void) [x]{}; }
 // CHECK:   1: x
 // CHECK:   2: [B1.1] (ImplicitCastExpr, NoOp, const struct X)
 // CHECK:   3: [B1.2] (CXXConstructExpr, struct X)
-// CHECK:   4: [=x]     {
+// CHECK:   4: [x]     {
 // CHECK:    }
 // CHECK:   5: (void)[B1.4] (CStyleCastExpr, ToVoid, void)
 // CHECK:   Preds (1): B2

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p11-1y.cpp Fri Sep 27 23:02:39 2013
@@ -1,34 +1,26 @@
 // RUN: %clang_cc1 -std=c++1y %s -verify
 
-// For every init-capture a non-static data member named by the identifier of
-// the init-capture is declared in the closure type.
-const char *has_member_x = [x("hello")] {}.x;
-// This member is not a bit-field...
-auto capturing_lambda = [n(0)] {};
-int decltype(capturing_lambda)::*mem_ptr = &decltype(capturing_lambda)::n;
-// ... and not mutable.
-const auto capturing_lambda_copy = capturing_lambda;
-int &n = capturing_lambda_copy.n; // expected-error {{drops qualifiers}}
-
-// The type of that member [...is that of a...] variable declaration of the form
-// "auto init-capture ;"...
-auto with_float = [f(1.0f)] {};
-float &f = with_float.f;
-// ... except that the variable name is replaced by a unique identifier.
-auto with_float_2 = [&f(f)] {}; // ok, refers to outer f
-float &f2 = with_float_2.f;
+const char *has_no_member = [x("hello")] {}.x; // expected-error {{no member named 'x'}}
 
-// Within the lambda-expression's lambda-declarator (FIXME) and
-// compound-statement, the identifier in the init-capture hides any declaration
+double f;
+auto with_float = [f(1.0f)] {
+  using T = decltype(f);
+  using T = float;
+};
+auto with_float_2 = [&f(f)] { // ok, refers to outer f
+  using T = decltype(f);
+  using T = double&;
+};
+
+// Within the lambda-expression's compound-statement,
+// the identifier in the init-capture hides any declaration
 // of the same name in scopes enclosing the lambda-expression.
 void hiding() {
   char c;
   (void) [c("foo")] {
     static_assert(sizeof(c) == sizeof(const char*), "");
   };
-  (void) [c("bar")] () -> decltype(c) {
-    // FIXME: the 'c' in the return type should be the init-capture, not the
-    // outer c.
+  (void) [c("bar")] () -> decltype(c) { // outer c, not init-capture
     return "baz"; // expected-error {{cannot initialize}}
   };
 }
@@ -54,22 +46,16 @@ int overload_fn(int);
 auto bad_init_1 = [a()] {}; // expected-error {{expected expression}}
 auto bad_init_2 = [a(1, 2)] {}; // expected-error {{initializer for lambda capture 'a' contains multiple expressions}}
 auto bad_init_3 = [&a(void_fn())] {}; // expected-error {{cannot form a reference to 'void'}}
-auto bad_init_4 = [a(void_fn())] {}; // expected-error {{field has incomplete type 'void'}}
+auto bad_init_4 = [a(void_fn())] {}; // expected-error {{has incomplete type 'void'}}
 auto bad_init_5 = [a(overload_fn)] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer of type '<overloaded function}}
 auto bad_init_6 = [a{overload_fn}] {}; // expected-error {{cannot deduce type for lambda capture 'a' from initializer list}}
 
-template<typename...T> void pack_1(T...t) { [a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
+template<typename...T> void pack_1(T...t) { (void)[a(t...)] {}; } // expected-error {{initializer missing for lambda capture 'a'}}
 template void pack_1<>(); // expected-note {{instantiation of}}
 
-auto multi_return(int a, int b) {
-  return [n(a + 2*b), m(a - 2*b)] {};
-}
-auto use_multi_return() {
-  auto nm = multi_return(5, 9);
-  return nm.n + nm.m;
-}
-
-auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] { // expected-warning {{binding reference member 'c' to a temporary value}} expected-note {{here}}
+// FIXME: Might need lifetime extension for the temporary here.
+// See DR1695.
+auto a = [a(4), b = 5, &c = static_cast<const int&&>(0)] {
   static_assert(sizeof(a) == sizeof(int), "");
   static_assert(sizeof(b) == sizeof(int), "");
   using T = decltype(c);
@@ -82,3 +68,10 @@ template<typename T> struct remove_refer
 template<typename T> struct remove_reference<T&> { typedef T type; };
 template<typename T> decltype(auto) move(T &&t) { return static_cast<typename remove_reference<T>::type&&>(t); }
 auto s = [s(move(S()))] {};
+
+template<typename T> T instantiate_test(T t) {
+  [x(&t)]() { *x = 1; } (); // expected-error {{assigning to 'const char *'}}
+  return t;
+}
+int instantiate_test_1 = instantiate_test(0);
+const char *instantiate_test_2 = instantiate_test("foo"); // expected-note {{here}}

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p23.cpp Fri Sep 27 23:02:39 2013
@@ -66,7 +66,7 @@ void init_capture_pack_err(Args ...args)
 
 template<typename ...Args>
 void init_capture_pack_multi(Args ...args) {
-  [as(args...)] {} (); // expected-error {{initializer missing}} expected-error {{multiple}}
+  [as(args...)] {} (); // expected-error {{initializer missing for lambda capture 'as'}} expected-error {{multiple}}
 }
 template void init_capture_pack_multi(); // expected-note {{instantiation}}
 template void init_capture_pack_multi(int);

Added: cfe/trunk/test/CodeGenCXX/cxx1y-init-captures.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/cxx1y-init-captures.cpp?rev=191605&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/cxx1y-init-captures.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/cxx1y-init-captures.cpp Fri Sep 27 23:02:39 2013
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -std=c++1y -triple x86_64-linux-gnu -emit-llvm %s -o - | FileCheck %s
+
+struct S {
+  S();
+  S(S &&);
+  ~S();
+};
+
+void f() {
+  (void) [s(S{})] {};
+}
+
+// CHECK-LABEL: define void @_Z1fv(
+// CHECK: call void @_ZN1SC1Ev(
+// CHECK: call void @"_ZZ1fvEN3$_0D1Ev"(
+
+// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D1Ev"(
+// CHECK: @"_ZZ1fvEN3$_0D2Ev"(
+
+// D2 at end of file.
+
+void g() {
+  [a(1), b(2)] { return a + b; } ();
+}
+
+// CHECK-LABEL: define void @_Z1gv(
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
+// CHECK: store i32 1, i32*
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
+// CHECK: store i32 2, i32*
+// CHECK: call i32 @"_ZZ1gvENK3$_1clEv"(
+
+// CHECK-LABEL: define internal i32 @"_ZZ1gvENK3$_1clEv"(
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 0
+// CHECK: load i32*
+// CHECK: getelementptr inbounds {{.*}}, i32 0, i32 1
+// CHECK: load i32*
+// CHECK: add nsw i32
+
+int h(int a) {
+  // CHECK-LABEL: define i32 @_Z1hi(
+  // CHECK: %[[A_ADDR:.*]] = alloca i32,
+  // CHECK: %[[OUTER:.*]] = alloca
+  // CHECK: store i32 {{.*}}, i32* %[[A_ADDR]],
+  //
+  // Initialize init-capture 'b(a)' by reference.
+  // CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
+  // CHECK: store i32* %[[A_ADDR]], i32** {{.*}},
+  //
+  // Initialize init-capture 'c(a)' by copy.
+  // CHECK: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
+  // CHECK: load i32* %[[A_ADDR]],
+  // CHECK: store i32
+  //
+  // CHECK: call i32 @"_ZZ1hiENK3$_2clEv"({{.*}}* %[[OUTER]])
+  return [&b(a), c(a)] {
+    // CHECK-LABEL: define internal i32 @"_ZZ1hiENK3$_2clEv"(
+    // CHECK: %[[OUTER_ADDR:.*]] = alloca
+    // CHECK: %[[INNER:.*]] = alloca
+    // CHECK: store {{.*}}, {{.*}}** %[[OUTER_ADDR]],
+    //
+    // Capture outer 'c' by reference.
+    // CHECK: %[[OUTER:.*]] = load {{.*}}** %[[OUTER_ADDR]]
+    // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
+    // CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 1
+    // CHECK-NEXT: store i32* %
+    //
+    // Capture outer 'b' by copy.
+    // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
+    // CHECK-NEXT: getelementptr inbounds {{.*}}* %[[OUTER]], i32 0, i32 0
+    // CHECK-NEXT: load i32** %
+    // CHECK-NEXT: load i32* %
+    // CHECK-NEXT: store i32
+    //
+    // CHECK: call i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"({{.*}}* %[[INNER]])
+    return [=, &c] {
+      // CHECK-LABEL: define internal i32 @"_ZZZ1hiENK3$_2clEvENKUlvE_clEv"(
+      // CHECK: %[[INNER_ADDR:.*]] = alloca
+      // CHECK: store {{.*}}, {{.*}}** %[[INNER_ADDR]],
+      // CHECK: %[[INNER:.*]] = load {{.*}}** %[[INNER_ADDR]]
+      //
+      // Load capture of 'b'
+      // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 1
+      // CHECK: load i32* %
+      //
+      // Load capture of 'c'
+      // CHECK: getelementptr inbounds {{.*}}* %[[INNER]], i32 0, i32 0
+      // CHECK: load i32** %
+      // CHECK: load i32* %
+      //
+      // CHECK: add nsw i32
+      return b + c;
+    } ();
+  } ();
+}
+
+// CHECK-LABEL: define internal void @"_ZZ1fvEN3$_0D2Ev"(
+// CHECK: call void @_ZN1SD1Ev(

Added: cfe/trunk/test/PCH/cxx1y-init-captures.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/cxx1y-init-captures.cpp?rev=191605&view=auto
==============================================================================
--- cfe/trunk/test/PCH/cxx1y-init-captures.cpp (added)
+++ cfe/trunk/test/PCH/cxx1y-init-captures.cpp Fri Sep 27 23:02:39 2013
@@ -0,0 +1,28 @@
+// No PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -include %s -verify %s
+//
+// With PCH:
+// RUN: %clang_cc1 -pedantic -std=c++1y -emit-pch %s -o %t
+// RUN: %clang_cc1 -pedantic -std=c++1y -include-pch %t -verify %s
+
+#ifndef HEADER
+#define HEADER
+
+auto counter = [a(0)] () mutable { return a++; };
+int x = counter();
+
+template<typename T> void f(T t) {
+  [t(t)] { int n = t; } ();
+}
+
+#else
+
+int y = counter();
+
+void g() {
+  f(0); // ok
+  // expected-error at 15 {{lvalue of type 'const char *const'}}
+  f("foo"); // expected-note {{here}}
+}
+
+#endif

Modified: cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp?rev=191605&r1=191604&r2=191605&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-lambda-expressions.cpp Fri Sep 27 23:02:39 2013
@@ -52,18 +52,16 @@ class C {
   // We support init-captures in C++11 as an extension.
   int z;
   void init_capture() {
-    // FIXME: These diagnostics should all disappear once semantic analysis
-    // for init-captures is complete.
-    [n(0)] () -> int { return ++n; }; // expected-error {{non-static data member}}
+    [n(0)] () mutable -> int { return ++n; };
     [n{0}] { return; }; // expected-error {{<initializer_list>}}
-    [n = 0] { return ++n; }; // expected-error {{non-static data member}}
+    [n = 0] { return ++n; }; // expected-error {{captured by copy in a non-mutable}}
     [n = {0}] { return; }; // expected-error {{<initializer_list>}}
     [a([&b = z]{})](){};
 
     int x = 4;
     auto y = [&r = x, x = x + 1]() -> int {
-      r += 2; // expected-error {{non-static data member}}
-      return x + 2; // expected-error {{non-static data member}}
+      r += 2;
+      return x + 2;
     } ();
   }
 };





More information about the cfe-commits mailing list