r191453 - Implement a rudimentary form of generic lambdas.

Faisal Vali faisalv at yahoo.com
Thu Sep 26 12:54:13 PDT 2013


Author: faisalv
Date: Thu Sep 26 14:54:12 2013
New Revision: 191453

URL: http://llvm.org/viewvc/llvm-project?rev=191453&view=rev
Log:
Implement a rudimentary form of generic lambdas.

Specifically, the following features are not included in this commit:
  - any sort of capturing within generic lambdas 
  - generic lambdas within template functions and nested 
    within other generic lambdas
  - conversion operator for captureless lambdas
  - ensuring all visitors are generic lambda aware
  (Although I have gotten some useful feedback on my patches of the above and will be incorporating that as I submit those patches for commit)

As an example of what compiles through this commit:

template <class F1, class F2>
struct overload : F1, F2 {
    using F1::operator();
    using F2::operator();
    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
  };

  auto Recursive = [](auto Self, auto h, auto ... rest) {
    return 1 + Self(Self, rest...);
  };
  auto Base = [](auto Self, auto h) {
      return 1;
  };
  overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');

Please see attached tests for more examples.

This patch has been reviewed by Doug and Richard.  Minor changes (non-functionality affecting) have been made since both of them formally looked at it, but the changes involve removal of supernumerary return type deduction changes (since they are now redundant, with richard having committed a recent patch to address return type deduction for C++11 lambdas using C++14 semantics). 



Some implementation notes:

  - Add a new Declarator context => LambdaExprParameterContext to 
    clang::Declarator to allow the use of 'auto' in declaring generic
    lambda parameters
      
  - Add various helpers to CXXRecordDecl to facilitate identifying
    and querying a closure class
  
  - LambdaScopeInfo (which maintains the current lambda's Sema state)
    was augmented to house the current depth of the template being
    parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)
    so that SemaType.cpp::ConvertDeclSpecToType may use it to immediately 
    generate a template-parameter-type when 'auto' is parsed in a generic
    lambda parameter context.  (i.e we do NOT use AutoType deduced to 
    a template parameter type - Richard seemed ok with this approach).  
    We encode that this template type was generated from an auto by simply
    adding $auto to the name which can be used for better diagnostics if needed.

  - SemaLambda.h was added to hold some common lambda utility
    functions (this file is likely to grow ...)
    
  - Teach Sema::ActOnStartOfFunctionDef to check whether it
    is being called to instantiate a generic lambda's call
    operator, and if so, push an appropriately prepared
    LambdaScopeInfo object on the stack.
    
  - various tests were added - but much more will be needed.

There is obviously more work to be done, and both Richard (weakly) and Doug (strongly) 
have requested that LambdaExpr be removed form the CXXRecordDecl LambdaDefinitionaData
in a future patch which is forthcoming.

A greatful thanks to all reviewers including Eli Friedman, James Dennett, 
and especially the two gracious wizards (Richard Smith and Doug Gregor) 
who spent hours providing feedback (in person in Chicago and on the mailing lists).  
And yet I am certain that I have allowed unidentified bugs to creep in; bugs, that I will do my best to slay, once identified!

Thanks!

Added:
    cfe/trunk/include/clang/AST/ASTLambda.h
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
Modified:
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/DeclCXX.h
    cfe/trunk/include/clang/AST/ExprCXX.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/include/clang/Sema/DeclSpec.h
    cfe/trunk/include/clang/Sema/ScopeInfo.h
    cfe/trunk/include/clang/Sema/Sema.h
    cfe/trunk/lib/AST/ASTDumper.cpp
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/lib/AST/DeclCXX.cpp
    cfe/trunk/lib/AST/ExprCXX.cpp
    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/ParseExprCXX.cpp
    cfe/trunk/lib/Sema/Sema.cpp
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/lib/Sema/SemaDeclCXX.cpp
    cfe/trunk/lib/Sema/SemaLambda.cpp
    cfe/trunk/lib/Sema/SemaOverload.cpp
    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/lib/Sema/TreeTransform.h
    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
    cfe/trunk/lib/Serialization/ASTWriter.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp
    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Thu Sep 26 14:54:12 2013
@@ -1130,7 +1130,7 @@ public:
 
   /// \brief C++11 deduced auto type.
   QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
-                       bool IsDependent = false) const;
+                       bool IsDependent) const;
 
   /// \brief C++11 deduction pattern for 'auto' type.
   QualType getAutoDeductType() const;

Added: cfe/trunk/include/clang/AST/ASTLambda.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTLambda.h?rev=191453&view=auto
==============================================================================
--- cfe/trunk/include/clang/AST/ASTLambda.h (added)
+++ cfe/trunk/include/clang/AST/ASTLambda.h Thu Sep 26 14:54:12 2013
@@ -0,0 +1,49 @@
+//===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file provides some common utility functions for processing
+/// Lambda related AST Constructs.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_AST_LAMBDA_H
+#define LLVM_CLANG_AST_LAMBDA_H
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclTemplate.h"
+
+namespace clang {
+inline StringRef getLambdaStaticInvokerName() {
+  return "__invoke";
+}
+// This function returns true if M is a specialization, a template,
+// or a non-generic lambda call operator.
+inline bool isLambdaCallOperator(const CXXMethodDecl *MD) {
+  const CXXRecordDecl *LambdaClass = MD->getParent();
+  if (!LambdaClass || !LambdaClass->isLambda()) return false;
+  return MD->getOverloadedOperator() == OO_Call;
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {
+  CXXRecordDecl *LambdaClass = MD->getParent();
+  if (LambdaClass && LambdaClass->isGenericLambda())
+    return isLambdaCallOperator(MD) && 
+                    MD->isFunctionTemplateSpecialization();
+  return false;
+}
+
+inline bool isGenericLambdaCallOperatorSpecialization(Decl *D) {
+  if (!D || !isa<CXXMethodDecl>(D)) return false;
+  return isGenericLambdaCallOperatorSpecialization(
+                                cast<CXXMethodDecl>(D));
+}
+} // clang
+
+#endif // LLVM_CLANG_AST_LAMBDA_H

Modified: cfe/trunk/include/clang/AST/DeclCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/DeclCXX.h (original)
+++ cfe/trunk/include/clang/AST/DeclCXX.h Thu Sep 26 14:54:12 2013
@@ -516,8 +516,8 @@ class CXXRecordDecl : public RecordDecl
     
     LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) 
       : DefinitionData(D), Dependent(Dependent), NumCaptures(0), 
-        NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0),
-        MethodTyInfo(Info) 
+        NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), 
+        Captures(0), MethodTyInfo(Info), TheLambdaExpr(0) 
     {
       IsLambda = true;
     }
@@ -529,7 +529,7 @@ class CXXRecordDecl : public RecordDecl
     /// within the default argument of a function template, because the
     /// lambda will have been created with the enclosing context as its
     /// declaration context, rather than function. This is an unfortunate
-    /// artifact of having to parse the default arguments before 
+    /// artifact of having to parse the default arguments before. 
     unsigned Dependent : 1;
     
     /// \brief The number of captures in this lambda.
@@ -554,6 +554,10 @@ class CXXRecordDecl : public RecordDecl
 
     /// \brief The type of the call method.
     TypeSourceInfo *MethodTyInfo;
