<div dir="ltr">Rolled back in r189004 as it appears to not have been fully reviewed / lgtm'ed (see the review thread) and violates a layering restriction.</div><div class="gmail_extra"><br><br><div class="gmail_quote">
On Thu, Aug 22, 2013 at 4:02 AM, Juergen Ributzka <span dir="ltr"><<a href="mailto:juergen@apple.com" target="_blank">juergen@apple.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I got two warning messages about unused variables ;-)<br>
<br>
llvm/tools/clang/lib/Sema/SemaLambda.cpp:146:12: warning: unused variable 'AutoTy' [-Wunused-variable]<br>
  QualType AutoTy = PVD->getType();<br>
           ^<br>
1 warning generated.<br>
llvm/tools/clang/lib/Parse/ParseExprCXX.cpp:941:30: warning: unused variable 'LSI' [-Wunused-variable]<br>
      sema::LambdaScopeInfo *LSI = Actions.getCurLambda();<br>
<br>
On Aug 21, 2013, at 6:49 PM, Faisal Vali <<a href="mailto:faisalv@yahoo.com">faisalv@yahoo.com</a>> wrote:<br>
<br>
> Author: faisalv<br>
> Date: Wed Aug 21 20:49:11 2013<br>
> New Revision: 188977<br>
><br>
> URL: <a href="http://llvm.org/viewvc/llvm-project?rev=188977&view=rev" target="_blank">http://llvm.org/viewvc/llvm-project?rev=188977&view=rev</a><br>
> Log:<br>
> Implement a rudimentary form of generic lambdas.<br>
><br>
> Specifically, the following features are not included in this commit:<br>
>  - any sort of capturing within generic lambdas<br>
>  - nested lambdas<br>
>  - conversion operator for captureless lambdas<br>
>  - ensuring all visitors are generic lambda aware<br>
><br>
><br>
> As an example of what compiles:<br>
><br>
> template <class F1, class F2><br>
> struct overload : F1, F2 {<br>
>    using F1::operator();<br>
>    using F2::operator();<br>
>    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }<br>
>  };<br>
><br>
>  auto Recursive = [](auto Self, auto h, auto ... rest) {<br>
>    return 1 + Self(Self, rest...);<br>
>  };<br>
>  auto Base = [](auto Self, auto h) {<br>
>      return 1;<br>
>  };<br>
>  overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);<br>
>  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');<br>
><br>
> Please see attached tests for more examples.<br>
><br>
> Some implementation notes:<br>
><br>
>  - Add a new Declarator context => LambdaExprParameterContext to<br>
>    clang::Declarator to allow the use of 'auto' in declaring generic<br>
>    lambda parameters<br>
><br>
>  - Augment AutoType's constructor (similar to how variadic<br>
>    template-type-parameters ala TemplateTypeParmDecl are implemented) to<br>
>    accept an IsParameterPack to encode a generic lambda parameter pack.<br>
><br>
>  - Add various helpers to CXXRecordDecl to facilitate identifying<br>
>    and querying a closure class<br>
><br>
>  - LambdaScopeInfo (which maintains the current lambda's Sema state)<br>
>    was augmented to house the current depth of the template being<br>
>    parsed (id est the Parser calls Sema::RecordParsingTemplateParameterDepth)<br>
>    so that Sema::ActOnLambdaAutoParameter may use it to create the<br>
>    appropriate list of corresponding TemplateTypeParmDecl for each<br>
>    auto parameter identified within the generic lambda (also stored<br>
>    within the current LambdaScopeInfo).  Additionally,<br>
>    a TemplateParameterList data-member was added to hold the invented<br>
>    TemplateParameterList AST node which will be much more useful<br>
>    once we teach TreeTransform how to transform generic lambdas.<br>
><br>
>  - SemaLambda.h was added to hold some common lambda utility<br>
>    functions (this file is likely to grow ...)<br>
><br>
>  - Teach Sema::ActOnStartOfFunctionDef to check whether it<br>
>    is being called to instantiate a generic lambda's call<br>
>    operator, and if so, push an appropriately prepared<br>
>    LambdaScopeInfo object on the stack.<br>
><br>
>  - Teach Sema::ActOnStartOfLambdaDefinition to set the<br>
>    return type of a lambda without a trailing return type<br>
>    to 'auto' in C++1y mode, and teach the return type<br>
>    deduction machinery in SemaStmt.cpp to process either<br>
>    C++11 and C++14 lambda's correctly depending on the flag.<br>
><br>
>  - various tests were added - but much more will be needed.<br>
><br>
> A greatful thanks to all reviewers including Eli Friedman,<br>
> James Dennett and the ever illuminating Richard Smith.  And<br>
> yet I am certain that I have allowed unidentified bugs to creep in;<br>
> bugs, that I will do my best to slay, once identified!<br>
><br>
> Thanks!<br>
><br>
><br>
><br>
> Added:<br>
>    cfe/trunk/include/clang/Sema/SemaLambda.h<br>
>    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp<br>
> Modified:<br>
>    cfe/trunk/include/clang/AST/ASTContext.h<br>
>    cfe/trunk/include/clang/AST/DeclCXX.h<br>
>    cfe/trunk/include/clang/AST/ExprCXX.h<br>
>    cfe/trunk/include/clang/AST/Type.h<br>
>    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
>    cfe/trunk/include/clang/Sema/DeclSpec.h<br>
>    cfe/trunk/include/clang/Sema/ScopeInfo.h<br>
>    cfe/trunk/include/clang/Sema/Sema.h<br>
>    cfe/trunk/lib/AST/ASTContext.cpp<br>
>    cfe/trunk/lib/AST/ASTImporter.cpp<br>
>    cfe/trunk/lib/AST/DeclCXX.cpp<br>
>    cfe/trunk/lib/AST/ExprCXX.cpp<br>
>    cfe/trunk/lib/AST/Type.cpp<br>
>    cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
>    cfe/trunk/lib/Parse/ParseDecl.cpp<br>
>    cfe/trunk/lib/Parse/ParseExprCXX.cpp<br>
>    cfe/trunk/lib/Parse/Parser.cpp<br>
>    cfe/trunk/lib/Sema/Sema.cpp<br>
>    cfe/trunk/lib/Sema/SemaDecl.cpp<br>
>    cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
>    cfe/trunk/lib/Sema/SemaLambda.cpp<br>
>    cfe/trunk/lib/Sema/SemaOverload.cpp<br>
>    cfe/trunk/lib/Sema/SemaStmt.cpp<br>
>    cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp<br>
>    cfe/trunk/lib/Sema/SemaType.cpp<br>
>    cfe/trunk/lib/Sema/TreeTransform.h<br>
>    cfe/trunk/lib/Serialization/ASTReader.cpp<br>
>    cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
>    cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp<br>
>    cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp<br>
><br>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)<br>
> +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Aug 21 20:49:11 2013<br>
> @@ -1115,7 +1115,7 @@ public:<br>
><br>
>   /// \brief C++11 deduced auto type.<br>
>   QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,<br>
> -                       bool IsDependent = false) const;<br>
> +                       bool IsDependent, bool IsParameterPack) const;<br>
><br>
>   /// \brief C++11 deduction pattern for 'auto' type.<br>
>   QualType getAutoDeductType() const;<br>
><br>
> Modified: cfe/trunk/include/clang/AST/DeclCXX.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

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

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/ExprCXX.h (original)<br>
> +++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Aug 21 20:49:11 2013<br>
> @@ -1605,6 +1605,13 @@ public:<br>
>   /// lambda expression.<br>
>   CXXMethodDecl *getCallOperator() const;<br>
><br>
> +  /// \brief If this is a generic lambda expression, retrieve the template<br>
> +  /// parameter list associated with it, or else return null.<br>
> +  TemplateParameterList *getTemplateParameterList() const;<br>
> +<br>
> +  /// \brief Whether this is a generic lambda.<br>
> +  bool isGenericLambda() const { return !!getTemplateParameterList(); }<br>
> +<br>
>   /// \brief Retrieve the body of the lambda.<br>
>   CompoundStmt *getBody() const;<br>
><br>
><br>
> Modified: cfe/trunk/include/clang/AST/Type.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/AST/Type.h (original)<br>
> +++ cfe/trunk/include/clang/AST/Type.h Wed Aug 21 20:49:11 2013<br>
> @@ -3614,10 +3614,11 @@ public:<br>
> /// is no deduced type and an auto type is canonical. In the latter case, it is<br>
> /// also a dependent type.<br>
> class AutoType : public Type, public llvm::FoldingSetNode {<br>
> -  AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)<br>
> +  AutoType(QualType DeducedType, bool IsDecltypeAuto,<br>
> +           bool IsDependent, bool IsParameterPack)<br>
>     : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,<br>
>            /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent,<br>
> -           /*VariablyModified=*/false, /*ContainsParameterPack=*/false) {<br>
> +           /*VariablyModified=*/false, /*ContainsParameterPack=*/IsParameterPack) {<br>
>     assert((DeducedType.isNull() || !IsDependent) &&<br>
>            "auto deduced to dependent type");<br>
>     AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;<br>
> @@ -3641,14 +3642,17 @@ public:<br>
>   }<br>
><br>
>   void Profile(llvm::FoldingSetNodeID &ID) {<br>
> -    Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());<br>
> +    Profile(ID, getDeducedType(), isDecltypeAuto(),<br>
> +                 isDependentType(), containsUnexpandedParameterPack());<br>
>   }<br>
><br>
>   static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,<br>
> -                      bool IsDecltypeAuto, bool IsDependent) {<br>
> +                      bool IsDecltypeAuto, bool IsDependent,<br>
> +                      bool IsParameterPack) {<br>
>     ID.AddPointer(Deduced.getAsOpaquePtr());<br>
>     ID.AddBoolean(IsDecltypeAuto);<br>
>     ID.AddBoolean(IsDependent);<br>
> +    ID.AddBoolean(IsParameterPack);<br>
>   }<br>
><br>
>   static bool classof(const Type *T) {<br>
><br>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Aug 21 20:49:11 2013<br>
> @@ -5050,6 +5050,10 @@ let CategoryName = "Lambda Issue" in {<br>
>     "cannot deduce type for lambda capture %0 from initializer list">;<br>
> }<br>
><br>
> +// C++1y Generic Lambdas<br>
> +def err_glambda_not_fully_implemented : Error<<br>
> +  "unimplemented generic lambda feature: %0">;<br>
> +<br>
> def err_return_in_captured_stmt : Error<<br>
>   "cannot return from %0">;<br>
> def err_capture_block_variable : Error<<br>
><br>
> Modified: cfe/trunk/include/clang/Sema/DeclSpec.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

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

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/ScopeInfo.h Wed Aug 21 20:49:11 2013<br>
> @@ -35,6 +35,8 @@ class LabelDecl;<br>
> class ReturnStmt;<br>
> class Scope;<br>
> class SwitchStmt;<br>
> +class TemplateTypeParmDecl;<br>
> +class TemplateParameterList;<br>
> class VarDecl;<br>
> class DeclRefExpr;<br>
> class ObjCIvarRefExpr;<br>
> @@ -613,12 +615,27 @@ public:<br>
>   /// \brief Offsets into the ArrayIndexVars array at which each capture starts<br>
>   /// its list of array index variables.<br>
>   SmallVector<unsigned, 4> ArrayIndexStarts;<br>
> +<br>
> +  /// \brief If this is a generic lambda, use this as the depth of<br>
> +  /// each 'auto' parameter, during initial AST construction.<br>
> +  unsigned AutoTemplateParameterDepth;<br>
> +<br>
> +  // If this is a generic lambda, store the list of the auto<br>
> +  // parameters converted into TemplateTypeParmDecls into a vector<br>
> +  // that can be used to construct the generic lambda's template<br>
> +  // parameter list, during initial AST construction.<br>
> +  /// \brief Store the list of the auto parameters for a generic lambda.<br>
> +  SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;<br>
><br>
> -  LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,<br>
> -                  CXXMethodDecl *CallOperator)<br>
> -    : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),<br>
> -      CallOperator(CallOperator), NumExplicitCaptures(0), Mutable(false),<br>
> -      ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)<br>
> +  // If this is a generic lambda, store its template parameter list.<br>
> +  TemplateParameterList *GLTemplateParameterList;<br>
> +<br>
> +  LambdaScopeInfo(DiagnosticsEngine &Diag)<br>
> +    : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),<br>
> +      CallOperator(0), NumExplicitCaptures(0), Mutable(false),<br>
> +      ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),<br>
> +      AutoTemplateParameterDepth(0),<br>
> +      GLTemplateParameterList(0)<br>
>   {<br>
>     Kind = SK_Lambda;<br>
>   }<br>
> @@ -631,8 +648,10 @@ public:<br>
>   }<br>
><br>
>   static bool classof(const FunctionScopeInfo *FSI) {<br>
> -    return FSI->Kind == SK_Lambda;<br>
> +    return FSI->Kind == SK_Lambda;<br>
>   }<br>
> +<br>
> +<br>
> };<br>
><br>
><br>
><br>
> Modified: cfe/trunk/include/clang/Sema/Sema.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/Sema.h (original)<br>
> +++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 21 20:49:11 2013<br>
> @@ -969,7 +969,13 @@ public:<br>
><br>
>   void PushFunctionScope();<br>
>   void PushBlockScope(Scope *BlockScope, BlockDecl *Block);<br>
> -  void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl *CallOperator);<br>
> +  void PushLambdaScope();<br>
> +<br>
> +  // This is used to inform Sema what the current TemplateParameterDepth<br>
> +  // is during Parsing.  Currently it is used to pass on the depth<br>
> +  // when parsing generic lambda 'auto' parameters.<br>
> +  void RecordParsingTemplateParameterDepth(unsigned Depth);<br>
> +<br>
>   void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,<br>
>                                RecordDecl *RD,<br>
>                                CapturedRegionKind K);<br>
> @@ -996,9 +1002,12 @@ public:<br>
>   /// \brief Retrieve the current block, if any.<br>
>   sema::BlockScopeInfo *getCurBlock();<br>
><br>
> -  /// \brief Retrieve the current lambda expression, if any.<br>
> +  /// \brief Retrieve the current lambda scope info, if any.<br>
>   sema::LambdaScopeInfo *getCurLambda();<br>
><br>
> +  /// \brief Retrieve the current generic lambda info, if any.<br>
> +  sema::LambdaScopeInfo *getCurGenericLambda();<br>
> +<br>
>   /// \brief Retrieve the current captured region, if any.<br>
>   sema::CapturedRegionScopeInfo *getCurCapturedRegion();<br>
><br>
> @@ -4402,6 +4411,10 @@ public:<br>
>   /// initializer for the declaration 'Dcl'.<br>
>   void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);<br>
><br>
> +  /// \brief Invoked when an auto parameter is parsed<br>
> +  /// in a lambda's parameter declaration clause.<br>
> +  ParmVarDecl *ActOnLambdaAutoParameter(ParmVarDecl *P);<br>
> +<br>
>   /// \brief Create a new lambda closure type.<br>
>   CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,<br>
>                                          TypeSourceInfo *Info,<br>
> @@ -4414,14 +4427,15 @@ public:<br>
>                                        SourceLocation EndLoc,<br>
>                                        ArrayRef<ParmVarDecl *> Params);<br>
><br>
> -  /// \brief Introduce the scope for a lambda expression.<br>
> -  sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,<br>
> -                                          SourceRange IntroducerRange,<br>
> -                                          LambdaCaptureDefault CaptureDefault,<br>
> -                                          SourceLocation CaptureDefaultLoc,<br>
> -                                          bool ExplicitParams,<br>
> -                                          bool ExplicitResultType,<br>
> -                                          bool Mutable);<br>
> +  /// \brief Endow the lambda scope info with the relevant properties.<br>
> +  void buildLambdaScope(sema::LambdaScopeInfo *LSI,<br>
> +                        CXXMethodDecl *CallOperator,<br>
> +                        SourceRange IntroducerRange,<br>
> +                        LambdaCaptureDefault CaptureDefault,<br>
> +                        SourceLocation CaptureDefaultLoc,<br>
> +                        bool ExplicitParams,<br>
> +                        bool ExplicitResultType,<br>
> +                        bool Mutable);<br>
><br>
>   /// \brief Check and build an init-capture with the specified name and<br>
>   /// initializer.<br>
> @@ -5806,6 +5820,12 @@ public:<br>
>                           sema::TemplateDeductionInfo &Info,<br>
>                           bool InOverloadResolution = false);<br>
><br>
> +  /// \brief Substitute Replacement for \p auto in \p TypeWithAuto<br>
> +  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);<br>
> +  /// \brief Substitute Replacement for auto in TypeWithAuto<br>
> +  TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,<br>
> +                                          QualType Replacement);<br>
> +<br>
>   /// \brief Result type of DeduceAutoType.<br>
>   enum DeduceAutoResult {<br>
>     DAR_Succeeded,<br>
> @@ -5817,7 +5837,6 @@ public:<br>
>                                   QualType &Result);<br>
>   DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr *&Initializer,<br>
>                                   QualType &Result);<br>
> -  QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);<br>
>   void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);<br>
>   bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,<br>
>                         bool Diagnose = true);<br>
><br>
> Added: cfe/trunk/include/clang/Sema/SemaLambda.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaLambda.h?rev=188977&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaLambda.h?rev=188977&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/include/clang/Sema/SemaLambda.h (added)<br>
> +++ cfe/trunk/include/clang/Sema/SemaLambda.h Wed Aug 21 20:49:11 2013<br>
> @@ -0,0 +1,44 @@<br>
> +//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++ -*-===//<br>
> +//<br>
> +//                     The LLVM Compiler Infrastructure<br>
> +//<br>
> +// This file is distributed under the University of Illinois Open Source<br>
> +// License. See LICENSE.TXT for details.<br>
> +//<br>
> +//===----------------------------------------------------------------------===//<br>
> +///<br>
> +/// \file<br>
> +/// \brief This file provides some common utility functions for processing<br>
> +/// Lambdas.<br>
> +///<br>
> +//===----------------------------------------------------------------------===//<br>
> +<br>
> +#ifndef LLVM_CLANG_SEMA_LAMBDA_H<br>
> +#define LLVM_CLANG_SEMA_LAMBDA_H<br>
> +<br>
> +#include "clang/AST/DeclCXX.h"<br>
> +#include "clang/AST/DeclTemplate.h"<br>
> +#include "clang/Sema/ScopeInfo.h"<br>
> +<br>
> +namespace clang {<br>
> +static inline const char *getLambdaStaticInvokerName() {<br>
> +  return "__invoke";<br>
> +}<br>
> +static inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {<br>
> +  if (MD) {<br>
> +    CXXRecordDecl *LambdaClass = MD->getParent();<br>
> +    if (LambdaClass && LambdaClass->isGenericLambda()) {<br>
> +      return LambdaClass->getLambdaCallOperator()<br>
> +                  == MD->getTemplateInstantiationPattern();<br>
> +    }<br>
> +  }<br>
> +  return false;<br>
> +}<br>
> +<br>
> +static inline bool isGenericLambdaCallOperatorSpecialization(Decl *D) {<br>
> +  return isGenericLambdaCallOperatorSpecialization(<br>
> +                                dyn_cast<CXXMethodDecl>(D));<br>
> +}<br>
> +} // clang<br>
> +<br>
> +#endif // LLVM_CLANG_SEMA_LAMBDA_H<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -3649,20 +3649,24 @@ QualType ASTContext::getUnaryTransformTy<br>
> /// deduced to the given type, or to the canonical undeduced 'auto' type, or the<br>
> /// canonical deduced-but-dependent 'auto' type.<br>
> QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto,<br>
> -                                 bool IsDependent) const {<br>
> -  if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)<br>
> +                             bool IsDependent, bool IsParameterPack) const {<br>
> +  if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent &&<br>
> +                              !IsParameterPack)<br>
>     return getAutoDeductType();<br>
> -<br>
> +  assert(!IsParameterPack || DeducedType.isNull()<br>
> +           && "Auto parameter pack: auto ... a should always be undeduced!");<br>
>   // Look in the folding set for an existing type.<br>
>   void *InsertPos = 0;<br>
>   llvm::FoldingSetNodeID ID;<br>
> -  AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);<br>
> +  AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent,<br>
> +     IsParameterPack);<br>
>   if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))<br>
>     return QualType(AT, 0);<br>
><br>
>   AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,<br>
>                                                      IsDecltypeAuto,<br>
> -                                                     IsDependent);<br>
> +                                                     IsDependent,<br>
> +                                                     IsParameterPack);<br>
>   Types.push_back(AT);<br>
>   if (InsertPos)<br>
>     AutoTypes.InsertNode(AT, InsertPos);<br>
> @@ -3702,7 +3706,8 @@ QualType ASTContext::getAutoDeductType()<br>
>   if (AutoDeductTy.isNull())<br>
>     AutoDeductTy = QualType(<br>
>       new (*this, TypeAlignment) AutoType(QualType(), /*decltype(auto)*/false,<br>
> -                                          /*dependent*/false),<br>
> +                                          /*dependent*/false,<br>
> +                                          /*IsParameterPack*/false),<br>
>       0);<br>
>   return AutoDeductTy;<br>
> }<br>
><br>
> Modified: cfe/trunk/lib/AST/ASTImporter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ASTImporter.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1709,7 +1709,9 @@ QualType ASTNodeImporter::VisitAutoType(<br>
>       return QualType();<br>
>   }<br>
><br>
> -  return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto());<br>
> +  return Importer.getToContext().getAutoType(ToDeduced, T->isDecltypeAuto(),<br>
> +                                             /*IsDependent*/false,<br>
> +                                      T->containsUnexpandedParameterPack());<br>
> }<br>
><br>
> QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {<br>
><br>
> Modified: cfe/trunk/lib/AST/DeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/DeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -20,6 +20,7 @@<br>
> #include "clang/AST/ExprCXX.h"<br>
> #include "clang/AST/TypeLoc.h"<br>
> #include "clang/Basic/IdentifierTable.h"<br>
> +#include "clang/Sema/SemaLambda.h"<br>
> #include "llvm/ADT/STLExtras.h"<br>
> #include "llvm/ADT/SmallPtrSet.h"<br>
> using namespace clang;<br>
> @@ -930,6 +931,40 @@ bool CXXRecordDecl::isCLike() const {<br>
>   return isPOD() && data().HasOnlyCMembers;<br>
> }<br>
><br>
> +bool CXXRecordDecl::isGenericLambda() const {<br>
> +  return isLambda() &&<br>
> +      getLambdaCallOperator()->getDescribedFunctionTemplate();<br>
> +}<br>
> +<br>
> +CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {<br>
> +  if (!isLambda()) return 0;<br>
> +  DeclarationName Name =<br>
> +    getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);<br>
> +  DeclContext::lookup_const_result Calls = lookup(Name);<br>
> +<br>
> +  assert(!Calls.empty() && "Missing lambda call operator!");<br>
> +  assert(Calls.size() == 1 && "More than one lambda call operator!");<br>
> +<br>
> +  NamedDecl *CallOp = Calls.front();<br>
> +  if (FunctionTemplateDecl *CallOpTmpl =<br>
> +                    dyn_cast<FunctionTemplateDecl>(CallOp))<br>
> +    return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());<br>
> +<br>
> +  return cast<CXXMethodDecl>(CallOp);<br>
> +}<br>
> +<br>
> +CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {<br>
> +  if (!isLambda()) return 0;<br>
> +  DeclarationName Name =<br>
> +    &getASTContext().Idents.get(getLambdaStaticInvokerName());<br>
> +  DeclContext::lookup_const_result Invoker = lookup(Name);<br>
> +  if (Invoker.empty()) return 0;<br>
> +  assert(Invoker.size() == 1 && "More than one static invoker operator!");<br>
> +  CXXMethodDecl *Result = cast<CXXMethodDecl>(Invoker.front());<br>
> +  return Result;<br>
> +<br>
> +}<br>
> +<br>
> void CXXRecordDecl::getCaptureFields(<br>
>        llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,<br>
>        FieldDecl *&ThisCapture) const {<br>
> @@ -947,6 +982,14 @@ void CXXRecordDecl::getCaptureFields(<br>
>   }<br>
> }<br>
><br>
> +TemplateParameterList*<br>
> +        CXXRecordDecl::getGenericLambdaTemplateParameterList() const {<br>
> +  if (!isLambda()) return 0;<br>
> +  CXXMethodDecl *CallOp = getLambdaCallOperator();<br>
> +  if (FunctionTemplateDecl *Tmpl = CallOp->getDescribedFunctionTemplate())<br>
> +    return Tmpl->getTemplateParameters();<br>
> +  return 0;<br>
> +}<br>
><br>
> static CanQualType GetConversionType(ASTContext &Context, NamedDecl *Conv) {<br>
>   QualType T;<br>
> @@ -1493,7 +1536,7 @@ bool CXXMethodDecl::hasInlineBody() cons<br>
><br>
> bool CXXMethodDecl::isLambdaStaticInvoker() const {<br>
>   return getParent()->isLambda() &&<br>
> -         getIdentifier() && getIdentifier()->getName() == "__invoke";<br>
> +         getParent()->getLambdaStaticInvoker() == this;<br>
> }<br>
><br>
><br>
><br>
> Modified: cfe/trunk/lib/AST/ExprCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/ExprCXX.cpp (original)<br>
> +++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1026,13 +1026,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClas<br>
><br>
> CXXMethodDecl *LambdaExpr::getCallOperator() const {<br>
>   CXXRecordDecl *Record = getLambdaClass();<br>
> -  DeclarationName Name<br>
> -    = Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);<br>
> -  DeclContext::lookup_result Calls = Record->lookup(Name);<br>
> -  assert(!Calls.empty() && "Missing lambda call operator!");<br>
> -  assert(Calls.size() == 1 && "More than one lambda call operator!");<br>
> -  CXXMethodDecl *Result = cast<CXXMethodDecl>(Calls.front());<br>
> -  return Result;<br>
> +  return Record->getLambdaCallOperator();<br>
> +}<br>
> +<br>
> +TemplateParameterList *LambdaExpr::getTemplateParameterList() const {<br>
> +  CXXRecordDecl *Record = getLambdaClass();<br>
> +  return Record->getGenericLambdaTemplateParameterList();<br>
> +<br>
> }<br>
><br>
> CompoundStmt *LambdaExpr::getBody() const {<br>
><br>
> Modified: cfe/trunk/lib/AST/Type.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/AST/Type.cpp (original)<br>
> +++ cfe/trunk/lib/AST/Type.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -589,6 +589,10 @@ namespace {<br>
>     AutoType *VisitAttributedType(const AttributedType *T) {<br>
>       return Visit(T->getModifiedType());<br>
>     }<br>
> +    AutoType *VisitPackExpansionType(const PackExpansionType *T) {<br>
> +      return Visit(T->getPattern());<br>
> +    }<br>
> +<br>
>   };<br>
> }<br>
><br>
><br>
> Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)<br>
> +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -700,7 +700,7 @@ void CodeGenFunction::GenerateCode(Globa<br>
>     EmitLambdaToBlockPointerBody(Args);<br>
>   } else if (isa<CXXMethodDecl>(FD) &&<br>
>              cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {<br>
> -    // The lambda "__invoke" function is special, because it forwards or<br>
> +    // The lambda static invoker function is special, because it forwards or<br>
>     // clones the body of the function call operator (but is actually static).<br>
>     EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));<br>
>   } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&<br>
><br>
> Modified: cfe/trunk/lib/Parse/ParseDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

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

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -20,6 +20,7 @@<br>
> #include "clang/Sema/ParsedTemplate.h"<br>
> #include "clang/Sema/Scope.h"<br>
> #include "llvm/Support/ErrorHandling.h"<br>
> +#include "clang/AST/DeclTemplate.h"<br>
><br>
> using namespace clang;<br>
><br>
> @@ -908,12 +909,16 @@ ExprResult Parser::ParseLambdaExpression<br>
>   PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,<br>
>                                 "lambda expression parsing");<br>
><br>
> +<br>
> +<br>
>   // FIXME: Call into Actions to add any init-capture declarations to the<br>
>   // scope while parsing the lambda-declarator and compound-statement.<br>
><br>
>   // Parse lambda-declarator[opt].<br>
>   DeclSpec DS(AttrFactory);<br>
>   Declarator D(DS, Declarator::LambdaExprContext);<br>
> +  TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);<br>
> +  Actions.PushLambdaScope();<br>
><br>
>   if (Tok.is(tok::l_paren)) {<br>
>     ParseScope PrototypeScope(this,<br>
> @@ -931,9 +936,17 @@ ExprResult Parser::ParseLambdaExpression<br>
>     SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;<br>
>     SourceLocation EllipsisLoc;<br>
><br>
> -    if (Tok.isNot(tok::r_paren))<br>
> +<br>
> +    if (Tok.isNot(tok::r_paren)) {<br>
> +      sema::LambdaScopeInfo *LSI = Actions.getCurLambda();<br>
> +      if (getLangOpts().CPlusPlus1y)<br>
> +        Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);<br>
>       ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);<br>
> -<br>
> +      // For a generic lambda, each 'auto' within the parameter declaration<br>
> +      // clause creates a template type parameter, so increment the depth.<br>
> +      if (getLangOpts().CPlusPlus1y && Actions.getCurGenericLambda())<br>
> +        ++CurTemplateDepthTracker;<br>
> +    }<br>
>     T.consumeClose();<br>
>     SourceLocation RParenLoc = T.getCloseLocation();<br>
>     DeclEndLoc = RParenLoc;<br>
><br>
> Modified: cfe/trunk/lib/Parse/Parser.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Parse/Parser.cpp (original)<br>
> +++ cfe/trunk/lib/Parse/Parser.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1175,7 +1175,6 @@ void Parser::ParseKNRParamDeclarations(D<br>
>       // Ask the actions module to compute the type for this declarator.<br>
>       Decl *Param =<br>
>         Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);<br>
> -<br>
>       if (Param &&<br>
>           // A missing identifier has already been diagnosed.<br>
>           ParmDeclarator.getIdentifier()) {<br>
><br>
> Modified: cfe/trunk/lib/Sema/Sema.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/Sema.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/Sema.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1007,10 +1007,17 @@ void Sema::PushBlockScope(Scope *BlockSc<br>
>                                               BlockScope, Block));<br>
> }<br>
><br>
> -void Sema::PushLambdaScope(CXXRecordDecl *Lambda,<br>
> -                           CXXMethodDecl *CallOperator) {<br>
> -  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,<br>
> -                                               CallOperator));<br>
> +void Sema::PushLambdaScope() {<br>
> +  FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics()));<br>
> +}<br>
> +<br>
> +void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {<br>
> +  if (LambdaScopeInfo *const LSI = getCurLambda()) {<br>
> +    LSI->AutoTemplateParameterDepth = Depth;<br>
> +    return;<br>
> +  }<br>
> +  assert(false &&<br>
> +      "Remove assertion if intentionally called in a non-lambda context.");<br>
> }<br>
><br>
> void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,<br>
> @@ -1066,6 +1073,16 @@ LambdaScopeInfo *Sema::getCurLambda() {<br>
><br>
>   return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());<br>
> }<br>
> +// We have a generic lambda if we parsed auto parameters, or we have<br>
> +// an associated template parameter list.<br>
> +LambdaScopeInfo *Sema::getCurGenericLambda() {<br>
> +  if (LambdaScopeInfo *LSI =  getCurLambda()) {<br>
> +    return (LSI->AutoTemplateParams.size() ||<br>
> +                    LSI->GLTemplateParameterList) ? LSI : 0;<br>
> +  }<br>
> +  return 0;<br>
> +}<br>
> +<br>
><br>
> void Sema::ActOnComment(SourceRange Comment) {<br>
>   if (!LangOpts.RetainCommentsFromSystemHeaders &&<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -35,6 +35,7 @@<br>
> #include "clang/Sema/DeclSpec.h"<br>
> #include "clang/Sema/DelayedDiagnostic.h"<br>
> #include "clang/Sema/Initialization.h"<br>
> +#include "clang/Sema/SemaLambda.h"<br>
> #include "clang/Sema/Lookup.h"<br>
> #include "clang/Sema/ParsedTemplate.h"<br>
> #include "clang/Sema/Scope.h"<br>
> @@ -8909,6 +8910,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *<br>
>   const DeclSpec &DS = D.getDeclSpec();<br>
><br>
>   // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.<br>
> +<br>
>   // C++03 [dcl.stc]p2 also permits 'auto'.<br>
>   VarDecl::StorageClass StorageClass = SC_None;<br>
>   if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {<br>
> @@ -9015,6 +9017,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *<br>
>   if (New->hasAttr<BlocksAttr>()) {<br>
>     Diag(New->getLocation(), diag::err_block_on_nonlocal);<br>
>   }<br>
> +<br>
> +  // Handle 'auto' within a generic lambda.<br>
> +  QualType ParamType = New->getType();<br>
> +  if (getLangOpts().CPlusPlus1y && ParamType->getContainedAutoType()) {<br>
> +    assert(getCurLambda() &&<br>
> +                  "'auto' in parameter type only allowed in lambdas!");<br>
> +    New = ActOnLambdaAutoParameter(New);<br>
> +  }<br>
>   return New;<br>
> }<br>
><br>
> @@ -9268,9 +9278,38 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop<br>
>     FD = FunTmpl->getTemplatedDecl();<br>
>   else<br>
>     FD = cast<FunctionDecl>(D);<br>
> -<br>
> -  // Enter a new function scope<br>
> -  PushFunctionScope();<br>
> +  // If we are instantiating a generic lambda call operator, push<br>
> +  // a LambdaScopeInfo onto the function stack.  But use the information<br>
> +  // that's already been calculated (ActOnLambdaExpr) when analyzing the<br>
> +  // template version, to prime the current LambdaScopeInfo.<br>
> +  if (getLangOpts().CPlusPlus1y<br>
> +                        && isGenericLambdaCallOperatorSpecialization(D)) {<br>
> +    CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);<br>
> +    CXXRecordDecl *LambdaClass = CallOperator->getParent();<br>
> +    LambdaExpr    *LE = LambdaClass->getLambdaExpr();<br>
> +    assert(LE &&<br>
> +     "No LambdaExpr of closure class when instantiating a generic lambda!");<br>
> +    assert(ActiveTemplateInstantiations.size() &&<br>
> +      "There should be an active template instantiation on the stack "<br>
> +      "when instantiating a generic lambda!");<br>
> +    PushLambdaScope();<br>
> +    LambdaScopeInfo *LSI = getCurLambda();<br>
> +    LSI->CallOperator = CallOperator;<br>
> +    LSI->Lambda = LambdaClass;<br>
> +    LSI->ReturnType = CallOperator->getResultType();<br>
> +<br>
> +    if (LE->getCaptureDefault() == LCD_None)<br>
> +      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;<br>
> +    else if (LE->getCaptureDefault() == LCD_ByCopy)<br>
> +      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;<br>
> +    else if (LE->getCaptureDefault() == LCD_ByRef)<br>
> +      LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;<br>
> +<br>
> +    LSI->IntroducerRange = LE->getIntroducerRange();<br>
> +  }<br>
> +  else<br>
> +    // Enter a new function scope<br>
> +    PushFunctionScope();<br>
><br>
>   // See if this is a redefinition.<br>
>   if (!FD->isLateTemplateParsed())<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -32,6 +32,7 @@<br>
> #include "clang/Sema/CXXFieldCollector.h"<br>
> #include "clang/Sema/DeclSpec.h"<br>
> #include "clang/Sema/Initialization.h"<br>
> +#include "clang/Sema/SemaLambda.h"<br>
> #include "clang/Sema/Lookup.h"<br>
> #include "clang/Sema/ParsedTemplate.h"<br>
> #include "clang/Sema/Scope.h"<br>
> @@ -10015,29 +10016,27 @@ void Sema::DefineImplicitLambdaToFunctio<br>
>        SourceLocation CurrentLocation,<br>
>        CXXConversionDecl *Conv)<br>
> {<br>
> -  CXXRecordDecl *Lambda = Conv->getParent();<br>
> +  CXXRecordDecl *LambdaClass = Conv->getParent();<br>
><br>
>   // Make sure that the lambda call operator is marked used.<br>
> -  markLambdaCallOperatorUsed(*this, Lambda);<br>
> +  markLambdaCallOperatorUsed(*this, LambdaClass);<br>
><br>
>   Conv->setUsed();<br>
><br>
>   SynthesizedFunctionScope Scope(*this, Conv);<br>
>   DiagnosticErrorTrap Trap(Diags);<br>
><br>
> -  // Return the address of the __invoke function.<br>
> -  DeclarationName InvokeName = &Context.Idents.get("__invoke");<br>
> -  CXXMethodDecl *Invoke<br>
> -    = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());<br>
> +  CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker();<br>
> +<br>
>   Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),<br>
>                                        VK_LValue, Conv->getLocation()).take();<br>
> -  assert(FunctionRef && "Can't refer to __invoke function?");<br>
> +  assert(FunctionRef && "Can't refer to lambda static invoker function?");<br>
>   Stmt *Return = ActOnReturnStmt(Conv->getLocation(), FunctionRef).take();<br>
>   Conv->setBody(new (Context) CompoundStmt(Context, Return,<br>
>                                            Conv->getLocation(),<br>
>                                            Conv->getLocation()));<br>
><br>
> -  // Fill in the __invoke function with a dummy implementation. IR generation<br>
> +  // Fill in the invoke function with a dummy implementation. IR generation<br>
>   // will fill in the actual details.<br>
>   Invoke->setUsed();<br>
>   Invoke->setReferenced();<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaLambda.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -14,6 +14,7 @@<br>
> #include "clang/AST/ExprCXX.h"<br>
> #include "clang/Lex/Preprocessor.h"<br>
> #include "clang/Sema/Initialization.h"<br>
> +#include "clang/Sema/SemaLambda.h"<br>
> #include "clang/Sema/Lookup.h"<br>
> #include "clang/Sema/Scope.h"<br>
> #include "clang/Sema/ScopeInfo.h"<br>
> @@ -120,11 +121,69 @@ Sema::getCurrentMangleNumberContext(cons<br>
>   llvm_unreachable("unexpected context");<br>
> }<br>
><br>
> +<br>
> +ParmVarDecl *Sema::ActOnLambdaAutoParameter(ParmVarDecl *PVD) {<br>
> +  LambdaScopeInfo *LSI = getCurLambda();<br>
> +  assert(LSI && "No LambdaScopeInfo on the stack!");<br>
> +  const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;<br>
> +  const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();<br>
> +  // Invent a template type parameter corresponding to the auto<br>
> +  // containing parameter.<br>
> +  TemplateTypeParmDecl *TemplateParam =<br>
> +    TemplateTypeParmDecl::Create(Context,<br>
> +      // Temporarily add to the TranslationUnit DeclContext.  When the<br>
> +      // associated TemplateParameterList is attached to a template<br>
> +      // declaration (such as FunctionTemplateDecl), the DeclContext<br>
> +      // for each template parameter gets updated appropriately via<br>
> +      // a call to AdoptTemplateParameterList.<br>
> +      Context.getTranslationUnitDecl(),<br>
> +      SourceLocation(),<br>
> +      PVD->getLocation(),<br>
> +      TemplateParameterDepth,<br>
> +      AutoParameterPosition,  // our template param index<br>
> +      /* Identifier*/ 0, false, PVD->isParameterPack());<br>
> +  LSI->AutoTemplateParams.push_back(TemplateParam);<br>
> +  QualType AutoTy = PVD->getType();<br>
> +  // Now replace the 'auto' in the function parameter with this invented<br>
> +  // template type parameter.<br>
> +  QualType TemplParamType = QualType(TemplateParam->getTypeForDecl(), 0);<br>
> +<br>
> +  TypeSourceInfo *AutoTSI = PVD->getTypeSourceInfo();<br>
> +  TypeSourceInfo *NewTSI = SubstAutoTypeSourceInfo(AutoTSI, TemplParamType);<br>
> +  PVD->setType(NewTSI->getType());<br>
> +  PVD->setTypeSourceInfo(NewTSI);<br>
> +  return PVD;<br>
> +}<br>
> +<br>
> +<br>
> +static inline TemplateParameterList *<br>
> +              getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI,<br>
> +                            Sema &SemaRef) {<br>
> +  if (LSI->GLTemplateParameterList)<br>
> +    return LSI->GLTemplateParameterList;<br>
> +  else if (LSI->AutoTemplateParams.size()) {<br>
> +    SourceRange IntroRange = LSI->IntroducerRange;<br>
> +    SourceLocation LAngleLoc = IntroRange.getBegin();<br>
> +    SourceLocation RAngleLoc = IntroRange.getEnd();<br>
> +    LSI->GLTemplateParameterList =<br>
> +          TemplateParameterList::Create(SemaRef.Context,<br>
> +            /* Template kw loc */ SourceLocation(),<br>
> +            LAngleLoc,<br>
> +            (NamedDecl**)LSI->AutoTemplateParams.data(),<br>
> +            LSI->AutoTemplateParams.size(), RAngleLoc);<br>
> +  }<br>
> +  return LSI->GLTemplateParameterList;<br>
> +}<br>
> +<br>
> +<br>
> +<br>
> CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,<br>
>                  SourceRange IntroducerRange,<br>
>                  TypeSourceInfo *MethodType,<br>
>                  SourceLocation EndLoc,<br>
>                  ArrayRef<ParmVarDecl *> Params) {<br>
> +  TemplateParameterList *TemplateParams =<br>
> +            getGenericLambdaTemplateParameterList(getCurLambda(), *this);<br>
>   // C++11 [expr.prim.lambda]p5:<br>
>   //   The closure type for a lambda-expression has a public inline function<br>
>   //   call operator (13.5.4) whose parameters and return type are described by<br>
> @@ -152,6 +211,17 @@ CXXMethodDecl *Sema::startLambdaDefiniti<br>
>   // Temporarily set the lexical declaration context to the current<br>
>   // context, so that the Scope stack matches the lexical nesting.<br>
>   Method->setLexicalDeclContext(CurContext);<br>
> +  // Create a function template if we have a template parameter list<br>
> +  FunctionTemplateDecl *const TemplateMethod = TemplateParams ?<br>
> +            FunctionTemplateDecl::Create(Context, Class,<br>
> +                                         Method->getLocation(), MethodName,<br>
> +                                         TemplateParams,<br>
> +                                         Method) : 0;<br>
> +  if (TemplateMethod) {<br>
> +    TemplateMethod->setLexicalDeclContext(CurContext);<br>
> +    TemplateMethod->setAccess(AS_public);<br>
> +    Method->setDescribedFunctionTemplate(TemplateMethod);<br>
> +  }<br>
><br>
>   // Add parameters.<br>
>   if (!Params.empty()) {<br>
> @@ -177,15 +247,16 @@ CXXMethodDecl *Sema::startLambdaDefiniti<br>
>   return Method;<br>
> }<br>
><br>
> -LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,<br>
> +void Sema::buildLambdaScope(LambdaScopeInfo *LSI,<br>
> +                                        CXXMethodDecl *CallOperator,<br>
>                                         SourceRange IntroducerRange,<br>
>                                         LambdaCaptureDefault CaptureDefault,<br>
>                                         SourceLocation CaptureDefaultLoc,<br>
>                                         bool ExplicitParams,<br>
>                                         bool ExplicitResultType,<br>
>                                         bool Mutable) {<br>
> -  PushLambdaScope(CallOperator->getParent(), CallOperator);<br>
> -  LambdaScopeInfo *LSI = getCurLambda();<br>
> +  LSI->CallOperator = CallOperator;<br>
> +  LSI->Lambda = CallOperator->getParent();<br>
>   if (CaptureDefault == LCD_ByCopy)<br>
>     LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;<br>
>   else if (CaptureDefault == LCD_ByRef)<br>
> @@ -208,8 +279,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(<br>
>   } else {<br>
>     LSI->HasImplicitReturnType = true;<br>
>   }<br>
> -<br>
> -  return LSI;<br>
> }<br>
><br>
> void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {<br>
> @@ -358,7 +427,7 @@ static void adjustBlockReturnsToEnum(Sem<br>
> }<br>
><br>
> void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {<br>
> -  assert(CSI.HasImplicitReturnType);<br>
> +  assert(CSI.HasImplicitReturnType || CSI.ReturnType->isUndeducedType());<br>
><br>
>   // C++ Core Issue #975, proposed resolution:<br>
>   //   If a lambda-expression does not include a trailing-return-type,<br>
> @@ -392,7 +461,7 @@ void Sema::deduceClosureReturnType(Captu<br>
>   // Second case: at least one return statement has dependent type.<br>
>   // Delay type checking until instantiation.<br>
>   assert(!CSI.ReturnType.isNull() && "We should have a tentative return type.");<br>
> -  if (CSI.ReturnType->isDependentType())<br>
> +  if (CSI.ReturnType->isDependentType() || CSI.ReturnType->isUndeducedType())<br>
>     return;<br>
><br>
>   // Try to apply the enum-fuzz rule.<br>
> @@ -519,15 +588,25 @@ FieldDecl *Sema::checkInitCapture(Source<br>
> }<br>
><br>
> void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,<br>
> -                                        Declarator &ParamInfo,<br>
> -                                        Scope *CurScope) {<br>
> +                  Declarator &ParamInfo, Scope *CurScope) {<br>
>   // Determine if we're within a context where we know that the lambda will<br>
>   // be dependent, because there are template parameters in scope.<br>
>   bool KnownDependent = false;<br>
> -  if (Scope *TmplScope = CurScope->getTemplateParamParent())<br>
> -    if (!TmplScope->decl_empty())<br>
> +  LambdaScopeInfo *const LSI = getCurLambda();<br>
> +  assert(LSI && "LambdaScopeInfo should be on stack!");<br>
> +  TemplateParameterList *TemplateParams =<br>
> +            getGenericLambdaTemplateParameterList(LSI, *this);<br>
> +<br>
> +  if (Scope *TmplScope = CurScope->getTemplateParamParent()) {<br>
> +    // Since we have our own TemplateParams, so check if an outer scope<br>
> +    // has template params, only then are we in a dependent scope.<br>
> +    if (TemplateParams)  {<br>
> +      TmplScope = TmplScope->getParent();<br>
> +      TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;<br>
> +    }<br>
> +    if (TmplScope && !TmplScope->decl_empty())<br>
>       KnownDependent = true;<br>
> -<br>
> +  }<br>
>   // Determine the signature of the call operator.<br>
>   TypeSourceInfo *MethodTyInfo;<br>
>   bool ExplicitParams = true;<br>
> @@ -542,7 +621,11 @@ void Sema::ActOnStartOfLambdaDefinition(<br>
>     FunctionProtoType::ExtProtoInfo EPI;<br>
>     EPI.HasTrailingReturn = true;<br>
>     EPI.TypeQuals |= DeclSpec::TQ_const;<br>
> -    QualType MethodTy = Context.getFunctionType(Context.DependentTy, None,<br>
> +    // For C++1y, use the new return type deduction machinery, by imaginging<br>
> +    // 'auto' if no trailing return type.<br>
> +    QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus1y ?<br>
> +                    Context.getAutoDeductType() : Context.DependentTy;<br>
> +    QualType MethodTy = Context.getFunctionType(DefaultTypeForNoTrailingReturn, None,<br>
>                                                 EPI);<br>
>     MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);<br>
>     ExplicitParams = false;<br>
> @@ -560,14 +643,15 @@ void Sema::ActOnStartOfLambdaDefinition(<br>
>     if (!FTI.hasMutableQualifier())<br>
>       FTI.TypeQuals |= DeclSpec::TQ_const;<br>
><br>
> +    ExplicitResultType = FTI.hasTrailingReturnType();<br>
> +    // In C++11 if there is no explicit return type, the return type is<br>
> +    // artificially set to DependentTy, whereas in C++1y it is set to AutoTy<br>
> +    // (through ConvertDeclSpecToType) which allows us to support both<br>
> +    // C++11 and C++1y return type deduction semantics.<br>
>     MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);<br>
>     assert(MethodTyInfo && "no type from lambda-declarator");<br>
>     EndLoc = ParamInfo.getSourceRange().getEnd();<br>
><br>
> -    ExplicitResultType<br>
> -      = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()<br>
> -                                                        != Context.DependentTy;<br>
> -<br>
>     if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0 &&<br>
>         cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {<br>
>       // Empty arg list, don't push any params.<br>
> @@ -588,7 +672,6 @@ void Sema::ActOnStartOfLambdaDefinition(<br>
><br>
>   CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,<br>
>                                                 MethodTyInfo, EndLoc, Params);<br>
> -<br>
>   if (ExplicitParams)<br>
>     CheckCXXDefaultArguments(Method);<br>
><br>
> @@ -598,9 +681,8 @@ void Sema::ActOnStartOfLambdaDefinition(<br>
>   // Introduce the function call operator as the current declaration context.<br>
>   PushDeclContext(CurScope, Method);<br>
><br>
> -  // Introduce the lambda scope.<br>
> -  LambdaScopeInfo *LSI<br>
> -    = enterLambdaScope(Method,<br>
> +  // Build the lambda scope.<br>
> +  buildLambdaScope(LSI, Method,<br>
>                        Intro.Range,<br>
>                        Intro.Default, Intro.DefaultLoc,<br>
>                        ExplicitParams,<br>
> @@ -812,6 +894,8 @@ static void addFunctionPointerConversion<br>
>                                          SourceRange IntroducerRange,<br>
>                                          CXXRecordDecl *Class,<br>
>                                          CXXMethodDecl *CallOperator) {<br>
> +  // FIXME: The conversion operator needs to be fixed for generic lambdas.<br>
> +  if (Class->isGenericLambda()) return;<br>
>   // Add the conversion to function pointer.<br>
>   const FunctionProtoType *Proto<br>
>     = CallOperator->getType()->getAs<FunctionProtoType>();<br>
> @@ -849,10 +933,9 @@ static void addFunctionPointerConversion<br>
>   Conversion->setAccess(AS_public);<br>
>   Conversion->setImplicit(true);<br>
>   Class->addDecl(Conversion);<br>
> -<br>
> -  // Add a non-static member function "__invoke" that will be the result of<br>
> -  // the conversion.<br>
> -  Name = &S.Context.Idents.get("__invoke");<br>
> +  // Add a non-static member function that will be the result of<br>
> +  // the conversion with a certain unique ID.<br>
> +  Name = &S.Context.Idents.get(getLambdaStaticInvokerName());<br>
>   CXXMethodDecl *Invoke<br>
>     = CXXMethodDecl::Create(S.Context, Class, Loc,<br>
>                             DeclarationNameInfo(Name, Loc), FunctionTy,<br>
> @@ -1000,8 +1083,11 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
>     //   If a lambda-expression does not include a<br>
>     //   trailing-return-type, it is as if the trailing-return-type<br>
>     //   denotes the following type:<br>
> +    // Skip for C++1y return type deduction semantics which uses<br>
> +    // different machinery currently.<br>
> +    // FIXME: Refactor and Merge the return type deduction machinery.<br>
>     // FIXME: Assumes current resolution to core issue 975.<br>
> -    if (LSI->HasImplicitReturnType) {<br>
> +    if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {<br>
>       deduceClosureReturnType(*LSI);<br>
><br>
>       //   - if there are no return statements in the<br>
> @@ -1019,13 +1105,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
>           LSI->ReturnType, Proto->getArgTypes(), Proto->getExtProtoInfo());<br>
>       CallOperator->setType(FunctionTy);<br>
>     }<br>
> -<br>
>     // C++ [expr.prim.lambda]p7:<br>
>     //   The lambda-expression's compound-statement yields the<br>
>     //   function-body (8.4) of the function call operator [...].<br>
>     ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);<br>
>     CallOperator->setLexicalDeclContext(Class);<br>
> -    Class->addDecl(CallOperator);<br>
> +    Decl *TemplateOrNonTemplateCallOperatorDecl =<br>
> +      !CallOperator->getDescribedFunctionTemplate() ? cast<Decl>(CallOperator)<br>
> +        : CallOperator->getDescribedFunctionTemplate();<br>
> +<br>
> +    TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);<br>
> +    Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);<br>
> +<br>
>     PopExpressionEvaluationContext();<br>
><br>
>     // C++11 [expr.prim.lambda]p6:<br>
> @@ -1065,7 +1156,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
>                                           CaptureInits, ArrayIndexVars,<br>
>                                           ArrayIndexStarts, Body->getLocEnd(),<br>
>                                           ContainsUnexpandedParameterPack);<br>
> -<br>
> +  Class->setLambdaExpr(Lambda);<br>
>   // C++11 [expr.prim.lambda]p2:<br>
>   //   A lambda-expression shall not appear in an unevaluated operand<br>
>   //   (Clause 5).<br>
> @@ -1085,7 +1176,15 @@ ExprResult Sema::ActOnLambdaExpr(SourceL<br>
>       break;<br>
>     }<br>
>   }<br>
> -<br>
> +  // TODO: Implement capturing.<br>
> +  if (Lambda->isGenericLambda()) {<br>
> +    if (Lambda->getCaptureDefault() != LCD_None) {<br>
> +      Diag(Lambda->getIntroducerRange().getBegin(),<br>
> +        diag::err_glambda_not_fully_implemented)<br>
> +        << " capturing not implemented yet";<br>
> +      return ExprError();<br>
> +    }<br>
> +  }<br>
>   return MaybeBindToTemporary(Lambda);<br>
> }<br>
><br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaOverload.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -8670,6 +8670,10 @@ void DiagnoseBadDeduction(Sema &S, Decl<br>
>         }<br>
>       }<br>
>     }<br>
> +    // FIXME: For generic lambda parameters, check if the function is a lambda<br>
> +    // call operator, and if so, emit a prettier and more informative<br>
> +    // diagnostic that mentions 'auto' and lambda in addition to<br>
> +    // (or instead of?) the canonical template type parameters.<br>
>     S.Diag(Templated->getLocation(),<br>
>            diag::note_ovl_candidate_non_deduced_mismatch)<br>
>         << FirstTA << SecondTA;<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -2487,12 +2487,31 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>   // [expr.prim.lambda]p4 in C++11; block literals follow the same rules.<br>
>   CapturingScopeInfo *CurCap = cast<CapturingScopeInfo>(getCurFunction());<br>
>   QualType FnRetType = CurCap->ReturnType;<br>
> -<br>
> -  // For blocks/lambdas with implicit return types, we check each return<br>
> -  // statement individually, and deduce the common return type when the block<br>
> -  // or lambda is completed.<br>
> -  if (CurCap->HasImplicitReturnType) {<br>
> -    // FIXME: Fold this into the 'auto' codepath below.<br>
> +  LambdaScopeInfo *const LambdaSI = getCurLambda();<br>
> +  // In C++1y, an implicit return type behaves as if 'auto' was<br>
> +  // the return type.<br>
> +  if (FnRetType.isNull() && getLangOpts().CPlusPlus1y) {<br>
> +    if (LambdaSI) {<br>
> +      FunctionDecl *CallOp = LambdaSI->CallOperator;<br>
> +      FnRetType = CallOp->getResultType();<br>
> +      assert(FnRetType->getContainedAutoType());<br>
> +    }<br>
> +  }<br>
> +<br>
> +  // For blocks/lambdas with implicit return types in C++11, we check each<br>
> +  // return statement individually, and deduce the common return type when<br>
> +  // the block or lambda is completed.  In C++1y, the return type deduction<br>
> +  // of a lambda is specified in terms of auto.<br>
> +  // Notably, in C++11, we take the type of the expression after decay and<br>
> +  // lvalue-to-rvalue conversion, so a class type can be cv-qualified.<br>
> +  // In C++1y, we perform template argument deduction as if the return<br>
> +  // type were 'auto', so an implicit return type is never cv-qualified.<br>
> +  // i.e if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())<br>
> +  //   FnRetType = FnRetType.getUnqualifiedType();<br>
> +  // Return type deduction is unchanged for blocks in C++1y.<br>
> +  // FIXME: Fold this into the 'auto' codepath below.<br>
> +  if (CurCap->HasImplicitReturnType &&<br>
> +                            (!LambdaSI || !getLangOpts().CPlusPlus1y)) {<br>
>     if (RetValExp && !isa<InitListExpr>(RetValExp)) {<br>
>       ExprResult Result = DefaultFunctionArrayLvalueConversion(RetValExp);<br>
>       if (Result.isInvalid())<br>
> @@ -2500,13 +2519,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>       RetValExp = Result.take();<br>
><br>
>       if (!CurContext->isDependentContext()) {<br>
> -        FnRetType = RetValExp->getType();<br>
> -        // In C++11, we take the type of the expression after decay and<br>
> -        // lvalue-to-rvalue conversion, so a class type can be cv-qualified.<br>
> -        // In C++1y, we perform template argument deduction as if the return<br>
> -        // type were 'auto', so an implicit return type is never cv-qualified.<br>
> -        if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())<br>
> -          FnRetType = FnRetType.getUnqualifiedType();<br>
> +        FnRetType = RetValExp->getType();<br>
>       } else<br>
>         FnRetType = CurCap->ReturnType = Context.DependentTy;<br>
>     } else {<br>
> @@ -2517,7 +2530,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>         Diag(ReturnLoc, diag::err_lambda_return_init_list)<br>
>           << RetValExp->getSourceRange();<br>
>       }<br>
> -<br>
>       FnRetType = Context.VoidTy;<br>
>     }<br>
><br>
> @@ -2526,7 +2538,8 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>     if (CurCap->ReturnType.isNull())<br>
>       CurCap->ReturnType = FnRetType;<br>
>   } else if (AutoType *AT =<br>
> -                 FnRetType.isNull() ? 0 : FnRetType->getContainedAutoType()) {<br>
> +                 (FnRetType.isNull() || !LambdaSI) ? 0<br>
> +                      : FnRetType->getContainedAutoType()) {<br>
>     // In C++1y, the return type may involve 'auto'.<br>
>     FunctionDecl *FD = cast<LambdaScopeInfo>(CurCap)->CallOperator;<br>
>     if (CurContext->isDependentContext()) {<br>
> @@ -2534,7 +2547,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>       //   Return type deduction [...] occurs when the definition is<br>
>       //   instantiated even if the function body contains a return<br>
>       //   statement with a non-type-dependent operand.<br>
> -      CurCap->ReturnType = FnRetType = Context.DependentTy;<br>
> +      CurCap->ReturnType = FnRetType;<br>
>     } else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {<br>
>       FD->setInvalidDecl();<br>
>       return StmtError();<br>
> @@ -2564,7 +2577,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
>   // pickier with blocks than for normal functions because we don't have GCC<br>
>   // compatibility to worry about here.<br>
>   const VarDecl *NRVOCandidate = 0;<br>
> -  if (FnRetType->isDependentType()) {<br>
> +  if (FnRetType->isDependentType() || FnRetType->isUndeducedType()) {<br>
>     // Delay processing for now.  TODO: there are lots of dependent<br>
>     // types we can conclusively prove aren't void.<br>
>   } else if (FnRetType->isVoidType()) {<br>
> @@ -2624,7 +2637,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca<br>
><br>
>   return Owned(Result);<br>
> }<br>
> -<br>
> /// Deduce the return type for a function from a returned expression, per<br>
> /// C++1y [dcl.spec.auto]p6.<br>
> bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,<br>
> @@ -2634,7 +2646,6 @@ bool Sema::DeduceFunctionTypeFromReturnE<br>
>   TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().<br>
>     IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();<br>
>   QualType Deduced;<br>
> -<br>
>   if (RetExpr && isa<InitListExpr>(RetExpr)) {<br>
>     //  If the deduction is for a return statement and the initializer is<br>
>     //  a braced-init-list, the program is ill-formed.<br>
> @@ -2692,9 +2703,18 @@ bool Sema::DeduceFunctionTypeFromReturnE<br>
>     AutoType *NewAT = Deduced->getContainedAutoType();<br>
>     if (!FD->isDependentContext() &&<br>
>         !Context.hasSameType(AT->getDeducedType(), NewAT->getDeducedType())) {<br>
> -      Diag(ReturnLoc, diag::err_auto_fn_different_deductions)<br>
> -        << (AT->isDecltypeAuto() ? 1 : 0)<br>
> -        << NewAT->getDeducedType() << AT->getDeducedType();<br>
> +      LambdaScopeInfo *const LambdaSI = getCurLambda();<br>
> +      if (LambdaSI && LambdaSI->HasImplicitReturnType) {<br>
> +        Diag(ReturnLoc,<br>
> +          diag::err_typecheck_missing_return_type_incompatible)<br>
> +          << NewAT->getDeducedType() << AT->getDeducedType()<br>
> +          << true /*IsLambda*/;<br>
> +      }<br>
> +      else {<br>
> +        Diag(ReturnLoc, diag::err_auto_fn_different_deductions)<br>
> +          << (AT->isDecltypeAuto() ? 1 : 0)<br>
> +          << NewAT->getDeducedType() << AT->getDeducedType();<br>
> +      }<br>
>       return true;<br>
>     }<br>
>   } else if (!FD->isInvalidDecl()) {<br>
> @@ -2710,10 +2730,8 @@ Sema::ActOnReturnStmt(SourceLocation Ret<br>
>   // Check for unexpanded parameter packs.<br>
>   if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))<br>
>     return StmtError();<br>
> -<br>
>   if (isa<CapturingScopeInfo>(getCurFunction()))<br>
>     return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);<br>
> -<br>
>   QualType FnRetType;<br>
>   QualType RelatedRetType;<br>
>   if (const FunctionDecl *FD = getCurFunctionDecl()) {<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -3766,7 +3766,8 @@ namespace {<br>
>         QualType Result =<br>
>           SemaRef.Context.getAutoType(Dependent ? QualType() : Replacement,<br>
>                                       TL.getTypePtr()->isDecltypeAuto(),<br>
> -                                      Dependent);<br>
> +                                      Dependent, TL.getTypePtr()-><br>
> +                                        containsUnexpandedParameterPack());<br>
>         AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);<br>
>         NewTL.setNameLoc(TL.getNameLoc());<br>
>         return Result;<br>
> @@ -3907,8 +3908,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr<br>
>   return DAR_Succeeded;<br>
> }<br>
><br>
> -QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {<br>
> -  return SubstituteAutoTransform(*this, Deduced).TransformType(Type);<br>
> +QualType Sema::SubstAutoType(QualType TypeWithAuto,<br>
> +                             QualType TypeToReplaceAuto) {<br>
> +  return SubstituteAutoTransform(*this, TypeToReplaceAuto).<br>
> +               TransformType(TypeWithAuto);<br>
> +}<br>
> +<br>
> +TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,<br>
> +                             QualType TypeToReplaceAuto) {<br>
> +    return SubstituteAutoTransform(*this, TypeToReplaceAuto).<br>
> +               TransformType(TypeWithAuto);<br>
> }<br>
><br>
> void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {<br>
><br>
> Modified: cfe/trunk/lib/Sema/SemaType.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/SemaType.cpp (original)<br>
> +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -781,7 +781,13 @@ static QualType ConvertDeclSpecToType(Ty<br>
>     // specified with a trailing return type or inferred.<br>
>     if (declarator.getContext() == Declarator::LambdaExprContext ||<br>
>         isOmittedBlockReturnType(declarator)) {<br>
> -      Result = Context.DependentTy;<br>
> +      // In C++1y (n3690 CD), 5.1.2 [expr.prim.lambda]/4 : The lambda return<br>
> +      // type is auto, which is replaced by the trailing-return-type if<br>
> +      // provided and/or deduced from return statements as described<br>
> +      // in 7.1.6.4.<br>
> +      Result = S.getLangOpts().CPlusPlus1y &&<br>
> +               declarator.getContext() == Declarator::LambdaExprContext<br>
> +                  ? Context.getAutoDeductType() : Context.DependentTy;<br>
>       break;<br>
>     }<br>
><br>
> @@ -1006,11 +1012,17 @@ static QualType ConvertDeclSpecToType(Ty<br>
><br>
>   case DeclSpec::TST_auto:<br>
>     // TypeQuals handled by caller.<br>
> -    Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);<br>
> +    Result = Context.getAutoType(QualType(),<br>
> +                                /*decltype(auto)*/false,<br>
> +                                /*IsDependent*/   false,<br>
> +                                /*IsParameterPack*/ declarator.hasEllipsis());<br>
>     break;<br>
><br>
>   case DeclSpec::TST_decltype_auto:<br>
> -    Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);<br>
> +    Result = Context.getAutoType(QualType(),<br>
> +                                 /*decltype(auto)*/true,<br>
> +                                 /*IsDependent*/   false,<br>
> +                                 /*IsParameterPack*/ false);<br>
>     break;<br>
><br>
>   case DeclSpec::TST_unknown_anytype:<br>
> @@ -1557,7 +1569,7 @@ QualType Sema::BuildArrayType(QualType T<br>
>         ASM = ArrayType::Normal;<br>
>       }<br>
>     } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&<br>
> -               !T->isIncompleteType()) {<br>
> +               !T->isIncompleteType() && !T->isUndeducedType()) {<br>
>       // Is the array too large?<br>
>       unsigned ActiveSizeBits<br>
>         = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);<br>
> @@ -2097,6 +2109,7 @@ static QualType GetDeclSpecTypeForDeclar<br>
>   // In C++11, a function declarator using 'auto' must have a trailing return<br>
>   // type (this is checked later) and we can skip this. In other languages<br>
>   // using auto, we need to check regardless.<br>
> +  // Generic Lambdas (C++14) allow 'auto' in their parameters.<br>
>   if (ContainsPlaceholderType &&<br>
>       (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator())) {<br>
>     int Error = -1;<br>
> @@ -2109,7 +2122,12 @@ static QualType GetDeclSpecTypeForDeclar<br>
>     case Declarator::ObjCParameterContext:<br>
>     case Declarator::ObjCResultContext:<br>
>     case Declarator::PrototypeContext:<br>
> -      Error = 0; // Function prototype<br>
> +      Error = 0;<br>
> +      break;<br>
> +    case Declarator::LambdaExprParameterContext:<br>
> +      if (!(SemaRef.getLangOpts().CPlusPlus1y<br>
> +              && D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_auto))<br>
> +        Error = 0;<br>
>       break;<br>
>     case Declarator::MemberContext:<br>
>       if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)<br>
> @@ -2189,8 +2207,13 @@ static QualType GetDeclSpecTypeForDeclar<br>
>       AutoRange = D.getName().getSourceRange();<br>
><br>
>     if (Error != -1) {<br>
> +      if (D.getDeclSpec().getTypeSpecType() == DeclSpec::TST_decltype_auto) {<br>
> +        SemaRef.Diag(AutoRange.getBegin(),<br>
> +            diag::err_decltype_auto_function_declarator_not_declaration);<br>
> +      } else {<br>
>       SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)<br>
>         << Error << AutoRange;<br>
> +      }<br>
>       T = SemaRef.Context.IntTy;<br>
>       D.setInvalidType(true);<br>
>     } else<br>
> @@ -2240,6 +2263,7 @@ static QualType GetDeclSpecTypeForDeclar<br>
>       D.setInvalidType(true);<br>
>       break;<br>
>     case Declarator::PrototypeContext:<br>
> +    case Declarator::LambdaExprParameterContext:<br>
>     case Declarator::ObjCParameterContext:<br>
>     case Declarator::ObjCResultContext:<br>
>     case Declarator::KNRTypeListContext:<br>
> @@ -2613,8 +2637,11 @@ static TypeSourceInfo *GetFullTypeForDec<br>
>           }<br>
>         }<br>
>       }<br>
> -<br>
> -      if (const AutoType *AT = T->getContainedAutoType()) {<br>
> +      const AutoType *AT = T->getContainedAutoType();<br>
> +      // Allow arrays of auto if we are a generic lambda parameter.<br>
> +      // i.e. [](auto (&array)[5]) { return array[0]; }; OK<br>
> +      if (AT && !(S.getLangOpts().CPlusPlus1y &&<br>
> +                  D.getContext() == Declarator::LambdaExprParameterContext)) {<br>
>         // We've already diagnosed this for decltype(auto).<br>
>         if (!AT->isDecltypeAuto())<br>
>           S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)<br>
> @@ -3110,6 +3137,7 @@ static TypeSourceInfo *GetFullTypeForDec<br>
>     //   is a parameter pack (14.5.3). [...]<br>
>     switch (D.getContext()) {<br>
>     case Declarator::PrototypeContext:<br>
> +    case Declarator::LambdaExprParameterContext:<br>
>       // C++0x [dcl.fct]p13:<br>
>       //   [...] When it is part of a parameter-declaration-clause, the<br>
>       //   parameter pack is a function parameter pack (14.5.3). The type T<br>
> @@ -3128,7 +3156,6 @@ static TypeSourceInfo *GetFullTypeForDec<br>
>         T = Context.getPackExpansionType(T, None);<br>
>       }<br>
>       break;<br>
> -<br>
>     case Declarator::TemplateParamContext:<br>
>       // C++0x [temp.param]p15:<br>
>       //   If a template-parameter is a [...] is a parameter-declaration that<br>
><br>
> Modified: cfe/trunk/lib/Sema/TreeTransform.h<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Sema/TreeTransform.h (original)<br>
> +++ cfe/trunk/lib/Sema/TreeTransform.h Wed Aug 21 20:49:11 2013<br>
> @@ -782,7 +782,10 @@ public:<br>
>     // Note, IsDependent is always false here: we implicitly convert an 'auto'<br>
>     // which has been deduced to a dependent type into an undeduced 'auto', so<br>
>     // that we'll retry deduction after the transformation.<br>
> -    return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);<br>
> +    // FIXME: Can we assume the same about IsParameterPack?<br>
> +    return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,<br>
> +                                       /*IsDependent*/ false,<br>
> +                                       /*IsParameterPack*/ false);<br>
>   }<br>
><br>
>   /// \brief Build a new template specialization type.<br>
> @@ -3494,7 +3497,9 @@ TreeTransform<Derived>::TransformQualifi<br>
>         Qs.removeObjCLifetime();<br>
>         Deduced = SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),<br>
>                                                    Qs);<br>
> -        Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto());<br>
> +        Result = SemaRef.Context.getAutoType(Deduced, AutoTy->isDecltypeAuto(),<br>
> +                                AutoTy->isDependentType(),<br>
> +                                AutoTy->containsUnexpandedParameterPack());<br>
>         TLB.TypeWasModifiedSafely(Result);<br>
>       } else {<br>
>         // Otherwise, complain about the addition of a qualifier to an<br>
> @@ -8193,6 +8198,14 @@ TreeTransform<Derived>::TransformCXXTemp<br>
> template<typename Derived><br>
> ExprResult<br>
> TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {<br>
> +<br>
> +  // FIXME: Implement nested generic lambda transformations.<br>
> +  if (E->isGenericLambda()) {<br>
> +    getSema().Diag(E->getIntroducerRange().getBegin(),<br>
> +      diag::err_glambda_not_fully_implemented)<br>
> +      << " nested lambdas not implemented yet";<br>
> +    return ExprError();<br>
> +  }<br>
>   // Transform the type of the lambda parameters and start the definition of<br>
>   // the lambda itself.<br>
>   TypeSourceInfo *MethodTy<br>
> @@ -8215,7 +8228,10 @@ TreeTransform<Derived>::TransformLambdaE<br>
>         E->getCallOperator()->param_size(),<br>
>         0, ParamTypes, &Params))<br>
>     return ExprError();<br>
> -<br>
> +  getSema().PushLambdaScope();<br>
> +  LambdaScopeInfo *LSI = getSema().getCurLambda();<br>
> +  // TODO: Fix for nested lambdas<br>
> +  LSI->GLTemplateParameterList = 0;<br>
>   // Build the call operator.<br>
>   CXXMethodDecl *CallOperator<br>
>     = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),<br>
> @@ -8250,9 +8266,9 @@ TreeTransform<Derived>::TransformLambdaS<br>
>   // Introduce the context of the call operator.<br>
>   Sema::ContextRAII SavedContext(getSema(), CallOperator);<br>
><br>
> +  LambdaScopeInfo *const LSI = getSema().getCurLambda();<br>
>   // Enter the scope of the lambda.<br>
> -  sema::LambdaScopeInfo *LSI<br>
> -    = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),<br>
> +  getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),<br>
>                                  E->getCaptureDefault(),<br>
>                                  E->getCaptureDefaultLoc(),<br>
>                                  E->hasExplicitParameters(),<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -4740,7 +4740,9 @@ QualType ASTReader::readTypeRecord(unsig<br>
>     QualType Deduced = readType(*Loc.F, Record, Idx);<br>
>     bool IsDecltypeAuto = Record[Idx++];<br>
>     bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;<br>
> -    return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);<br>
> +    bool IsParameterPack = Record[Idx++];<br>
> +    return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent,<br>
> +                                                      IsParameterPack);<br>
>   }<br>
><br>
>   case TYPE_RECORD: {<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1201,6 +1201,7 @@ void ASTDeclReader::ReadCXXDefinitionDat<br>
>       = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);<br>
>     Capture *ToCapture = Lambda.Captures;<br>
>     Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);<br>
> +    Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));<br>
>     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {<br>
>       SourceLocation Loc = ReadSourceLocation(Record, Idx);<br>
>       bool IsImplicit = Record[Idx++];<br>
><br>
> Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

> ==============================================================================<br>
> --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>
> +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -253,6 +253,7 @@ void ASTTypeWriter::VisitAutoType(const<br>
>   Record.push_back(T->isDecltypeAuto());<br>
>   if (T->getDeducedType().isNull())<br>
>     Record.push_back(T->isDependentType());<br>
> +  Record.push_back(T->containsUnexpandedParameterPack());<br>
>   Code = TYPE_AUTO;<br>
> }<br>
><br>
> @@ -5136,6 +5137,7 @@ void ASTWriter::AddCXXDefinitionData(con<br>
>     Record.push_back(Lambda.ManglingNumber);<br>
>     AddDeclRef(Lambda.ContextDecl, Record);<br>
>     AddTypeSourceInfo(Lambda.MethodTyInfo, Record);<br>
> +    AddStmt(Lambda.TheLambdaExpr);<br>
>     for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {<br>
>       LambdaExpr::Capture &Capture = Lambda.Captures[I];<br>
>       AddSourceLocation(Capture.getLocation(), Record);<br>
><br>
> Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp<br>
> URL: <a href="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=188977&view=auto" target="_blank">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=188977&view=auto</a><br>

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

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp (added)<br>
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -0,0 +1,50 @@<br>
> +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -emit-llvm<br>
> +namespace return_type_deduction_ok {<br>
> +// FIXME: Once return type deduction is implemented for generic lambdas<br>
> +// this will need to be updated.<br>
> + auto l = [](auto a) ->auto { return a; }(2);<br>
> + auto l2 = [](auto a) ->decltype(auto) { return a; }(2);<br>
> + auto l3 = [](auto a) { return a; }(2);<br>
> +<br>
> +<br>
> +}<br>
> +<br>
> +namespace lambda_capturing {<br>
> +// FIXME: Once return type deduction is implemented for generic lambdas<br>
> +// this will need to be updated.<br>
> +void test() {<br>
> +  int i = 10;<br>
> +  auto L = [=](auto a) -> int { //expected-error{{unimplemented}}<br>
> +    return i + a;<br>
> +  };<br>
> +  L(3);<br>
> +}<br>
> +<br>
> +}<br>
> +<br>
> +namespace nested_generic_lambdas {<br>
> +void test() {<br>
> +  auto L = [](auto a) -> int {<br>
> +    auto M = [](auto b, decltype(a) b2) -> int { //expected-error{{unimplemented}}<br>
> +      return 1;<br>
> +    };<br>
> +    M(a, a);<br>
> +  };<br>
> +  L(3); //expected-note{{in instantiation of}}<br>
> +}<br>
> +}<br>
> +<br>
> +namespace conversion_operator {<br>
> +void test() {<br>
> +    auto L = [](auto a) -> int { return a; };<br>
> +    int (*fp)(int) = L;  //expected-error{{no viable conversion}}<br>
> +  }<br>
> +}<br>
> +<br>
> +namespace generic_lambda_as_default_argument_ok {<br>
> +  void test(int i = [](auto a)->int { return a; }(3)) {<br>
> +<br>
> +  }<br>
> +<br>
> +}<br>
> +<br>
><br>
> Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=188977&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=188977&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp (added)<br>
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -0,0 +1,23 @@<br>
> +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y<br>
> +<br>
> +// prvalue<br>
> +void prvalue() {<br>
> +  auto&& x = [](auto a)->void { };<br>
> +  auto& y = [](auto *a)->void { }; // expected-error{{cannot bind to a temporary of type}}<br>
> +}<br>
> +<br>
> +namespace std {<br>
> +  class type_info;<br>
> +}<br>
> +<br>
> +struct P {<br>
> +  virtual ~P();<br>
> +};<br>
> +<br>
> +void unevaluated_operand(P &p, int i) {<br>
> +  // FIXME: this should only emit one error.<br>
> +  int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); // expected-error{{lambda expression in an unevaluated operand}} \<br>
> +                                                       // expected-error{{invalid application of 'sizeof'}}<br>
> +  const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p; return p; }(i));<br>
> +  const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i));  // expected-error{{lambda expression in an unevaluated operand}}<br>
> +}<br>
><br>
> Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp?rev=188977&r1=188976&r2=188977&view=diff" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp?rev=188977&r1=188976&r2=188977&view=diff</a><br>

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

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp (original)<br>
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -1,5 +1,5 @@<br>
> // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify<br>
> -// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify<br>
> +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -DCPP1Y<br>
><br>
> void missing_lambda_declarator() {<br>
>   [](){}();<br>
> @@ -18,7 +18,7 @@ void infer_void_return_type(int i) {<br>
>     switch (x) {<br>
>     case 0: return get<void>();<br>
>     case 1: return;<br>
> -    case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda return type from initializer list}}<br>
> +    case 2: return { 1, 2.0 }; //expected-error{{cannot deduce}}<br>
>     }<br>
>   }(7);<br>
> }<br>
><br>
> Added: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp<br>
> URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=188977&view=auto" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=188977&view=auto</a><br>