+
+    /// \brief The AST node of the lambda expression.
+    LambdaExpr *TheLambdaExpr;
+       
   };
 
   struct DefinitionData &data() {
@@ -989,6 +993,36 @@ public:
   /// \brief Determine whether this class describes a lambda function object.
   bool isLambda() const { return hasDefinition() && data().IsLambda; }
 
+  /// \brief Determine whether this class describes a generic 
+  /// lambda function object (i.e. function call operator is
+  /// a template). 
+  bool isGenericLambda() const; 
+
+  /// \brief Retrieve the lambda call operator of the closure type
+  /// if this is a closure type.
+  CXXMethodDecl *getLambdaCallOperator() const; 
+
+  /// \brief Retrieve the lambda static invoker, the address of which
+  /// is returned by the conversion operator, and the body of which
+  /// is forwarded to the lambda call operator. 
+  CXXMethodDecl *getLambdaStaticInvoker() const; 
+
+  /// \brief Retrieve the generic lambda's template parameter list.
+  /// Returns null if the class does not represent a lambda or a generic 
+  /// lambda.
+  TemplateParameterList *getGenericLambdaTemplateParameterList() const;
+
+  /// \brief Assign the member call operator of the lambda. 
+  void setLambdaExpr(LambdaExpr *E) {
+    getLambdaData().TheLambdaExpr = E;
+  }
+
+  /// \brief Retrieve the parent lambda expression.
+  LambdaExpr *getLambdaExpr() const {
+    return isLambda() ? getLambdaData().TheLambdaExpr : 0;
+  }
+
+
   /// \brief For a closure type, retrieve the mapping from captured
   /// variables and \c this to the non-static data members that store the
   /// values or references of the captures.

Modified: cfe/trunk/include/clang/AST/ExprCXX.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExprCXX.h (original)
+++ cfe/trunk/include/clang/AST/ExprCXX.h Thu Sep 26 14:54:12 2013
@@ -1606,6 +1606,13 @@ public:
   /// lambda expression. 
   CXXMethodDecl *getCallOperator() const;
 
+  /// \brief If this is a generic lambda expression, retrieve the template 
+  /// parameter list associated with it, or else return null. 
+  TemplateParameterList *getTemplateParameterList() const;
+
+  /// \brief Whether this is a generic lambda.
+  bool isGenericLambda() const { return getTemplateParameterList(); }
+
   /// \brief Retrieve the body of the lambda.
   CompoundStmt *getBody() const;
 

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Thu Sep 26 14:54:12 2013
@@ -3630,10 +3630,13 @@ public:
 /// is no deduced type and an auto type is canonical. In the latter case, it is
 /// also a dependent type.
 class AutoType : public Type, public llvm::FoldingSetNode {
-  AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)
+  AutoType(QualType DeducedType, bool IsDecltypeAuto, 
+           bool IsDependent)
     : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
            /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,
-           /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {
+           /*VariablyModified=*/false, 
+           /*ContainsParameterPack=*/DeducedType.isNull() 
+               ? false : DeducedType->containsUnexpandedParameterPack()) {
     assert((DeducedType.isNull() || !IsDependent) &&
            "auto deduced to dependent type");
     AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
@@ -3657,7 +3660,8 @@ public:
   }
 
   void Profile(llvm::FoldingSetNodeID &ID) {
-    Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());
+    Profile(ID, getDeducedType(), isDecltypeAuto(), 
+		    isDependentType());
   }
 
   static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Thu Sep 26 14:54:12 2013
@@ -1470,11 +1470,12 @@ def err_illegal_decl_array_of_auto : Err
 def err_new_array_of_auto : Error<
   "cannot allocate array of 'auto'">;
 def err_auto_not_allowed : Error<
-  "'auto' not allowed %select{in function prototype|in non-static struct member"
+  "%select{'auto'|'decltype(auto)'}0 not allowed %select{in function prototype"
+  "|in non-static struct member"
   "|in non-static union member|in non-static class member|in interface member"
   "|in exception declaration|in template parameter|in block literal"
   "|in template argument|in typedef|in type alias|in function return type"
-  "|in conversion function type|here}0">;
+  "|in conversion function type|here|in lambda parameter}1">;
 def err_auto_not_allowed_var_inst : Error<
   "'auto' variable template instantiation is not allowed">;
 def err_auto_var_requires_init : Error<
@@ -5078,6 +5079,10 @@ let CategoryName = "Lambda Issue" in {
     "cannot deduce type for lambda capture %0 from initializer list">;
 }
 
+// C++1y Generic Lambdas
+def err_glambda_not_fully_implemented : Error<
+  "unimplemented generic lambda feature: %0">;
+    
 def err_return_in_captured_stmt : Error<
   "cannot return from %0">;
 def err_capture_block_variable : Error<

Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
+++ cfe/trunk/include/clang/Sema/DeclSpec.h Thu Sep 26 14:54:12 2013
@@ -1502,6 +1502,7 @@ public:
     ObjCCatchContext,    // Objective-C catch exception-declaration
     BlockLiteralContext, // Block literal declarator.
     LambdaExprContext,   // Lambda-expression declarator.
+    LambdaExprParameterContext, // Lambda-expression parameter declarator.
     ConversionIdContext, // C++ conversion-type-id.
     TrailingReturnContext, // C++11 trailing-type-specifier.
     TemplateTypeArgContext, // Template type argument.
@@ -1577,7 +1578,6 @@ public:
   ~Declarator() {
     clear();
   }
-
   /// getDeclSpec - Return the declaration-specifier that this declarator was
   /// declared with.
   const DeclSpec &getDeclSpec() const { return DS; }
@@ -1606,7 +1606,8 @@ public:
   bool isPrototypeContext() const {
     return (Context == PrototypeContext ||
             Context == ObjCParameterContext ||
-            Context == ObjCResultContext);
+            Context == ObjCResultContext ||
+            Context == LambdaExprParameterContext);
   }
 
   /// \brief Get the source range that spans this declarator.
@@ -1670,6 +1671,7 @@ public:
     case AliasDeclContext:
     case AliasTemplateContext:
     case PrototypeContext:
+    case LambdaExprParameterContext:
     case ObjCParameterContext:
     case ObjCResultContext:
     case TemplateParamContext:
@@ -1698,6 +1700,7 @@ public:
     case ForContext:
     case ConditionContext:
     case PrototypeContext:
+    case LambdaExprParameterContext:
     case TemplateParamContext:
     case CXXCatchContext:
     case ObjCCatchContext:
@@ -1730,6 +1733,7 @@ public:
     case ForContext:
     case ConditionContext:
     case PrototypeContext:
+    case LambdaExprParameterContext:
     case TemplateParamContext:
     case CXXCatchContext:
     case ObjCCatchContext:
@@ -1782,6 +1786,7 @@ public:
     case KNRTypeListContext:
     case MemberContext:
     case PrototypeContext:
+    case LambdaExprParameterContext:
     case ObjCParameterContext:
     case ObjCResultContext:
     case TemplateParamContext:
@@ -1968,6 +1973,7 @@ public:
     case AliasDeclContext:
     case AliasTemplateContext:
     case PrototypeContext:
+    case LambdaExprParameterContext:
     case ObjCParameterContext:
     case ObjCResultContext:
     case TemplateParamContext:

Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
+++ cfe/trunk/include/clang/Sema/ScopeInfo.h Thu Sep 26 14:54:12 2013
@@ -35,6 +35,8 @@ class LabelDecl;
 class ReturnStmt;
 class Scope;
 class SwitchStmt;
+class TemplateTypeParmDecl;
+class TemplateParameterList;
 class VarDecl;
 class DeclRefExpr;
 class ObjCIvarRefExpr;
@@ -615,12 +617,29 @@ public:
   /// \brief Offsets into the ArrayIndexVars array at which each capture starts
   /// its list of array index variables.
   SmallVector<unsigned, 4> ArrayIndexStarts;
-
-  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
-                  CXXMethodDecl *CallOperator)
-    : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
-      CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),
-      ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
+  
+  /// \brief If this is a generic lambda, use this as the depth of 
+  /// each 'auto' parameter, during initial AST construction.
+  unsigned AutoTemplateParameterDepth;
+
+  /// \brief Store the list of the auto parameters for a generic lambda.
+  /// If this is a generic lambda, store the list of the auto 
+  /// parameters converted into TemplateTypeParmDecls into a vector
+  /// that can be used to construct the generic lambda's template
+  /// parameter list, during initial AST construction.
+  SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
+
+  /// If this is a generic lambda, and the template parameter
+  /// list has been created (from the AutoTemplateParams) then
+  /// store a reference to it (cache it to avoid reconstructing it).
+  TemplateParameterList *GLTemplateParameterList;
+
+  LambdaScopeInfo(DiagnosticsEngine &Diag)
+    : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),
+      CallOperator(0), NumExplicitCaptures(0), Mutable(false),
+      ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),
+      AutoTemplateParameterDepth(0),
+      GLTemplateParameterList(0)
   {
     Kind = SK_Lambda;
   }

Modified: cfe/trunk/include/clang/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/Sema.h (original)
+++ cfe/trunk/include/clang/Sema/Sema.h Thu Sep 26 14:54:12 2013
@@ -965,7 +965,13 @@ public:
 
   void PushFunctionScope();
   void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
-  void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);
+  void PushLambdaScope();
+  
+  /// \brief This is used to inform Sema what the current TemplateParameterDepth
+  /// is during Parsing.  Currently it is used to pass on the depth
+  /// when parsing generic lambda 'auto' parameters.
+  void RecordParsingTemplateParameterDepth(unsigned Depth);
+  
   void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
                                RecordDecl *RD,
                                CapturedRegionKind K);
@@ -992,9 +998,12 @@ public:
   /// \brief Retrieve the current block, if any.
   sema::BlockScopeInfo *getCurBlock();
 
-  /// \brief Retrieve the current lambda expression, if any.
+  /// \brief Retrieve the current lambda scope info, if any.
   sema::LambdaScopeInfo *getCurLambda();
 
+  /// \brief Retrieve the current generic lambda info, if any.
+  sema::LambdaScopeInfo *getCurGenericLambda();
+
   /// \brief Retrieve the current captured region, if any.
   sema::CapturedRegionScopeInfo *getCurCapturedRegion();
 
@@ -4427,14 +4436,15 @@ public:
                                        SourceLocation EndLoc,
                                        ArrayRef<ParmVarDecl *> Params);
 
-  /// \brief Introduce the scope for a lambda expression.
-  sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
-                                          SourceRange IntroducerRange,
-                                          LambdaCaptureDefault CaptureDefault,
-                                          SourceLocation CaptureDefaultLoc,
-                                          bool ExplicitParams,
-                                          bool ExplicitResultType,
-                                          bool Mutable);
+  /// \brief Endow the lambda scope info with the relevant properties.
+  void buildLambdaScope(sema::LambdaScopeInfo *LSI, 
+                        CXXMethodDecl *CallOperator,
+                        SourceRange IntroducerRange,
+                        LambdaCaptureDefault CaptureDefault,
+                        SourceLocation CaptureDefaultLoc,
+                        bool ExplicitParams,
+                        bool ExplicitResultType,
+                        bool Mutable);
 
   /// \brief Check and build an init-capture with the specified name and
   /// initializer.
@@ -5819,6 +5829,12 @@ public:
                           sema::TemplateDeductionInfo &Info,
                           bool InOverloadResolution = false);
 
+  /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
+  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
+  /// \brief Substitute Replacement for auto in TypeWithAuto
+  TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, 
+                                          QualType Replacement);
+
   /// \brief Result type of DeduceAutoType.
   enum DeduceAutoResult {
     DAR_Succeeded,
@@ -5830,7 +5846,6 @@ public:
                                   QualType &Result);
   DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,
                                   QualType &Result);
-  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
   void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
   bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
                         bool Diagnose = true);

Modified: cfe/trunk/lib/AST/ASTDumper.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTDumper.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTDumper.cpp (original)
+++ cfe/trunk/lib/AST/ASTDumper.cpp Thu Sep 26 14:54:12 2013
@@ -286,6 +286,10 @@ namespace  {
     void VisitExprWithCleanups(const ExprWithCleanups *Node);
     void VisitUnresolvedLookupExpr(const UnresolvedLookupExpr *Node);
     void dumpCXXTemporary(const CXXTemporary *Temporary);
+    void VisitLambdaExpr(const LambdaExpr *Node) {
+      VisitExpr(Node);
+      dumpDecl(Node->getLambdaClass());
+    }
 
     // ObjC
     void VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node);

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Sep 26 14:54:12 2013
@@ -1709,7 +1709,8 @@ QualType ASTNodeImporter::VisitAutoType(
       return QualType();
   }
   
-  return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto());
+  return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(), 
+                                             /*IsDependent*/false);
 }
 
 QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {

Modified: cfe/trunk/lib/AST/DeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/DeclCXX.cpp (original)
+++ cfe/trunk/lib/AST/DeclCXX.cpp Thu Sep 26 14:54:12 2013
@@ -10,9 +10,9 @@
 // This file implements the C++ related Decl classes.
 //
 //===----------------------------------------------------------------------===//
-
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
 #include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclTemplate.h"
@@ -943,6 +943,40 @@ bool CXXRecordDecl::isCLike() const {
   return isPOD() && data().HasOnlyCMembers;
 }
 
+bool CXXRecordDecl::isGenericLambda() const { 
+  return isLambda() && 
+      getLambdaCallOperator()->getDescribedFunctionTemplate(); 
+}
+
+CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
+  if (!isLambda()) return 0;
+  DeclarationName Name = 
+    getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
+  DeclContext::lookup_const_result Calls = lookup(Name);
+
+  assert(!Calls.empty() && "Missing lambda call operator!");
+  assert(Calls.size() == 1 && "More than one lambda call operator!"); 
+   
+  NamedDecl *CallOp = Calls.front();
+  if (FunctionTemplateDecl *CallOpTmpl = 
+                    dyn_cast<FunctionTemplateDecl>(CallOp)) 
+    return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
+  
+  return cast<CXXMethodDecl>(CallOp);
+}
+
+CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
+  if (!isLambda()) return 0;
+  DeclarationName Name = 
+    &getASTContext().Idents.get(getLambdaStaticInvokerName());
+  DeclContext::lookup_const_result Invoker = lookup(Name);
+  if (Invoker.empty()) return 0;
+  assert(Invoker.size() == 1 && "More than one static invoker operator!");  
+  CXXMethodDecl *Result = cast<CXXMethodDecl>(Invoker.front());  
+  return Result;
+
+}
+
 void CXXRecordDecl::getCaptureFields(
        llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
        FieldDecl *&ThisCapture) const {
@@ -960,6 +994,14 @@ void CXXRecordDecl::getCaptureFields(
   }
 }
 