> ==============================================================================<br>
> --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp (added)<br>
> +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp Wed Aug 21 20:49:11 2013<br>
> @@ -0,0 +1,135 @@<br>
> +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y -emit-llvm<br>
> +<br>
> +namespace test_factorial {<br>
> +<br>
> +auto Fact = [](auto Self, unsigned n) -> unsigned {<br>
> +    return !n ? 1 : Self(Self, n - 1) * n;<br>
> +};<br>
> +<br>
> +auto six = Fact(Fact, 3);<br>
> +<br>
> +}<br>
> +<br>
> +namespace overload_generic_lambda {<br>
> +  template <class F1, class F2> struct overload : F1, F2 {<br>
> +    using F1::operator();<br>
> +    using F2::operator();<br>
> +    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }<br>
> +  };<br>
> +<br>
> +  auto NumParams = [](auto Self, auto h, auto ... rest) -> unsigned {<br>
> +    return 1 + Self(Self, rest...);<br>
> +  };<br>
> +  auto Base = [](auto Self, auto h) -> unsigned {<br>
> +      return 1;<br>
> +  };<br>
> +  overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);<br>
> +  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');<br>
> +}<br>
> +<br>
> +<br>
> +namespace overload_generic_lambda_return_type_deduction {<br>
> +  template <class F1, class F2> struct overload : F1, F2 {<br>
> +    using F1::operator();<br>
> +    using F2::operator();<br>
> +    overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }<br>
> +  };<br>
> +<br>
> +  auto NumParams = [](auto Self, auto h, auto ... rest) {<br>
> +    return 1 + Self(Self, rest...);<br>
> +  };<br>
> +  auto Base = [](auto Self, auto h) {<br>
> +      return 1;<br>
> +  };<br>
> +  overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);<br>
> +  int num_params =  O(O, 5, 3, "abc", 3.14, 'a');<br>
> +}<br>
> +<br>
> +namespace test_standard_p5 {<br>
> +// FIXME: This test should eventually compile without an explicit trailing return type<br>
> +auto glambda = [](auto a, auto&& b) ->bool { return a < b; };<br>
> +bool b = glambda(3, 3.14); // OK<br>
> +<br>
> +}<br>
> +namespace test_deduction_failure {<br>
> + int test() {<br>
> +   auto g = [](auto *a) { //expected-note{{candidate template ignored}}<br>
> +    return a;<br>
> +   };<br>
> +   struct X { };<br>
> +   X *x;<br>
> +   g(x);<br>
> +   g(3); //expected-error{{no matching function}}<br>
> +   return 0;<br>
> + }<br>
> +<br>
> +}<br>
> +<br>
> +namespace test_instantiation_or_sfinae_failure {<br>
> +int test2() {<br>
> +  {<br>
> +    auto L = [](auto *a) {<br>
> +                return (*a)(a); }; //expected-error{{called object type 'double' is not a function}}<br>
> +    //l(&l);<br>
> +    double d;<br>
> +    L(&d); //expected-note{{in instantiation of}}<br>
> +    auto M = [](auto b) { return b; };<br>
> +    L(&M); // ok<br>
> +  }<br>
> +  {<br>
> +    auto L = [](auto *a) ->decltype (a->foo()) { //expected-note2{{candidate template ignored:}}<br>
> +                return (*a)(a); };<br>
> +    //l(&l);<br>
> +    double d;<br>
> +    L(&d); //expected-error{{no matching function for call}}<br>
> +    auto M = [](auto b) { return b; };<br>
> +    L(&M); //expected-error{{no matching function for call}}<br>
> +<br>
> +  }<br>
> +  return 0;<br>
> +}<br>
> +<br>
> +<br>
> +}<br>
> +<br>
> +namespace test_misc {<br>
> +auto GL = [](auto a, decltype(a) b) //expected-note{{candidate function}}<br>
> +                -> int { return a + b; };<br>
> +<br>
> +void test() {<br>
> +   struct X { };<br>
> +   GL(3, X{}); //expected-error{{no matching function}}<br>
> +}<br>
> +<br>
> +void test2() {<br>
> +  auto l = [](auto *a) -> int {<br>
> +              (*a)(a); return 0; }; //expected-error{{called object type 'double' is not a function}}<br>
> +  l(&l);<br>
> +  double d;<br>
> +  l(&d); //expected-note{{in instantiation of}}<br>
> +}<br>
> +<br>
> +}<br>
> +<br>
> +namespace nested_lambdas {<br>
> +  int test() {<br>
> +    auto L = [](auto a) {<br>
> +                 return [=](auto b) {  //expected-error{{unimplemented}}<br>
> +                           return a + b;<br>
> +                        };<br>
> +              };<br>
> +   // auto M = L(3.14);<br>
> +   // return M('4');<br>
> +  }<br>
> +  auto get_lambda() {<br>
> +    return [](auto a) {<br>
> +      return a;<br>
> +    };<br>
> +  };<br>
> +<br>
> +  int test2() {<br>
> +    auto L = get_lambda();<br>
> +    L(3);<br>
> +  }<br>
> +}<br>
> +<br>
><br>
><br>
> _______________________________________________<br>
> cfe-commits mailing list<br>
> <a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
> <a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>
<a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits" target="_blank">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>