+TemplateParameterList * 
+CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
+  if (!isLambda()) return 0;
+  CXXMethodDecl *CallOp = getLambdaCallOperator();     
+  if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())
+    return Tmpl->getTemplateParameters();
+  return 0;
+}
 
 static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {
   QualType T;
@@ -1510,7 +1552,7 @@ bool CXXMethodDecl::hasInlineBody() cons
 
 bool CXXMethodDecl::isLambdaStaticInvoker() const {
   return getParent()->isLambda() && 
-         getIdentifier() && getIdentifier()->getName() == "__invoke";
+         getParent()->getLambdaStaticInvoker() == this;
 }
 
 

Modified: cfe/trunk/lib/AST/ExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExprCXX.cpp (original)
+++ cfe/trunk/lib/AST/ExprCXX.cpp Thu Sep 26 14:54:12 2013
@@ -1076,13 +1076,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClas
 
 CXXMethodDecl *LambdaExpr::getCallOperator() const {
   CXXRecordDecl *Record = getLambdaClass();
-  DeclarationName Name
-    = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
-  DeclContext::lookup_result Calls = Record->lookup(Name);
-  assert(!Calls.empty() && "Missing lambda call operator!");
-  assert(Calls.size() == 1 && "More than one lambda call operator!");
-  CXXMethodDecl *Result = cast<CXXMethodDecl>(Calls.front());
-  return Result;
+  return Record->getLambdaCallOperator();  
+}
+
+TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
+  CXXRecordDecl *Record = getLambdaClass();
+  return Record->getGenericLambdaTemplateParameterList();
+
 }
 
 CompoundStmt *LambdaExpr::getBody() const {

Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
+++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Thu Sep 26 14:54:12 2013
@@ -698,7 +698,7 @@ void CodeGenFunction::GenerateCode(Globa
     EmitLambdaToBlockPointerBody(Args);
   } else if (isa<CXXMethodDecl>(FD) &&
              cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
-    // The lambda "__invoke" function is special, because it forwards or
+    // The lambda static invoker function is special, because it forwards or
     // clones the body of the function call operator (but is actually static).
     EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
   } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Thu Sep 26 14:54:12 2013
@@ -4677,6 +4677,7 @@ void Parser::ParseDirectDeclarator(Decla
     //   as part of the parameter-declaration-clause.
     if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
         !((D.getContext() == Declarator::PrototypeContext ||
+           D.getContext() == Declarator::LambdaExprParameterContext ||
            D.getContext() == Declarator::BlockLiteralContext) &&
           NextToken().is(tok::r_paren) &&
           !D.hasGroupingParens() &&
@@ -5002,7 +5003,6 @@ void Parser::ParseFunctionDeclarator(Dec
   TypeResult TrailingReturnType;
 
   Actions.ActOnStartFunctionDeclarator();
-
   /* LocalEndLoc is the end location for the local FunctionTypeLoc.
      EndLoc is the end location for the function declarator.
      They differ for trailing return types. */
@@ -5023,7 +5023,8 @@ void Parser::ParseFunctionDeclarator(Dec
     EndLoc = RParenLoc;
   } else {
     if (Tok.isNot(tok::r_paren))
-      ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, EllipsisLoc);
+      ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo, 
+                                      EllipsisLoc);
     else if (RequiresArg)
       Diag(Tok, diag::err_argument_required_after_attribute);
 
@@ -5254,7 +5255,6 @@ void Parser::ParseParameterDeclarationCl
        ParsedAttributes &FirstArgAttrs,
        SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
        SourceLocation &EllipsisLoc) {
-
   while (1) {
     if (Tok.is(tok::ellipsis)) {
       // FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
@@ -5284,16 +5284,21 @@ void Parser::ParseParameterDeclarationCl
 
     ParseDeclarationSpecifiers(DS);
 
-    // Parse the declarator.  This is "PrototypeContext", because we must
-    // accept either 'declarator' or 'abstract-declarator' here.
-    Declarator ParmDecl(DS, Declarator::PrototypeContext);
-    ParseDeclarator(ParmDecl);
+
+    // Parse the declarator.  This is "PrototypeContext" or 
+    // "LambdaExprParameterContext", because we must accept either 
+    // 'declarator' or 'abstract-declarator' here.
+    Declarator ParmDeclarator(DS, 
+              D.getContext() == Declarator::LambdaExprContext ?
+                                  Declarator::LambdaExprParameterContext : 
+                                                Declarator::PrototypeContext);
+    ParseDeclarator(ParmDeclarator);
 
     // Parse GNU attributes, if present.
-    MaybeParseGNUAttributes(ParmDecl);
+    MaybeParseGNUAttributes(ParmDeclarator);
 
     // Remember this parsed parameter in ParamInfo.
-    IdentifierInfo *ParmII = ParmDecl.getIdentifier();
+    IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
 
     // DefArgToks is used when the parsing of default arguments needs
     // to be delayed.
@@ -5301,8 +5306,8 @@ void Parser::ParseParameterDeclarationCl
 
     // If no parameter was specified, verify that *something* was specified,
     // otherwise we have a missing type and identifier.
-    if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
-        ParmDecl.getNumTypeObjects() == 0) {
+    if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
+        ParmDeclarator.getNumTypeObjects() == 0) {
       // Completely missing, emit error.
       Diag(DSStart, diag::err_missing_param);
     } else {
@@ -5311,8 +5316,8 @@ void Parser::ParseParameterDeclarationCl
 
       // Inform the actions module about the parameter declarator, so it gets
       // added to the current scope.
-      Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), ParmDecl);
-
+      Decl *Param = Actions.ActOnParamDeclarator(getCurScope(), 
+                                                       ParmDeclarator);
       // Parse the default argument, if any. We parse the default
       // arguments in all dialects; the semantic analysis in
       // ActOnParamDefaultArgument will reject the default argument in
@@ -5371,8 +5376,8 @@ void Parser::ParseParameterDeclarationCl
       }
 
       ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
-                                          ParmDecl.getIdentifierLoc(), Param,
-                                          DefArgToks));
+                                          ParmDeclarator.getIdentifierLoc(), 
+                                          Param, DefArgToks));
     }
 
     // If the next token is a comma, consume it and keep reading arguments.

Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
+++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Thu Sep 26 14:54:12 2013
@@ -10,7 +10,7 @@
 // This file implements the Expression parsing implementation for C++.
 //
 //===----------------------------------------------------------------------===//
-
+#include "clang/AST/DeclTemplate.h"
 #include "clang/Parse/Parser.h"
 #include "RAIIObjectsForParser.h"
 #include "clang/Basic/PrettyStackTrace.h"
@@ -21,6 +21,7 @@
 #include "clang/Sema/Scope.h"
 #include "llvm/Support/ErrorHandling.h"
 
+
 using namespace clang;
 
 static int SelectDigraphErrorMessage(tok::TokenKind Kind) {
@@ -908,12 +909,16 @@ ExprResult Parser::ParseLambdaExpression
   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
                                 "lambda expression parsing");
 
+ 
+
   // FIXME: Call into Actions to add any init-capture declarations to the
   // scope while parsing the lambda-declarator and compound-statement.
 
   // Parse lambda-declarator[opt].
   DeclSpec DS(AttrFactory);
   Declarator D(DS, Declarator::LambdaExprContext);
+  TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+  Actions.PushLambdaScope();    
 
   if (Tok.is(tok::l_paren)) {
     ParseScope PrototypeScope(this,
@@ -931,9 +936,16 @@ ExprResult Parser::ParseLambdaExpression
     SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
     SourceLocation EllipsisLoc;
 
-    if (Tok.isNot(tok::r_paren))
+    
+    if (Tok.isNot(tok::r_paren)) {
+      sema::LambdaScopeInfo *LSI = Actions.getCurLambda(); 
+      Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
       ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
-
+      // For a generic lambda, each 'auto' within the parameter declaration 
+      // clause creates a template type parameter, so increment the depth.
+      if (Actions.getCurGenericLambda()) 
+        ++CurTemplateDepthTracker;
+    }
     T.consumeClose();
     SourceLocation RParenLoc = T.getCloseLocation();
     DeclEndLoc = RParenLoc;

Modified: cfe/trunk/lib/Sema/Sema.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.cpp (original)
+++ cfe/trunk/lib/Sema/Sema.cpp Thu Sep 26 14:54:12 2013
@@ -1023,10 +1023,17 @@ void Sema::PushBlockScope(Scope *BlockSc
                                               BlockScope, Block));
 }
 
-void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
-                           CXXMethodDecl *CallOperator) {
-  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
-                                               CallOperator));
+void Sema::PushLambdaScope() {
+  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics()));
+}
+
+void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
+  if (LambdaScopeInfo *const LSI = getCurLambda()) {
+    LSI->AutoTemplateParameterDepth = Depth;
+    return;
+  } 
+  llvm_unreachable( 
+      "Remove assertion if intentionally called in a non-lambda context.");
 }
 
 void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
@@ -1082,6 +1089,16 @@ LambdaScopeInfo *Sema::getCurLambda() {
 
   return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
 }
+// We have a generic lambda if we parsed auto parameters, or we have 
+// an associated template parameter list.
+LambdaScopeInfo *Sema::getCurGenericLambda() {
+  if (LambdaScopeInfo *LSI =  getCurLambda()) {
+    return (LSI->AutoTemplateParams.size() ||
+                    LSI->GLTemplateParameterList) ? LSI : 0;
+  }
+  return 0;
+}
+
 
 void Sema::ActOnComment(SourceRange Comment) {
   if (!LangOpts.RetainCommentsFromSystemHeaders &&

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Thu Sep 26 14:54:12 2013
@@ -15,6 +15,7 @@
 #include "TypeLocBuilder.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
 #include "clang/AST/CommentDiagnostic.h"
@@ -8975,6 +8976,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *
   const DeclSpec &DS = D.getDeclSpec();
 
   // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
+
   // C++03 [dcl.stc]p2 also permits 'auto'.
   VarDecl::StorageClass StorageClass = SC_None;
   if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
@@ -9334,9 +9336,37 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop
     FD = FunTmpl->getTemplatedDecl();
   else
     FD = cast<FunctionDecl>(D);
-
-  // Enter a new function scope
-  PushFunctionScope();
+  // If we are instantiating a generic lambda call operator, push
+  // a LambdaScopeInfo onto the function stack.  But use the information
+  // that's already been calculated (ActOnLambdaExpr) when analyzing the
+  // template version, to prime the current LambdaScopeInfo. 
+  if (isGenericLambdaCallOperatorSpecialization(D)) {
+    CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
+    CXXRecordDecl *LambdaClass = CallOperator->getParent();
+    LambdaExpr    *LE = LambdaClass->getLambdaExpr();
+    assert(LE && 
+     "No LambdaExpr of closure class when instantiating a generic lambda!");
+    assert(ActiveTemplateInstantiations.size() &&
+      "There should be an active template instantiation on the stack " 
+      "when instantiating a generic lambda!");
+    PushLambdaScope();
+    LambdaScopeInfo *LSI = getCurLambda();
+    LSI->CallOperator = CallOperator;
+    LSI->Lambda = LambdaClass;
+    LSI->ReturnType = CallOperator->getResultType();
+
+    if (LE->getCaptureDefault() == LCD_None)
+      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
+    else if (LE->getCaptureDefault() == LCD_ByCopy)
+      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
+    else if (LE->getCaptureDefault() == LCD_ByRef)
+      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
+    
+    LSI->IntroducerRange = LE->getIntroducerRange();
+  }
+  else
+    // Enter a new function scope
+    PushFunctionScope();
 
   // See if this is a redefinition.
   if (!FD->isLateTemplateParsed())

Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Thu Sep 26 14:54:12 2013
@@ -14,6 +14,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTLambda.h"
 #include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/CharUnits.h"
@@ -10364,10 +10365,10 @@ void Sema::DefineImplicitLambdaToFunctio
        SourceLocation CurrentLocation,
        CXXConversionDecl *Conv) 
 {
-  CXXRecordDecl *Lambda = Conv->getParent();
+  CXXRecordDecl *LambdaClass = Conv->getParent();
   
   // Make sure that the lambda call operator is marked used.
-  markLambdaCallOperatorUsed(*this, Lambda);
+  markLambdaCallOperatorUsed(*this, LambdaClass);
   
   Conv->markUsed(Context);
   
@@ -10375,19 +10376,18 @@ void Sema::DefineImplicitLambdaToFunctio
   DiagnosticErrorTrap Trap(Diags);
   
   // Return the address of the __invoke function.
-  DeclarationName InvokeName = &Context.Idents.get("__invoke");
-  CXXMethodDecl *Invoke 
-    = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
+  
+  CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker();
   Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
                                        VK_LValue, Conv->getLocation()).take();
-  assert(FunctionRef && "Can't refer to __invoke function?");
+  assert(FunctionRef && "Can't refer to lambda static invoker function?");
   Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();
   Conv->setBody(new (Context) CompoundStmt(Context, Return,
                                            Conv->getLocation(),
                                            Conv->getLocation()));
     
-  // Fill in the __invoke function with a dummy implementation. IR generation
-  // will fill in the actual details.
+  // Fill in the static invoker function with a dummy implementation. 
+  // IR generation will fill in the actual details.
   Invoke->markUsed(Context);
   Invoke->setReferenced();
   Invoke->setBody(new (Context) CompoundStmt(Conv->getLocation()));

Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLambda.cpp Thu Sep 26 14:54:12 2013
@@ -11,6 +11,7 @@
 //
 //===----------------------------------------------------------------------===//
 #include "clang/Sema/DeclSpec.h"
+#include "clang/AST/ASTLambda.h"
 #include "clang/AST/ExprCXX.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Lex/Preprocessor.h"
@@ -130,17 +131,37 @@ Sema::ExpressionEvaluationContextRecord:
   return *MangleNumbering;
 }
 
+static inline TemplateParameterList *
+getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) {
+  if (LSI->GLTemplateParameterList)
+    return LSI->GLTemplateParameterList;
+  else if (LSI->AutoTemplateParams.size()) {
+    SourceRange IntroRange = LSI->IntroducerRange;
+    SourceLocation LAngleLoc = IntroRange.getBegin();
+    SourceLocation RAngleLoc = IntroRange.getEnd();
+    LSI->GLTemplateParameterList = 
+          TemplateParameterList::Create(SemaRef.Context, 
+            /* Template kw loc */ SourceLocation(), 
+            LAngleLoc,
+            (NamedDecl**)LSI->AutoTemplateParams.data(), 
+            LSI->AutoTemplateParams.size(), RAngleLoc);  
+  }
+  return LSI->GLTemplateParameterList;
+}
+
+
 CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
                                            SourceRange IntroducerRange,
                                            TypeSourceInfo *MethodTypeInfo,
                                            SourceLocation EndLoc,
                                            ArrayRef<ParmVarDecl *> Params) {
   QualType MethodType = MethodTypeInfo->getType();
-
-  // If a lambda appears in a dependent context and has an 'auto' return type,
-  // deduce it to a dependent type.
-  // FIXME: Generic lambda call operators should also get this treatment.
-  if (Class->isDependentContext()) {
+  TemplateParameterList *TemplateParams = 
+            getGenericLambdaTemplateParameterList(getCurLambda(), *this);
+  // If a lambda appears in a dependent context or is a generic lambda (has
+  // template parameters) and has an 'auto' return type, deduce it to a 
+  // dependent type.
+  if (Class->isDependentContext() || TemplateParams) {
     const FunctionProtoType *FPT = MethodType->castAs<FunctionProtoType>();
     QualType Result = FPT->getResultType();
     if (Result->isUndeducedType()) {
@@ -177,6 +198,17 @@ CXXMethodDecl *Sema::startLambdaDefiniti
   // Temporarily set the lexical declaration context to the current
   // context, so that the Scope stack matches the lexical nesting.
   Method->setLexicalDeclContext(CurContext);  
+  // Create a function template if we have a template parameter list
+  FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
+            FunctionTemplateDecl::Create(Context, Class,
+                                         Method->getLocation(), MethodName, 
+                                         TemplateParams,
+                                         Method) : 0;
+  if (TemplateMethod) {
+    TemplateMethod->setLexicalDeclContext(CurContext);
+    TemplateMethod->setAccess(AS_public);
+    Method->setDescribedFunctionTemplate(TemplateMethod);
+  }
   
   // Add parameters.
   if (!Params.empty()) {
@@ -202,15 +234,16 @@ CXXMethodDecl *Sema::startLambdaDefiniti
   return Method;
 }
 
-LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
+                                        CXXMethodDecl *CallOperator,
                                         SourceRange IntroducerRange,
                                         LambdaCaptureDefault CaptureDefault,
                                         SourceLocation CaptureDefaultLoc,
                                         bool ExplicitParams,
                                         bool ExplicitResultType,
                                         bool Mutable) {
-  PushLambdaScope(CallOperator->getParent(), CallOperator);
-  LambdaScopeInfo *LSI = getCurLambda();
+  LSI->CallOperator = CallOperator;
+  LSI->Lambda = CallOperator->getParent();
   if (CaptureDefault == LCD_ByCopy)
     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
   else if (CaptureDefault == LCD_ByRef)
@@ -233,8 +266,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(
   } else {
     LSI->HasImplicitReturnType = true;
   }
-
-  return LSI;
 }
 
 void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
@@ -384,6 +415,8 @@ static void adjustBlockReturnsToEnum(Sem
 
 void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
   assert(CSI.HasImplicitReturnType);
+  // If it was ever a placeholder, it had to been deduced to DependentTy.
+  assert(CSI.ReturnType.isNull() || !CSI.ReturnType->isUndeducedType()); 
 
   // C++ Core Issue #975, proposed resolution:
   //   If a lambda-expression does not include a trailing-return-type,
@@ -544,15 +577,25 @@ FieldDecl *Sema::checkInitCapture(Source
 }
 
 void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
-                                        Declarator &ParamInfo,
-                                        Scope *CurScope) {
+                  Declarator &ParamInfo, Scope *CurScope) {
   // Determine if we're within a context where we know that the lambda will
   // be dependent, because there are template parameters in scope.
   bool KnownDependent = false;
-  if (Scope *TmplScope = CurScope->getTemplateParamParent())
-    if (!TmplScope->decl_empty())
+  LambdaScopeInfo *const LSI = getCurLambda();
+  assert(LSI && "LambdaScopeInfo should be on stack!");
+  TemplateParameterList *TemplateParams = 
+            getGenericLambdaTemplateParameterList(LSI, *this);
+
+  if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
+    // Since we have our own TemplateParams, so check if an outer scope
+    // has template params, only then are we in a dependent scope.
+    if (TemplateParams)  {
+      TmplScope = TmplScope->getParent();
+      TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
+    }
+    if (TmplScope && !TmplScope->decl_empty())
       KnownDependent = true;
-  
+  }
   // Determine the signature of the call operator.
   TypeSourceInfo *MethodTyInfo;
   bool ExplicitParams = true;
@@ -621,7 +664,6 @@ void Sema::ActOnStartOfLambdaDefinition(
 
   CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
                                                 MethodTyInfo, EndLoc, Params);
-  
   if (ExplicitParams)
     CheckCXXDefaultArguments(Method);
   
@@ -631,9 +673,8 @@ void Sema::ActOnStartOfLambdaDefinition(
   // Introduce the function call operator as the current declaration context.
   PushDeclContext(CurScope, Method);
     
-  // Introduce the lambda scope.
-  LambdaScopeInfo *LSI
-    = enterLambdaScope(Method,
+  // Build the lambda scope.
+  buildLambdaScope(LSI, Method,
                        Intro.Range,
                        Intro.Default, Intro.DefaultLoc,
                        ExplicitParams,
@@ -845,6 +886,8 @@ static void addFunctionPointerConversion
                                          SourceRange IntroducerRange,
                                          CXXRecordDecl *Class,
                                          CXXMethodDecl *CallOperator) {
+  // FIXME: The conversion operator needs to be fixed for generic lambdas.
+  if (Class->isGenericLambda()) return;
   // Add the conversion to function pointer.
   const FunctionProtoType *Proto
     = CallOperator->getType()->getAs<FunctionProtoType>(); 
@@ -885,10 +928,9 @@ static void addFunctionPointerConversion
   Conversion->setAccess(AS_public);
   Conversion->setImplicit(true);
   Class->addDecl(Conversion);
-  
-  // Add a non-static member function "__invoke" that will be the result of
-  // the conversion.
-  Name = &S.Context.Idents.get("__invoke");
+  // Add a non-static member function that will be the result of
+  // the conversion with a certain unique ID.
+  Name = &S.Context.Idents.get(getLambdaStaticInvokerName());
   CXXMethodDecl *Invoke
     = CXXMethodDecl::Create(S.Context, Class, Loc, 
                             DeclarationNameInfo(Name, Loc), FunctionTy, 
@@ -1060,13 +1102,19 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
           LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());
       CallOperator->setType(FunctionTy);
     }
-
     // C++ [expr.prim.lambda]p7:
     //   The lambda-expression's compound-statement yields the
     //   function-body (8.4) of the function call operator [...].
     ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
     CallOperator->setLexicalDeclContext(Class);
-    Class->addDecl(CallOperator);
+    Decl *TemplateOrNonTemplateCallOperatorDecl = 
+        CallOperator->getDescribedFunctionTemplate()  
+        ? CallOperator->getDescribedFunctionTemplate() 
+        : cast<Decl>(CallOperator);
+
+    TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
+    Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
+
     PopExpressionEvaluationContext();
 
     // C++11 [expr.prim.lambda]p6:
@@ -1106,7 +1154,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
                                           CaptureInits, ArrayIndexVars, 
                                           ArrayIndexStarts, Body->getLocEnd(),
                                           ContainsUnexpandedParameterPack);
-
+  Class->setLambdaExpr(Lambda);
   // C++11 [expr.prim.lambda]p2:
   //   A lambda-expression shall not appear in an unevaluated operand
   //   (Clause 5).
@@ -1126,7 +1174,15 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
       break;
     }
   }
-  
+  // TODO: Implement capturing.
+  if (Lambda->isGenericLambda()) {
+    if (Lambda->getCaptureDefault() != LCD_None) {
+      Diag(Lambda->getIntroducerRange().getBegin(), 
+        diag::err_glambda_not_fully_implemented) 
+        << " capturing not implemented yet";
+      return ExprError();
+    }
+  }
   return MaybeBindToTemporary(Lambda);
 }
 

Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Thu Sep 26 14:54:12 2013
@@ -8682,6 +8682,10 @@ void DiagnoseBadDeduction(Sema &S, Decl
         }
       }
     }
+    // FIXME: For generic lambda parameters, check if the function is a lambda
+    // call operator, and if so, emit a prettier and more informative 
+    // diagnostic that mentions 'auto' and lambda in addition to 
+    // (or instead of?) the canonical template type parameters.
     S.Diag(Templated->getLocation(),
            diag::note_ovl_candidate_non_deduced_mismatch)
         << FirstTA << SecondTA;

Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Thu Sep 26 14:54:12 2013
@@ -3913,8 +3913,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
   return DAR_Succeeded;
 }
 
-QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
-  return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
+QualType Sema::SubstAutoType(QualType TypeWithAuto, 
+                             QualType TypeToReplaceAuto) {
+  return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+               TransformType(TypeWithAuto);
+}
+
+TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, 
+                             QualType TypeToReplaceAuto) {
+    return SubstituteAutoTransform(*this, TypeToReplaceAuto).
+               TransformType(TypeWithAuto);
 }
 
 void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Thu Sep 26 14:54:12 2013
@@ -994,11 +994,54 @@ static QualType ConvertDeclSpecToType(Ty
 
   case DeclSpec::TST_auto:
     // TypeQuals handled by caller.
-    Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
+    // If auto is mentioned in a lambda parameter context, convert it to a 
+    // template parameter type immediately, with the appropriate depth and 
+    // index, and update sema's state (LambdaScopeInfo) for the current lambda 
+    // being analyzed (which tracks the invented type template parameter).
+    if (declarator.getContext() == Declarator::LambdaExprParameterContext) {
+      sema::LambdaScopeInfo *LSI = S.getCurLambda();
+      assert(LSI && "No LambdaScopeInfo on the stack!");
+      const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
+      const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+      const bool IsParameterPack = declarator.hasEllipsis();
+      
+      // Create a name for the invented template parameter type.
+      std::string InventedTemplateParamName = "$auto-";
+      llvm::raw_string_ostream ss(InventedTemplateParamName);
+      ss << TemplateParameterDepth; 
+      ss << "-" << AutoParameterPosition;
+      ss.flush();
+
+      IdentifierInfo& TemplateParamII = Context.Idents.get(
+                                        InventedTemplateParamName.c_str());
+      // Turns out we must create the TemplateTypeParmDecl here to 
+      // retrieve the corresponding template parameter type. 
+      TemplateTypeParmDecl *CorrespondingTemplateParam =
+        TemplateTypeParmDecl::Create(Context, 
+        // Temporarily add to the TranslationUnit DeclContext.  When the 
+        // associated TemplateParameterList is attached to a template
+        // declaration (such as FunctionTemplateDecl), the DeclContext 
+        // for each template parameter gets updated appropriately via
+        // a call to AdoptTemplateParameterList. 
+        Context.getTranslationUnitDecl(), 
+        /*KeyLoc*/ SourceLocation(), 
+        /*NameLoc*/ declarator.getLocStart(),  
+        TemplateParameterDepth, 
+        AutoParameterPosition,  // our template param index 
+        /* Identifier*/ &TemplateParamII, false, IsParameterPack);
+      LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+      // Replace the 'auto' in the function parameter with this invented 
+      // template type parameter.
+      Result = QualType(CorrespondingTemplateParam->getTypeForDecl(), 0);  
+    } else {
+      Result = Context.getAutoType(QualType(), /*decltype(auto)*/false, false);
+    }
     break;
 
   case DeclSpec::TST_decltype_auto:
-    Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
+    Result = Context.getAutoType(QualType(), 
+                                 /*decltype(auto)*/true, 
+                                 /*IsDependent*/   false);
     break;
 
   case DeclSpec::TST_unknown_anytype:
@@ -1545,7 +1588,7 @@ QualType Sema::BuildArrayType(QualType T
         ASM = ArrayType::Normal;
       }
     } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
-               !T->isIncompleteType()) {
+               !T->isIncompleteType() && !T->isUndeducedType()) {
       // Is the array too large?
       unsigned ActiveSizeBits
         = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
@@ -2087,6 +2130,7 @@ static QualType GetDeclSpecTypeForDeclar
   // In C++11, a function declarator using 'auto' must have a trailing return
   // type (this is checked later) and we can skip this. In other languages
   // using auto, we need to check regardless.
+  // C++14 In generic lambdas allow 'auto' in their parameters.
   if (ContainsPlaceholderType &&
       (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {
     int Error = -1;
@@ -2099,7 +2143,12 @@ static QualType GetDeclSpecTypeForDeclar
     case Declarator::ObjCParameterContext:
     case Declarator::ObjCResultContext:
     case Declarator::PrototypeContext:
-      Error = 0; // Function prototype
+      Error = 0;  
+      break;
+    case Declarator::LambdaExprParameterContext:
+      if (!(SemaRef.getLangOpts().CPlusPlus1y 
+              && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))
+        Error = 14;
       break;
     case Declarator::MemberContext:
       if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
@@ -2179,8 +2228,10 @@ static QualType GetDeclSpecTypeForDeclar
       AutoRange = D.getName().getSourceRange();
 
     if (Error != -1) {
+      const bool IsDeclTypeAuto = 
+          D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto;
       SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
-        << Error << AutoRange;
+        << IsDeclTypeAuto << Error << AutoRange;
       T = SemaRef.Context.IntTy;
       D.setInvalidType(true);
     } else
@@ -2230,6 +2281,7 @@ static QualType GetDeclSpecTypeForDeclar
       D.setInvalidType(true);
       break;
     case Declarator::PrototypeContext:
+    case Declarator::LambdaExprParameterContext:
     case Declarator::ObjCParameterContext:
     case Declarator::ObjCResultContext:
     case Declarator::KNRTypeListContext:
@@ -2651,8 +2703,10 @@ static TypeSourceInfo *GetFullTypeForDec
           }
         }
       }
-
-      if (const AutoType *AT = T->getContainedAutoType()) {
+      const AutoType *AT = T->getContainedAutoType();
+      // Allow arrays of auto if we are a generic lambda parameter.
+      // i.e. [](auto (&array)[5]) { return array[0]; }; OK
+      if (AT && D.getContext() != Declarator::LambdaExprParameterContext) {
         // We've already diagnosed this for decltype(auto).
         if (!AT->isDecltypeAuto())
           S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
@@ -3151,6 +3205,7 @@ static TypeSourceInfo *GetFullTypeForDec
     //   is a parameter pack (14.5.3). [...]
     switch (D.getContext()) {
     case Declarator::PrototypeContext:
+    case Declarator::LambdaExprParameterContext:
       // C++0x [dcl.fct]p13:
       //   [...] When it is part of a parameter-declaration-clause, the
       //   parameter pack is a function parameter pack (14.5.3). The type T
@@ -3169,7 +3224,6 @@ static TypeSourceInfo *GetFullTypeForDec
         T = Context.getPackExpansionType(T, None);
       }
       break;
-
     case Declarator::TemplateParamContext:
       // C++0x [temp.param]p15:
       //   If a template-parameter is a [...] is a parameter-declaration that

Modified: cfe/trunk/lib/Sema/TreeTransform.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/TreeTransform.h (original)
+++ cfe/trunk/lib/Sema/TreeTransform.h Thu Sep 26 14:54:12 2013
@@ -787,7 +787,8 @@ public:
     // Note, IsDependent is always false here: we implicitly convert an 'auto'
     // which has been deduced to a dependent type into an undeduced 'auto', so
     // that we'll retry deduction after the transformation.
-    return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
+    return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto, 
+                                       /*IsDependent*/ false);
   }
 
   /// \brief Build a new template specialization type.
@@ -3514,7 +3515,8 @@ TreeTransform<Derived>::TransformQualifi
         Qs.removeObjCLifetime();
         Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
                                                    Qs);
-        Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto());
+        Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(), 
+                                AutoTy->isDependentType());
         TLB.TypeWasModifiedSafely(Result);
       } else {
         // Otherwise, complain about the addition of a qualifier to an
@@ -8249,6 +8251,14 @@ TreeTransform<Derived>::TransformCXXTemp
 template<typename Derived>
 ExprResult
 TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
+ 
+  // FIXME: Implement nested generic lambda transformations.
+  if (E->isGenericLambda()) {
+    getSema().Diag(E->getIntroducerRange().getBegin(), 
+      diag::err_glambda_not_fully_implemented) 
+      << " template transformation of generic lambdas not implemented yet";
+    return ExprError();
+  }
   // Transform the type of the lambda parameters and start the definition of
   // the lambda itself.
   TypeSourceInfo *MethodTy
@@ -8271,7 +8281,10 @@ TreeTransform<Derived>::TransformLambdaE
         E->getCallOperator()->param_size(),
         0, ParamTypes, &Params))
     return ExprError();
-
+  getSema().PushLambdaScope();
+  LambdaScopeInfo *LSI = getSema().getCurLambda();
+  // TODO: Fix for nested lambdas
+  LSI->GLTemplateParameterList = 0;
   // Build the call operator.
   CXXMethodDecl *CallOperator
     = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
@@ -8306,9 +8319,9 @@ TreeTransform<Derived>::TransformLambdaS
   // Introduce the context of the call operator.
   Sema::ContextRAII SavedContext(getSema(), CallOperator);
 
+  LambdaScopeInfo *const LSI = getSema().getCurLambda();
   // Enter the scope of the lambda.
-  sema::LambdaScopeInfo *LSI
-    = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
+  getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
                                  E->getCaptureDefault(),
                                  E->getCaptureDefaultLoc(),
                                  E->hasExplicitParameters(),

Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Thu Sep 26 14:54:12 2013
@@ -1213,6 +1213,7 @@ void ASTDeclReader::ReadCXXDefinitionDat
       = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
     Capture *ToCapture = Lambda.Captures;
     Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
+    Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
       SourceLocation Loc = ReadSourceLocation(Record, Idx);
       bool IsImplicit = Record[Idx++];

Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Thu Sep 26 14:54:12 2013
@@ -5134,6 +5134,7 @@ void ASTWriter::AddCXXDefinitionData(con
     Record.push_back(Lambda.ManglingNumber);
     AddDeclRef(Lambda.ContextDecl, Record);
     AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
+    AddStmt(Lambda.TheLambdaExpr);
     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
       LambdaExpr::Capture &Capture = Lambda.Captures[I];
       AddSourceLocation(Capture.getLocation(), Record);

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp?rev=191453&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp Thu Sep 26 14:54:12 2013
@@ -0,0 +1,74 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
+
+//FIXME: These tests were written when return type deduction had not been implemented
+// for generic lambdas, hence
+template<class T> T id(T t);
+template<class ... Ts> int vfoo(Ts&& ... ts);
+auto GL1 = [](auto a, int i) -> int { return id(a); };
+
+auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
+auto GL3 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); };
+
+auto GL4 = [](int i, char c, auto* ... As) -> int { return vfoo(As...); };
+
+
+void foo() {
+  auto GL1 = [](auto a, int i) -> int { return id(a); };
+
+  auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
+}
+
+int main()
+{
+  auto l1 = [](auto a) -> int { return a + 5; };
+  auto l2 = [](auto *p) -> int { return p + 5; };
+ 
+  struct A { int i; char f(int) { return 'c'; } };
+  auto l3 = [](auto &&ur, 
+                auto &lr, 
+                auto v, 
+                int i, 
+                auto* p,
+                auto A::*memvar,
+                auto (A::*memfun)(int),
+                char c,
+                decltype (v)* pv
+                , auto (&array)[5] 
+              ) -> int { return v + i + c
+                          + array[0]; 
+                       };
+  int arr[5] = {0, 1, 2, 3, 4 };
+  int lval = 0;
+  double d = 3.14;
+  l3(3, lval, d, lval, &lval, &A::i, &A::f, 'c', &d, arr);
+  auto l4 = [](decltype(auto) a) -> int { return 0; }; //expected-error{{decltype(auto)}}
+  {
+    struct Local {
+      static int ifi(int i) { return i; }
+      static char cfi(int) { return 'a'; }
+      static double dfi(int i) { return i + 3.14; }
+      static Local localfi(int) { return Local{}; }
+    };
+    auto l4 = [](auto (*fp)(int)) -> int { return fp(3); }; //expected-error{{no viable conversion from 'Local' to 'int'}} 
+    l4(&Local::ifi);
+    l4(&Local::cfi);
+    l4(&Local::dfi);
+    l4(&Local::localfi); //expected-note{{in instantiation of function template specialization}}  
+  }
+  {
+    auto unnamed_parameter = [](auto, auto) -> void { };
+    unnamed_parameter(3, '4');
+  }
+  {
+    auto l = [](auto 
+                      (*)(auto)) { }; //expected-error{{'auto' not allowed}}
+    //FIXME: These diagnostics might need some work.
+    auto l2 = [](char auto::*pm) { };  //expected-error{{cannot combine with previous}}\
+                                         expected-error{{'pm' does not point into a class}}
+    auto l3 = [](char (auto::*pmf)()) { };  //expected-error{{'auto' not allowed}}\
+                                              expected-error{{'pmf' does not point into a class}}\
+                                              expected-error{{function cannot return function type 'char ()'}}
+  }
+}
+
+

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp?rev=191453&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp Thu Sep 26 14:54:12 2013
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -emit-llvm
+namespace return_type_deduction_ok {
+ auto l = [](auto a) ->auto { return a; }(2); 
+ auto l2 = [](auto a) ->decltype(auto) { return a; }(2);  
+ auto l3 = [](auto a) { return a; }(2); 
+
+}
+
+namespace lambda_capturing {
+// FIXME: Once return type deduction is implemented for generic lambdas
+// this will need to be updated.
+void test() {
+  int i = 10;
+  auto L = [=](auto a) -> int { //expected-error{{unimplemented}}
+    return i + a;
+  };
+  L(3); 
+}
+
+}
+
+namespace nested_generic_lambdas {
+void test() {
+  auto L = [](auto a) -> int {
+    auto M = [](auto b, decltype(a) b2) -> int { //expected-error{{unimplemented}}
+      return 1;
+    };
+    M(a, a);
+  };
+  L(3); //expected-note{{in instantiation of}}
+}
+template<class T> void foo(T) {
+ auto L = [](auto a) { return a; }; //expected-error{{unimplemented}}
+}
+template void foo(int); //expected-note{{in instantiation of}}
+}
+
+namespace conversion_operator {
+void test() {
+    auto L = [](auto a) -> int { return a; };
+    int (*fp)(int) = L;  //expected-error{{no viable conversion}}
+  }
+}
+
+namespace generic_lambda_as_default_argument_ok {
+  void test(int i = [](auto a)->int { return a; }(3)) {
+  
+  }
+  
+}
+

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=191453&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp Thu Sep 26 14:54:12 2013
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
+
+// prvalue
+void prvalue() {
+  auto&& x = [](auto a)->void { };
+  auto& y = [](auto *a)->void { }; // expected-error{{cannot bind to a temporary of type}}
+}
+
+namespace std {
+  class type_info;
+}
+
+struct P {
+  virtual ~P();
+};
+
+void unevaluated_operand(P &p, int i) {
+  // FIXME: this should only emit one error.
+  int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \
+                                                       // expected-error{{invalid application of 'sizeof'}}
+  const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i));
+  const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i));  // expected-error{{lambda expression in an unevaluated operand}}
+}

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp Thu Sep 26 14:54:12 2013
@@ -7,3 +7,60 @@ int &d = [] (int &r) -> auto & { return
 int &e = [] (int &r) -> auto { return r; } (a); // expected-error {{cannot bind to a temporary}}
 int &f = [] (int r) -> decltype(auto) { return r; } (a); // expected-error {{cannot bind to a temporary}}
 int &g = [] (int r) -> decltype(auto) { return (r); } (a); // expected-warning {{reference to stack}}
+
+
+int test_explicit_auto_return() 
+{
+    struct X {};
+    auto L = [](auto F, auto a) { return F(a); };
+    auto M = [](auto a) -> auto { return a; }; // OK
+    auto MRef = [](auto b) -> auto& { return b; }; //expected-warning{{reference to stack}}
+    auto MPtr = [](auto c) -> auto* { return &c; }; //expected-warning{{address of stack}}
+    auto MDeclType = [](auto&& d) -> decltype(auto) { return static_cast<decltype(d)>(d); }; //OK
+    M(3);
+    
+    auto &&x = MDeclType(X{});
+    auto &&x1 = M(X{});
+    auto &&x2 = MRef(X{});//expected-note{{in instantiation of}}
+    auto &&x3 = MPtr(X{}); //expected-note{{in instantiation of}}
+    return 0;    
+}
+
+int test_implicit_auto_return() 
+{  
+  {
+    auto M = [](auto a) { return a; };
+    struct X {};
+    X x = M(X{});
+    
+  }
+}
+ 
+int test_multiple_returns()  {
+    auto M = [](auto a) { 
+      bool k;
+      if (k)
+        return a;
+      else
+        return 5; //expected-error{{deduced as 'int' here}}
+    }; 
+    M(3); // OK
+    M('a'); //expected-note{{in instantiation of}}
+  return 0;
+}
+int test_no_parameter_list()
+{
+  static int si = 0;
+    auto M = [] { return 5; }; // OK
+    auto M2 = [] -> auto&& { return si; }; // expected-error{{lambda requires '()'}}
+    M();
+}
+
+int test_conditional_in_return() {
+  auto Fac = [](auto f, auto n) { 
+    return n <= 0 ? n : f(f, n - 1) * n;
+  };
+  // FIXME: this test causes a recursive limit - need to error more gracefully.
+  //Fac(Fac, 3);
+
+}
\ No newline at end of file

Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp?rev=191453&r1=191452&r2=191453&view=diff
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp (original)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp Thu Sep 26 14:54:12 2013
@@ -1,5 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
-// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
+// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -DCPP1Y
 
 void missing_lambda_declarator() {
   [](){}();
@@ -18,7 +18,7 @@ void infer_void_return_type(int i) {
     switch (x) {
     case 0: return get<void>();
     case 1: return;
-    case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}}
+    case 2: return { 1, 2.0 }; //expected-error{{cannot deduce}}
     }
   }(7);
 }

Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=191453&view=auto
==============================================================================
--- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp (added)
+++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp Thu Sep 26 14:54:12 2013
@@ -0,0 +1,135 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y -emit-llvm
+
+namespace test_factorial {
+
+auto Fact = [](auto Self, unsigned n) -> unsigned {
+    return !n ? 1 : Self(Self, n - 1) * n;
+};
+
+auto six = Fact(Fact, 3);
+
+}
+
+namespace overload_generic_lambda {
+  template <class F1, class F2> struct overload : F1, F2 {
+    using F1::operator();
+    using F2::operator();
+    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
+  };
+
+  auto NumParams = [](auto Self, auto h, auto ... rest) -> unsigned {
+    return 1 + Self(Self, rest...);
+  };
+  auto Base = [](auto Self, auto h) -> unsigned {
+      return 1;
+  };
+  overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);
+  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');
+}
+
+
+namespace overload_generic_lambda_return_type_deduction {
+  template <class F1, class F2> struct overload : F1, F2 {
+    using F1::operator();
+    using F2::operator();
+    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
+  };
+
+  auto NumParams = [](auto Self, auto h, auto ... rest) {
+    return 1 + Self(Self, rest...);
+  };
+  auto Base = [](auto Self, auto h) {
+      return 1;
+  };
+  overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);
+  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');
+}
+
+namespace test_standard_p5 {
+// FIXME: This test should eventually compile without an explicit trailing return type
+auto glambda = [](auto a, auto&& b) ->bool { return a < b; };
+bool b = glambda(3, 3.14); // OK
+
+}
+namespace test_deduction_failure {
+ int test() {
+   auto g = [](auto *a) { //expected-note{{candidate template ignored}}
+    return a;
+   };
+   struct X { };
+   X *x;
+   g(x);
+   g(3); //expected-error{{no matching function}}
+   return 0;
+ }
+
+}
+  
+namespace test_instantiation_or_sfinae_failure {
+int test2() {
+  {
+    auto L = [](auto *a) { 
+                return (*a)(a); }; //expected-error{{called object type 'double' is not a function}}
+    //l(&l);
+    double d;
+    L(&d); //expected-note{{in instantiation of}}
+    auto M = [](auto b) { return b; };
+    L(&M); // ok
+  }
+  {
+    auto L = [](auto *a) ->decltype (a->foo()) { //expected-note2{{candidate template ignored:}}
+                return (*a)(a); }; 
+    //l(&l);
+    double d;
+    L(&d); //expected-error{{no matching function for call}} 
+    auto M = [](auto b) { return b; };
+    L(&M); //expected-error{{no matching function for call}} 
+ 
+  }
+  return 0;
+}
+
+
+}
+  
+namespace test_misc {
+auto GL = [](auto a, decltype(a) b) //expected-note{{candidate function}} 
+                -> int { return a + b; };
+
+void test() {
+   struct X { };
+   GL(3, X{}); //expected-error{{no matching function}}
+}
+
+void test2() {
+  auto l = [](auto *a) -> int { 
+              (*a)(a); return 0; }; //expected-error{{called object type 'double' is not a function}}
+  l(&l);
+  double d;
+  l(&d); //expected-note{{in instantiation of}}
+}
+
+}
+
+namespace nested_lambdas {
+  int test() {
+    auto L = [](auto a) {
+                 return [=](auto b) {  //expected-error{{unimplemented}}
+                           return a + b;
+                        };
+              };
+   // auto M = L(3.14);
+   // return M('4');    
+  }
+  auto get_lambda() {
+    return [](auto a) {
+      return a; 
+    };
+  };
+  
+  int test2() {
+    auto L = get_lambda();
+    L(3);
+  }
+}
+





More information about the cfe-commits mailing list