r188977 - Implement a rudimentary form of generic lambdas.
Manuel Klimek
klimek at google.com
Thu Aug 22 05:25:01 PDT 2013
Rolled back in r189004 as it appears to not have been fully reviewed /
lgtm'ed (see the review thread) and violates a layering restriction.
On Thu, Aug 22, 2013 at 4:02 AM, Juergen Ributzka <juergen at apple.com> wrote:
> I got two warning messages about unused variables ;-)
>
> llvm/tools/clang/lib/Sema/SemaLambda.cpp:146:12: warning: unused variable
> 'AutoTy' [-Wunused-variable]
> QualType AutoTy = PVD->getType();
> ^
> 1 warning generated.
> llvm/tools/clang/lib/Parse/ParseExprCXX.cpp:941:30: warning: unused
> variable 'LSI' [-Wunused-variable]
> sema::LambdaScopeInfo *LSI = Actions.getCurLambda();
>
> On Aug 21, 2013, at 6:49 PM, Faisal Vali <faisalv at yahoo.com> wrote:
>
> > Author: faisalv
> > Date: Wed Aug 21 20:49:11 2013
> > New Revision: 188977
> >
> > URL: http://llvm.org/viewvc/llvm-project?rev=188977&view=rev
> > Log:
> > Implement a rudimentary form of generic lambdas.
> >
> > Specifically, the following features are not included in this commit:
> > - any sort of capturing within generic lambdas
> > - nested lambdas
> > - conversion operator for captureless lambdas
> > - ensuring all visitors are generic lambda aware
> >
> >
> > As an example of what compiles:
> >
> > template <class F1, class F2>
> > struct overload : F1, F2 {
> > using F1::operator();
> > using F2::operator();
> > overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
> > };
> >
> > auto Recursive = [](auto Self, auto h, auto ... rest) {
> > return 1 + Self(Self, rest...);
> > };
> > auto Base = [](auto Self, auto h) {
> > return 1;
> > };
> > overload<decltype(Base), decltype(Recursive)> O(Base, Recursive);
> > int num_params = O(O, 5, 3, "abc", 3.14, 'a');
> >
> > Please see attached tests for more examples.
> >
> > Some implementation notes:
> >
> > - Add a new Declarator context => LambdaExprParameterContext to
> > clang::Declarator to allow the use of 'auto' in declaring generic
> > lambda parameters
> >
> > - Augment AutoType's constructor (similar to how variadic
> > template-type-parameters ala TemplateTypeParmDecl are implemented) to
> > accept an IsParameterPack to encode a generic lambda parameter pack.
> >
> > - Add various helpers to CXXRecordDecl to facilitate identifying
> > and querying a closure class
> >
> > - LambdaScopeInfo (which maintains the current lambda's Sema state)
> > was augmented to house the current depth of the template being
> > parsed (id est the Parser calls
> Sema::RecordParsingTemplateParameterDepth)
> > so that Sema::ActOnLambdaAutoParameter may use it to create the
> > appropriate list of corresponding TemplateTypeParmDecl for each
> > auto parameter identified within the generic lambda (also stored
> > within the current LambdaScopeInfo). Additionally,
> > a TemplateParameterList data-member was added to hold the invented
> > TemplateParameterList AST node which will be much more useful
> > once we teach TreeTransform how to transform generic lambdas.
> >
> > - SemaLambda.h was added to hold some common lambda utility
> > functions (this file is likely to grow ...)
> >
> > - Teach Sema::ActOnStartOfFunctionDef to check whether it
> > is being called to instantiate a generic lambda's call
> > operator, and if so, push an appropriately prepared
> > LambdaScopeInfo object on the stack.
> >
> > - Teach Sema::ActOnStartOfLambdaDefinition to set the
> > return type of a lambda without a trailing return type
> > to 'auto' in C++1y mode, and teach the return type
> > deduction machinery in SemaStmt.cpp to process either
> > C++11 and C++14 lambda's correctly depending on the flag.
> >
> > - various tests were added - but much more will be needed.
> >
> > A greatful thanks to all reviewers including Eli Friedman,
> > James Dennett and the ever illuminating Richard Smith. And
> > yet I am certain that I have allowed unidentified bugs to creep in;
> > bugs, that I will do my best to slay, once identified!
> >
> > Thanks!
> >
> >
> >
> > Added:
> > cfe/trunk/include/clang/Sema/SemaLambda.h
> >
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
> >
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
> >
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
> >
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
> > Modified:
> > cfe/trunk/include/clang/AST/ASTContext.h
> > cfe/trunk/include/clang/AST/DeclCXX.h
> > cfe/trunk/include/clang/AST/ExprCXX.h
> > cfe/trunk/include/clang/AST/Type.h
> > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > cfe/trunk/include/clang/Sema/DeclSpec.h
> > cfe/trunk/include/clang/Sema/ScopeInfo.h
> > cfe/trunk/include/clang/Sema/Sema.h
> > cfe/trunk/lib/AST/ASTContext.cpp
> > cfe/trunk/lib/AST/ASTImporter.cpp
> > cfe/trunk/lib/AST/DeclCXX.cpp
> > cfe/trunk/lib/AST/ExprCXX.cpp
> > cfe/trunk/lib/AST/Type.cpp
> > cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> > cfe/trunk/lib/Parse/ParseDecl.cpp
> > cfe/trunk/lib/Parse/ParseExprCXX.cpp
> > cfe/trunk/lib/Parse/Parser.cpp
> > cfe/trunk/lib/Sema/Sema.cpp
> > cfe/trunk/lib/Sema/SemaDecl.cpp
> > cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > cfe/trunk/lib/Sema/SemaLambda.cpp
> > cfe/trunk/lib/Sema/SemaOverload.cpp
> > cfe/trunk/lib/Sema/SemaStmt.cpp
> > cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
> > cfe/trunk/lib/Sema/SemaType.cpp
> > cfe/trunk/lib/Sema/TreeTransform.h
> > cfe/trunk/lib/Serialization/ASTReader.cpp
> > cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > cfe/trunk/lib/Serialization/ASTWriter.cpp
> > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp
> > cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
> >
> > Modified: cfe/trunk/include/clang/AST/ASTContext.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> > +++ cfe/trunk/include/clang/AST/ASTContext.h Wed Aug 21 20:49:11 2013
> > @@ -1115,7 +1115,7 @@ public:
> >
> > /// \brief C++11 deduced auto type.
> > QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto,
> > - bool IsDependent = false) const;
> > + bool IsDependent, bool IsParameterPack) const;
> >
> > /// \brief C++11 deduction pattern for 'auto' type.
> > QualType getAutoDeductType() const;
> >
> > Modified: cfe/trunk/include/clang/AST/DeclCXX.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclCXX.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/DeclCXX.h (original)
> > +++ cfe/trunk/include/clang/AST/DeclCXX.h Wed Aug 21 20:49:11 2013
> > @@ -516,8 +516,8 @@ class CXXRecordDecl : public RecordDecl
> >
> > LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool
> Dependent)
> > : DefinitionData(D), Dependent(Dependent), NumCaptures(0),
> > - NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0),
> Captures(0),
> > - MethodTyInfo(Info)
> > + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0),
> > + Captures(0), MethodTyInfo(Info), TheLambdaExpr(0)
> > {
> > IsLambda = true;
> > }
> > @@ -529,7 +529,7 @@ class CXXRecordDecl : public RecordDecl
> > /// within the default argument of a function template, because the
> > /// lambda will have been created with the enclosing context as its
> > /// declaration context, rather than function. This is an unfortunate
> > - /// artifact of having to parse the default arguments before
> > + /// artifact of having to parse the default arguments before.
> > unsigned Dependent : 1;
> >
> > /// \brief The number of captures in this lambda.
> > @@ -554,6 +554,10 @@ class CXXRecordDecl : public RecordDecl
> >
> > /// \brief The type of the call method.
> > TypeSourceInfo *MethodTyInfo;
> > +
> > + /// \brief The AST node of the lambda expression.
> > + LambdaExpr *TheLambdaExpr;
> > +
> > };
> >
> > struct DefinitionData &data() {
> > @@ -989,6 +993,36 @@ public:
> > /// \brief Determine whether this class describes a lambda function
> object.
> > bool isLambda() const { return hasDefinition() && data().IsLambda; }
> >
> > + /// \brief Determine whether this class describes a generic
> > + /// lambda function object (i.e. function call operator is
> > + /// a template).
> > + bool isGenericLambda() const;
> > +
> > + /// \brief Retrieve the lambda call operator of the closure type
> > + /// if this is a closure type.
> > + CXXMethodDecl* getLambdaCallOperator() const;
> > +
> > + /// \brief Retrieve the lambda static invoker, the address of which
> > + /// is returned by the conversion operator, and the body of which
> > + /// is forwarded to the lambda call operator.
> > + CXXMethodDecl* getLambdaStaticInvoker() const;
> > +
> > + /// \brief Retrieve the generic lambda's template parameter list.
> > + /// Returns null if the class does not represent a lambda or a generic
> > + /// lambda.
> > + TemplateParameterList* getGenericLambdaTemplateParameterList() const;
> > +
> > + /// \brief Assign the member call operator of the lambda.
> > + void setLambdaExpr(LambdaExpr *E) {
> > + getLambdaData().TheLambdaExpr = E;
> > + }
> > +
> > + /// \brief Retrieve the parent lambda expression.
> > + LambdaExpr* getLambdaExpr() const {
> > + return isLambda() ? getLambdaData().TheLambdaExpr : 0;
> > + }
> > +
> > +
> > /// \brief For a closure type, retrieve the mapping from captured
> > /// variables and \c this to the non-static data members that store the
> > /// values or references of the captures.
> >
> > Modified: cfe/trunk/include/clang/AST/ExprCXX.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExprCXX.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/ExprCXX.h (original)
> > +++ cfe/trunk/include/clang/AST/ExprCXX.h Wed Aug 21 20:49:11 2013
> > @@ -1605,6 +1605,13 @@ public:
> > /// lambda expression.
> > CXXMethodDecl *getCallOperator() const;
> >
> > + /// \brief If this is a generic lambda expression, retrieve the
> template
> > + /// parameter list associated with it, or else return null.
> > + TemplateParameterList *getTemplateParameterList() const;
> > +
> > + /// \brief Whether this is a generic lambda.
> > + bool isGenericLambda() const { return !!getTemplateParameterList(); }
> > +
> > /// \brief Retrieve the body of the lambda.
> > CompoundStmt *getBody() const;
> >
> >
> > Modified: cfe/trunk/include/clang/AST/Type.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/AST/Type.h (original)
> > +++ cfe/trunk/include/clang/AST/Type.h Wed Aug 21 20:49:11 2013
> > @@ -3614,10 +3614,11 @@ public:
> > /// is no deduced type and an auto type is canonical. In the latter
> case, it is
> > /// also a dependent type.
> > class AutoType : public Type, public llvm::FoldingSetNode {
> > - AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent)
> > + AutoType(QualType DeducedType, bool IsDecltypeAuto,
> > + bool IsDependent, bool IsParameterPack)
> > : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType,
> > /*Dependent=*/IsDependent,
> /*InstantiationDependent=*/IsDependent,
> > - /*VariablyModified=*/false, /*ContainsParameterPack=*/false)
> {
> > + /*VariablyModified=*/false,
> /*ContainsParameterPack=*/IsParameterPack) {
> > assert((DeducedType.isNull() || !IsDependent) &&
> > "auto deduced to dependent type");
> > AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto;
> > @@ -3641,14 +3642,17 @@ public:
> > }
> >
> > void Profile(llvm::FoldingSetNodeID &ID) {
> > - Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType());
> > + Profile(ID, getDeducedType(), isDecltypeAuto(),
> > + isDependentType(), containsUnexpandedParameterPack());
> > }
> >
> > static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced,
> > - bool IsDecltypeAuto, bool IsDependent) {
> > + bool IsDecltypeAuto, bool IsDependent,
> > + bool IsParameterPack) {
> > ID.AddPointer(Deduced.getAsOpaquePtr());
> > ID.AddBoolean(IsDecltypeAuto);
> > ID.AddBoolean(IsDependent);
> > + ID.AddBoolean(IsParameterPack);
> > }
> >
> > static bool classof(const Type *T) {
> >
> > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Aug 21
> 20:49:11 2013
> > @@ -5050,6 +5050,10 @@ let CategoryName = "Lambda Issue" in {
> > "cannot deduce type for lambda capture %0 from initializer list">;
> > }
> >
> > +// C++1y Generic Lambdas
> > +def err_glambda_not_fully_implemented : Error<
> > + "unimplemented generic lambda feature: %0">;
> > +
> > def err_return_in_captured_stmt : Error<
> > "cannot return from %0">;
> > def err_capture_block_variable : Error<
> >
> > Modified: cfe/trunk/include/clang/Sema/DeclSpec.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/DeclSpec.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/DeclSpec.h (original)
> > +++ cfe/trunk/include/clang/Sema/DeclSpec.h Wed Aug 21 20:49:11 2013
> > @@ -1502,6 +1502,7 @@ public:
> > ObjCCatchContext, // Objective-C catch exception-declaration
> > BlockLiteralContext, // Block literal declarator.
> > LambdaExprContext, // Lambda-expression declarator.
> > + LambdaExprParameterContext, // Lambda-expression parameter
> declarator.
> > ConversionIdContext, // C++ conversion-type-id.
> > TrailingReturnContext, // C++11 trailing-type-specifier.
> > TemplateTypeArgContext, // Template type argument.
> > @@ -1577,7 +1578,6 @@ public:
> > ~Declarator() {
> > clear();
> > }
> > -
> > /// getDeclSpec - Return the declaration-specifier that this
> declarator was
> > /// declared with.
> > const DeclSpec &getDeclSpec() const { return DS; }
> > @@ -1606,7 +1606,8 @@ public:
> > bool isPrototypeContext() const {
> > return (Context == PrototypeContext ||
> > Context == ObjCParameterContext ||
> > - Context == ObjCResultContext);
> > + Context == ObjCResultContext ||
> > + Context == LambdaExprParameterContext);
> > }
> >
> > /// \brief Get the source range that spans this declarator.
> > @@ -1670,6 +1671,7 @@ public:
> > case AliasDeclContext:
> > case AliasTemplateContext:
> > case PrototypeContext:
> > + case LambdaExprParameterContext:
> > case ObjCParameterContext:
> > case ObjCResultContext:
> > case TemplateParamContext:
> > @@ -1698,6 +1700,7 @@ public:
> > case ForContext:
> > case ConditionContext:
> > case PrototypeContext:
> > + case LambdaExprParameterContext:
> > case TemplateParamContext:
> > case CXXCatchContext:
> > case ObjCCatchContext:
> > @@ -1730,6 +1733,7 @@ public:
> > case ForContext:
> > case ConditionContext:
> > case PrototypeContext:
> > + case LambdaExprParameterContext:
> > case TemplateParamContext:
> > case CXXCatchContext:
> > case ObjCCatchContext:
> > @@ -1782,6 +1786,7 @@ public:
> > case KNRTypeListContext:
> > case MemberContext:
> > case PrototypeContext:
> > + case LambdaExprParameterContext:
> > case ObjCParameterContext:
> > case ObjCResultContext:
> > case TemplateParamContext:
> > @@ -1968,6 +1973,7 @@ public:
> > case AliasDeclContext:
> > case AliasTemplateContext:
> > case PrototypeContext:
> > + case LambdaExprParameterContext:
> > case ObjCParameterContext:
> > case ObjCResultContext:
> > case TemplateParamContext:
> >
> > Modified: cfe/trunk/include/clang/Sema/ScopeInfo.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ScopeInfo.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/ScopeInfo.h (original)
> > +++ cfe/trunk/include/clang/Sema/ScopeInfo.h Wed Aug 21 20:49:11 2013
> > @@ -35,6 +35,8 @@ class LabelDecl;
> > class ReturnStmt;
> > class Scope;
> > class SwitchStmt;
> > +class TemplateTypeParmDecl;
> > +class TemplateParameterList;
> > class VarDecl;
> > class DeclRefExpr;
> > class ObjCIvarRefExpr;
> > @@ -613,12 +615,27 @@ public:
> > /// \brief Offsets into the ArrayIndexVars array at which each capture
> starts
> > /// its list of array index variables.
> > SmallVector<unsigned, 4> ArrayIndexStarts;
> > +
> > + /// \brief If this is a generic lambda, use this as the depth of
> > + /// each 'auto' parameter, during initial AST construction.
> > + unsigned AutoTemplateParameterDepth;
> > +
> > + // If this is a generic lambda, store the list of the auto
> > + // parameters converted into TemplateTypeParmDecls into a vector
> > + // that can be used to construct the generic lambda's template
> > + // parameter list, during initial AST construction.
> > + /// \brief Store the list of the auto parameters for a generic lambda.
> > + SmallVector<TemplateTypeParmDecl*, 4> AutoTemplateParams;
> >
> > - LambdaScopeInfo(DiagnosticsEngine &Diag, CXXRecordDecl *Lambda,
> > - CXXMethodDecl *CallOperator)
> > - : CapturingScopeInfo(Diag, ImpCap_None), Lambda(Lambda),
> > - CallOperator(CallOperator), NumExplicitCaptures(0),
> Mutable(false),
> > - ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false)
> > + // If this is a generic lambda, store its template parameter list.
> > + TemplateParameterList *GLTemplateParameterList;
> > +
> > + LambdaScopeInfo(DiagnosticsEngine &Diag)
> > + : CapturingScopeInfo(Diag, ImpCap_None), Lambda(0),
> > + CallOperator(0), NumExplicitCaptures(0), Mutable(false),
> > + ExprNeedsCleanups(false), ContainsUnexpandedParameterPack(false),
> > + AutoTemplateParameterDepth(0),
> > + GLTemplateParameterList(0)
> > {
> > Kind = SK_Lambda;
> > }
> > @@ -631,8 +648,10 @@ public:
> > }
> >
> > static bool classof(const FunctionScopeInfo *FSI) {
> > - return FSI->Kind == SK_Lambda;
> > + return FSI->Kind == SK_Lambda;
> > }
> > +
> > +
> > };
> >
> >
> >
> > Modified: cfe/trunk/include/clang/Sema/Sema.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/Sema.h (original)
> > +++ cfe/trunk/include/clang/Sema/Sema.h Wed Aug 21 20:49:11 2013
> > @@ -969,7 +969,13 @@ public:
> >
> > void PushFunctionScope();
> > void PushBlockScope(Scope *BlockScope, BlockDecl *Block);
> > - void PushLambdaScope(CXXRecordDecl *Lambda, CXXMethodDecl
> *CallOperator);
> > + void PushLambdaScope();
> > +
> > + // This is used to inform Sema what the current TemplateParameterDepth
> > + // is during Parsing. Currently it is used to pass on the depth
> > + // when parsing generic lambda 'auto' parameters.
> > + void RecordParsingTemplateParameterDepth(unsigned Depth);
> > +
> > void PushCapturedRegionScope(Scope *RegionScope, CapturedDecl *CD,
> > RecordDecl *RD,
> > CapturedRegionKind K);
> > @@ -996,9 +1002,12 @@ public:
> > /// \brief Retrieve the current block, if any.
> > sema::BlockScopeInfo *getCurBlock();
> >
> > - /// \brief Retrieve the current lambda expression, if any.
> > + /// \brief Retrieve the current lambda scope info, if any.
> > sema::LambdaScopeInfo *getCurLambda();
> >
> > + /// \brief Retrieve the current generic lambda info, if any.
> > + sema::LambdaScopeInfo *getCurGenericLambda();
> > +
> > /// \brief Retrieve the current captured region, if any.
> > sema::CapturedRegionScopeInfo *getCurCapturedRegion();
> >
> > @@ -4402,6 +4411,10 @@ public:
> > /// initializer for the declaration 'Dcl'.
> > void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl);
> >
> > + /// \brief Invoked when an auto parameter is parsed
> > + /// in a lambda's parameter declaration clause.
> > + ParmVarDecl *ActOnLambdaAutoParameter(ParmVarDecl *P);
> > +
> > /// \brief Create a new lambda closure type.
> > CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange,
> > TypeSourceInfo *Info,
> > @@ -4414,14 +4427,15 @@ public:
> > SourceLocation EndLoc,
> > ArrayRef<ParmVarDecl *> Params);
> >
> > - /// \brief Introduce the scope for a lambda expression.
> > - sema::LambdaScopeInfo *enterLambdaScope(CXXMethodDecl *CallOperator,
> > - SourceRange IntroducerRange,
> > - LambdaCaptureDefault
> CaptureDefault,
> > - SourceLocation
> CaptureDefaultLoc,
> > - bool ExplicitParams,
> > - bool ExplicitResultType,
> > - bool Mutable);
> > + /// \brief Endow the lambda scope info with the relevant properties.
> > + void buildLambdaScope(sema::LambdaScopeInfo *LSI,
> > + CXXMethodDecl *CallOperator,
> > + SourceRange IntroducerRange,
> > + LambdaCaptureDefault CaptureDefault,
> > + SourceLocation CaptureDefaultLoc,
> > + bool ExplicitParams,
> > + bool ExplicitResultType,
> > + bool Mutable);
> >
> > /// \brief Check and build an init-capture with the specified name and
> > /// initializer.
> > @@ -5806,6 +5820,12 @@ public:
> > sema::TemplateDeductionInfo &Info,
> > bool InOverloadResolution = false);
> >
> > + /// \brief Substitute Replacement for \p auto in \p TypeWithAuto
> > + QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
> > + /// \brief Substitute Replacement for auto in TypeWithAuto
> > + TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto,
> > + QualType Replacement);
> > +
> > /// \brief Result type of DeduceAutoType.
> > enum DeduceAutoResult {
> > DAR_Succeeded,
> > @@ -5817,7 +5837,6 @@ public:
> > QualType &Result);
> > DeduceAutoResult DeduceAutoType(TypeLoc AutoTypeLoc, Expr
> *&Initializer,
> > QualType &Result);
> > - QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement);
> > void DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init);
> > bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc,
> > bool Diagnose = true);
> >
> > Added: cfe/trunk/include/clang/Sema/SemaLambda.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/SemaLambda.h?rev=188977&view=auto
> >
> ==============================================================================
> > --- cfe/trunk/include/clang/Sema/SemaLambda.h (added)
> > +++ cfe/trunk/include/clang/Sema/SemaLambda.h Wed Aug 21 20:49:11 2013
> > @@ -0,0 +1,44 @@
> > +//===--- SemaLambda.h - Lambda Helper Functions --------------*- C++
> -*-===//
> > +//
> > +// The LLVM Compiler Infrastructure
> > +//
> > +// This file is distributed under the University of Illinois Open Source
> > +// License. See LICENSE.TXT for details.
> > +//
> >
> +//===----------------------------------------------------------------------===//
> > +///
> > +/// \file
> > +/// \brief This file provides some common utility functions for
> processing
> > +/// Lambdas.
> > +///
> >
> +//===----------------------------------------------------------------------===//
> > +
> > +#ifndef LLVM_CLANG_SEMA_LAMBDA_H
> > +#define LLVM_CLANG_SEMA_LAMBDA_H
> > +
> > +#include "clang/AST/DeclCXX.h"
> > +#include "clang/AST/DeclTemplate.h"
> > +#include "clang/Sema/ScopeInfo.h"
> > +
> > +namespace clang {
> > +static inline const char *getLambdaStaticInvokerName() {
> > + return "__invoke";
> > +}
> > +static inline bool
> isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) {
> > + if (MD) {
> > + CXXRecordDecl *LambdaClass = MD->getParent();
> > + if (LambdaClass && LambdaClass->isGenericLambda()) {
> > + return LambdaClass->getLambdaCallOperator()
> > + == MD->getTemplateInstantiationPattern();
> > + }
> > + }
> > + return false;
> > +}
> > +
> > +static inline bool isGenericLambdaCallOperatorSpecialization(Decl *D) {
> > + return isGenericLambdaCallOperatorSpecialization(
> > + dyn_cast<CXXMethodDecl>(D));
> > +}
> > +} // clang
> > +
> > +#endif // LLVM_CLANG_SEMA_LAMBDA_H
> >
> > Modified: cfe/trunk/lib/AST/ASTContext.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> > +++ cfe/trunk/lib/AST/ASTContext.cpp Wed Aug 21 20:49:11 2013
> > @@ -3649,20 +3649,24 @@ QualType ASTContext::getUnaryTransformTy
> > /// deduced to the given type, or to the canonical undeduced 'auto'
> type, or the
> > /// canonical deduced-but-dependent 'auto' type.
> > QualType ASTContext::getAutoType(QualType DeducedType, bool
> IsDecltypeAuto,
> > - bool IsDependent) const {
> > - if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent)
> > + bool IsDependent, bool IsParameterPack)
> const {
> > + if (DeducedType.isNull() && !IsDecltypeAuto && !IsDependent &&
> > + !IsParameterPack)
> > return getAutoDeductType();
> > -
> > + assert(!IsParameterPack || DeducedType.isNull()
> > + && "Auto parameter pack: auto ... a should always be
> undeduced!");
> > // Look in the folding set for an existing type.
> > void *InsertPos = 0;
> > llvm::FoldingSetNodeID ID;
> > - AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent);
> > + AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent,
> > + IsParameterPack);
> > if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos))
> > return QualType(AT, 0);
> >
> > AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType,
> > IsDecltypeAuto,
> > - IsDependent);
> > + IsDependent,
> > + IsParameterPack);
> > Types.push_back(AT);
> > if (InsertPos)
> > AutoTypes.InsertNode(AT, InsertPos);
> > @@ -3702,7 +3706,8 @@ QualType ASTContext::getAutoDeductType()
> > if (AutoDeductTy.isNull())
> > AutoDeductTy = QualType(
> > new (*this, TypeAlignment) AutoType(QualType(),
> /*decltype(auto)*/false,
> > - /*dependent*/false),
> > + /*dependent*/false,
> > + /*IsParameterPack*/false),
> > 0);
> > return AutoDeductTy;
> > }
> >
> > Modified: cfe/trunk/lib/AST/ASTImporter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ASTImporter.cpp (original)
> > +++ cfe/trunk/lib/AST/ASTImporter.cpp Wed Aug 21 20:49:11 2013
> > @@ -1709,7 +1709,9 @@ QualType ASTNodeImporter::VisitAutoType(
> > return QualType();
> > }
> >
> > - return Importer.getToContext().getAutoType(ToDeduced,
> T->isDecltypeAuto());
> > + return Importer.getToContext().getAutoType(ToDeduced,
> T->isDecltypeAuto(),
> > + /*IsDependent*/false,
> > +
> T->containsUnexpandedParameterPack());
> > }
> >
> > QualType ASTNodeImporter::VisitRecordType(const RecordType *T) {
> >
> > Modified: cfe/trunk/lib/AST/DeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/DeclCXX.cpp (original)
> > +++ cfe/trunk/lib/AST/DeclCXX.cpp Wed Aug 21 20:49:11 2013
> > @@ -20,6 +20,7 @@
> > #include "clang/AST/ExprCXX.h"
> > #include "clang/AST/TypeLoc.h"
> > #include "clang/Basic/IdentifierTable.h"
> > +#include "clang/Sema/SemaLambda.h"
> > #include "llvm/ADT/STLExtras.h"
> > #include "llvm/ADT/SmallPtrSet.h"
> > using namespace clang;
> > @@ -930,6 +931,40 @@ bool CXXRecordDecl::isCLike() const {
> > return isPOD() && data().HasOnlyCMembers;
> > }
> >
> > +bool CXXRecordDecl::isGenericLambda() const {
> > + return isLambda() &&
> > + getLambdaCallOperator()->getDescribedFunctionTemplate();
> > +}
> > +
> > +CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const {
> > + if (!isLambda()) return 0;
> > + DeclarationName Name =
> > + getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
> > + DeclContext::lookup_const_result Calls = lookup(Name);
> > +
> > + assert(!Calls.empty() && "Missing lambda call operator!");
> > + assert(Calls.size() == 1 && "More than one lambda call operator!");
> > +
> > + NamedDecl *CallOp = Calls.front();
> > + if (FunctionTemplateDecl *CallOpTmpl =
> > + dyn_cast<FunctionTemplateDecl>(CallOp))
> > + return cast<CXXMethodDecl>(CallOpTmpl->getTemplatedDecl());
> > +
> > + return cast<CXXMethodDecl>(CallOp);
> > +}
> > +
> > +CXXMethodDecl* CXXRecordDecl::getLambdaStaticInvoker() const {
> > + if (!isLambda()) return 0;
> > + DeclarationName Name =
> > + &getASTContext().Idents.get(getLambdaStaticInvokerName());
> > + DeclContext::lookup_const_result Invoker = lookup(Name);
> > + if (Invoker.empty()) return 0;
> > + assert(Invoker.size() == 1 && "More than one static invoker
> operator!");
> > + CXXMethodDecl *Result = cast<CXXMethodDecl>(Invoker.front());
> > + return Result;
> > +
> > +}
> > +
> > void CXXRecordDecl::getCaptureFields(
> > llvm::DenseMap<const VarDecl *, FieldDecl *> &Captures,
> > FieldDecl *&ThisCapture) const {
> > @@ -947,6 +982,14 @@ void CXXRecordDecl::getCaptureFields(
> > }
> > }
> >
> > +TemplateParameterList*
> > + CXXRecordDecl::getGenericLambdaTemplateParameterList() const {
> > + if (!isLambda()) return 0;
> > + CXXMethodDecl *CallOp = getLambdaCallOperator();
> > + if (FunctionTemplateDecl *Tmpl =
> CallOp->getDescribedFunctionTemplate())
> > + return Tmpl->getTemplateParameters();
> > + return 0;
> > +}
> >
> > static CanQualType GetConversionType(ASTContext &Context, NamedDecl
> *Conv) {
> > QualType T;
> > @@ -1493,7 +1536,7 @@ bool CXXMethodDecl::hasInlineBody() cons
> >
> > bool CXXMethodDecl::isLambdaStaticInvoker() const {
> > return getParent()->isLambda() &&
> > - getIdentifier() && getIdentifier()->getName() == "__invoke";
> > + getParent()->getLambdaStaticInvoker() == this;
> > }
> >
> >
> >
> > Modified: cfe/trunk/lib/AST/ExprCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/ExprCXX.cpp (original)
> > +++ cfe/trunk/lib/AST/ExprCXX.cpp Wed Aug 21 20:49:11 2013
> > @@ -1026,13 +1026,13 @@ CXXRecordDecl *LambdaExpr::getLambdaClas
> >
> > CXXMethodDecl *LambdaExpr::getCallOperator() const {
> > CXXRecordDecl *Record = getLambdaClass();
> > - DeclarationName Name
> > - =
> Record->getASTContext().DeclarationNames.getCXXOperatorName(OO_Call);
> > - DeclContext::lookup_result Calls = Record->lookup(Name);
> > - assert(!Calls.empty() && "Missing lambda call operator!");
> > - assert(Calls.size() == 1 && "More than one lambda call operator!");
> > - CXXMethodDecl *Result = cast<CXXMethodDecl>(Calls.front());
> > - return Result;
> > + return Record->getLambdaCallOperator();
> > +}
> > +
> > +TemplateParameterList *LambdaExpr::getTemplateParameterList() const {
> > + CXXRecordDecl *Record = getLambdaClass();
> > + return Record->getGenericLambdaTemplateParameterList();
> > +
> > }
> >
> > CompoundStmt *LambdaExpr::getBody() const {
> >
> > Modified: cfe/trunk/lib/AST/Type.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Type.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/AST/Type.cpp (original)
> > +++ cfe/trunk/lib/AST/Type.cpp Wed Aug 21 20:49:11 2013
> > @@ -589,6 +589,10 @@ namespace {
> > AutoType *VisitAttributedType(const AttributedType *T) {
> > return Visit(T->getModifiedType());
> > }
> > + AutoType *VisitPackExpansionType(const PackExpansionType *T) {
> > + return Visit(T->getPattern());
> > + }
> > +
> > };
> > }
> >
> >
> > Modified: cfe/trunk/lib/CodeGen/CodeGenFunction.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CodeGenFunction.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/CodeGen/CodeGenFunction.cpp (original)
> > +++ cfe/trunk/lib/CodeGen/CodeGenFunction.cpp Wed Aug 21 20:49:11 2013
> > @@ -700,7 +700,7 @@ void CodeGenFunction::GenerateCode(Globa
> > EmitLambdaToBlockPointerBody(Args);
> > } else if (isa<CXXMethodDecl>(FD) &&
> > cast<CXXMethodDecl>(FD)->isLambdaStaticInvoker()) {
> > - // The lambda "__invoke" function is special, because it forwards or
> > + // The lambda static invoker function is special, because it
> forwards or
> > // clones the body of the function call operator (but is actually
> static).
> > EmitLambdaStaticInvokeFunction(cast<CXXMethodDecl>(FD));
> > } else if (FD->isDefaulted() && isa<CXXMethodDecl>(FD) &&
> >
> > Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseDecl.cpp Wed Aug 21 20:49:11 2013
> > @@ -4670,6 +4670,7 @@ void Parser::ParseDirectDeclarator(Decla
> > // as part of the parameter-declaration-clause.
> > if (Tok.is(tok::ellipsis) && D.getCXXScopeSpec().isEmpty() &&
> > !((D.getContext() == Declarator::PrototypeContext ||
> > + D.getContext() == Declarator::LambdaExprParameterContext ||
> > D.getContext() == Declarator::BlockLiteralContext) &&
> > NextToken().is(tok::r_paren) &&
> > !D.hasGroupingParens() &&
> > @@ -4988,7 +4989,6 @@ void Parser::ParseFunctionDeclarator(Dec
> > TypeResult TrailingReturnType;
> >
> > Actions.ActOnStartFunctionDeclarator();
> > -
> > /* LocalEndLoc is the end location for the local FunctionTypeLoc.
> > EndLoc is the end location for the function declarator.
> > They differ for trailing return types. */
> > @@ -5009,7 +5009,8 @@ void Parser::ParseFunctionDeclarator(Dec
> > EndLoc = RParenLoc;
> > } else {
> > if (Tok.isNot(tok::r_paren))
> > - ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
> EllipsisLoc);
> > + ParseParameterDeclarationClause(D, FirstArgAttrs, ParamInfo,
> > + EllipsisLoc);
> > else if (RequiresArg)
> > Diag(Tok, diag::err_argument_required_after_attribute);
> >
> > @@ -5240,7 +5241,6 @@ void Parser::ParseParameterDeclarationCl
> > ParsedAttributes &FirstArgAttrs,
> > SmallVectorImpl<DeclaratorChunk::ParamInfo> &ParamInfo,
> > SourceLocation &EllipsisLoc) {
> > -
> > while (1) {
> > if (Tok.is(tok::ellipsis)) {
> > // FIXME: Issue a diagnostic if we parsed an
> attribute-specifier-seq
> > @@ -5270,16 +5270,21 @@ void Parser::ParseParameterDeclarationCl
> >
> > ParseDeclarationSpecifiers(DS);
> >
> > - // Parse the declarator. This is "PrototypeContext", because we
> must
> > - // accept either 'declarator' or 'abstract-declarator' here.
> > - Declarator ParmDecl(DS, Declarator::PrototypeContext);
> > - ParseDeclarator(ParmDecl);
> > +
> > + // Parse the declarator. This is "PrototypeContext" or
> > + // "LambdaExprParameterContext", because we must accept either
> > + // 'declarator' or 'abstract-declarator' here.
> > + Declarator ParmDeclarator(DS,
> > + D.getContext() == Declarator::LambdaExprContext ?
> > +
> Declarator::LambdaExprParameterContext :
> > +
> Declarator::PrototypeContext);
> > + ParseDeclarator(ParmDeclarator);
> >
> > // Parse GNU attributes, if present.
> > - MaybeParseGNUAttributes(ParmDecl);
> > + MaybeParseGNUAttributes(ParmDeclarator);
> >
> > // Remember this parsed parameter in ParamInfo.
> > - IdentifierInfo *ParmII = ParmDecl.getIdentifier();
> > + IdentifierInfo *ParmII = ParmDeclarator.getIdentifier();
> >
> > // DefArgToks is used when the parsing of default arguments needs
> > // to be delayed.
> > @@ -5287,8 +5292,8 @@ void Parser::ParseParameterDeclarationCl
> >
> > // If no parameter was specified, verify that *something* was
> specified,
> > // otherwise we have a missing type and identifier.
> > - if (DS.isEmpty() && ParmDecl.getIdentifier() == 0 &&
> > - ParmDecl.getNumTypeObjects() == 0) {
> > + if (DS.isEmpty() && ParmDeclarator.getIdentifier() == 0 &&
> > + ParmDeclarator.getNumTypeObjects() == 0) {
> > // Completely missing, emit error.
> > Diag(DSStart, diag::err_missing_param);
> > } else {
> > @@ -5297,8 +5302,8 @@ void Parser::ParseParameterDeclarationCl
> >
> > // Inform the actions module about the parameter declarator, so it
> gets
> > // added to the current scope.
> > - Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),
> ParmDecl);
> > -
> > + Decl *Param = Actions.ActOnParamDeclarator(getCurScope(),
> > + ParmDeclarator);
> > // Parse the default argument, if any. We parse the default
> > // arguments in all dialects; the semantic analysis in
> > // ActOnParamDefaultArgument will reject the default argument in
> > @@ -5359,8 +5364,8 @@ void Parser::ParseParameterDeclarationCl
> > }
> >
> > ParamInfo.push_back(DeclaratorChunk::ParamInfo(ParmII,
> > - ParmDecl.getIdentifierLoc(),
> Param,
> > - DefArgToks));
> > +
> ParmDeclarator.getIdentifierLoc(),
> > + Param, DefArgToks));
> > }
> >
> > // If the next token is a comma, consume it and keep reading
> arguments.
> >
> > Modified: cfe/trunk/lib/Parse/ParseExprCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseExprCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/ParseExprCXX.cpp (original)
> > +++ cfe/trunk/lib/Parse/ParseExprCXX.cpp Wed Aug 21 20:49:11 2013
> > @@ -20,6 +20,7 @@
> > #include "clang/Sema/ParsedTemplate.h"
> > #include "clang/Sema/Scope.h"
> > #include "llvm/Support/ErrorHandling.h"
> > +#include "clang/AST/DeclTemplate.h"
> >
> > using namespace clang;
> >
> > @@ -908,12 +909,16 @@ ExprResult Parser::ParseLambdaExpression
> > PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), LambdaBeginLoc,
> > "lambda expression parsing");
> >
> > +
> > +
> > // FIXME: Call into Actions to add any init-capture declarations to the
> > // scope while parsing the lambda-declarator and compound-statement.
> >
> > // Parse lambda-declarator[opt].
> > DeclSpec DS(AttrFactory);
> > Declarator D(DS, Declarator::LambdaExprContext);
> > + TemplateParameterDepthRAII
> CurTemplateDepthTracker(TemplateParameterDepth);
> > + Actions.PushLambdaScope();
> >
> > if (Tok.is(tok::l_paren)) {
> > ParseScope PrototypeScope(this,
> > @@ -931,9 +936,17 @@ ExprResult Parser::ParseLambdaExpression
> > SmallVector<DeclaratorChunk::ParamInfo, 16> ParamInfo;
> > SourceLocation EllipsisLoc;
> >
> > - if (Tok.isNot(tok::r_paren))
> > +
> > + if (Tok.isNot(tok::r_paren)) {
> > + sema::LambdaScopeInfo *LSI = Actions.getCurLambda();
> > + if (getLangOpts().CPlusPlus1y)
> > +
> Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
> > ParseParameterDeclarationClause(D, Attr, ParamInfo, EllipsisLoc);
> > -
> > + // For a generic lambda, each 'auto' within the parameter
> declaration
> > + // clause creates a template type parameter, so increment the
> depth.
> > + if (getLangOpts().CPlusPlus1y && Actions.getCurGenericLambda())
> > + ++CurTemplateDepthTracker;
> > + }
> > T.consumeClose();
> > SourceLocation RParenLoc = T.getCloseLocation();
> > DeclEndLoc = RParenLoc;
> >
> > Modified: cfe/trunk/lib/Parse/Parser.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Parse/Parser.cpp (original)
> > +++ cfe/trunk/lib/Parse/Parser.cpp Wed Aug 21 20:49:11 2013
> > @@ -1175,7 +1175,6 @@ void Parser::ParseKNRParamDeclarations(D
> > // Ask the actions module to compute the type for this declarator.
> > Decl *Param =
> > Actions.ActOnParamDeclarator(getCurScope(), ParmDeclarator);
> > -
> > if (Param &&
> > // A missing identifier has already been diagnosed.
> > ParmDeclarator.getIdentifier()) {
> >
> > Modified: cfe/trunk/lib/Sema/Sema.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/Sema.cpp (original)
> > +++ cfe/trunk/lib/Sema/Sema.cpp Wed Aug 21 20:49:11 2013
> > @@ -1007,10 +1007,17 @@ void Sema::PushBlockScope(Scope *BlockSc
> > BlockScope, Block));
> > }
> >
> > -void Sema::PushLambdaScope(CXXRecordDecl *Lambda,
> > - CXXMethodDecl *CallOperator) {
> > - FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics(), Lambda,
> > - CallOperator));
> > +void Sema::PushLambdaScope() {
> > + FunctionScopes.push_back(new LambdaScopeInfo(getDiagnostics()));
> > +}
> > +
> > +void Sema::RecordParsingTemplateParameterDepth(unsigned Depth) {
> > + if (LambdaScopeInfo *const LSI = getCurLambda()) {
> > + LSI->AutoTemplateParameterDepth = Depth;
> > + return;
> > + }
> > + assert(false &&
> > + "Remove assertion if intentionally called in a non-lambda
> context.");
> > }
> >
> > void Sema::PopFunctionScopeInfo(const AnalysisBasedWarnings::Policy *WP,
> > @@ -1066,6 +1073,16 @@ LambdaScopeInfo *Sema::getCurLambda() {
> >
> > return dyn_cast<LambdaScopeInfo>(FunctionScopes.back());
> > }
> > +// We have a generic lambda if we parsed auto parameters, or we have
> > +// an associated template parameter list.
> > +LambdaScopeInfo *Sema::getCurGenericLambda() {
> > + if (LambdaScopeInfo *LSI = getCurLambda()) {
> > + return (LSI->AutoTemplateParams.size() ||
> > + LSI->GLTemplateParameterList) ? LSI : 0;
> > + }
> > + return 0;
> > +}
> > +
> >
> > void Sema::ActOnComment(SourceRange Comment) {
> > if (!LangOpts.RetainCommentsFromSystemHeaders &&
> >
> > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Aug 21 20:49:11 2013
> > @@ -35,6 +35,7 @@
> > #include "clang/Sema/DeclSpec.h"
> > #include "clang/Sema/DelayedDiagnostic.h"
> > #include "clang/Sema/Initialization.h"
> > +#include "clang/Sema/SemaLambda.h"
> > #include "clang/Sema/Lookup.h"
> > #include "clang/Sema/ParsedTemplate.h"
> > #include "clang/Sema/Scope.h"
> > @@ -8909,6 +8910,7 @@ Decl *Sema::ActOnParamDeclarator(Scope *
> > const DeclSpec &DS = D.getDeclSpec();
> >
> > // Verify C99 6.7.5.3p2: The only SCS allowed is 'register'.
> > +
> > // C++03 [dcl.stc]p2 also permits 'auto'.
> > VarDecl::StorageClass StorageClass = SC_None;
> > if (DS.getStorageClassSpec() == DeclSpec::SCS_register) {
> > @@ -9015,6 +9017,14 @@ Decl *Sema::ActOnParamDeclarator(Scope *
> > if (New->hasAttr<BlocksAttr>()) {
> > Diag(New->getLocation(), diag::err_block_on_nonlocal);
> > }
> > +
> > + // Handle 'auto' within a generic lambda.
> > + QualType ParamType = New->getType();
> > + if (getLangOpts().CPlusPlus1y && ParamType->getContainedAutoType()) {
> > + assert(getCurLambda() &&
> > + "'auto' in parameter type only allowed in lambdas!");
> > + New = ActOnLambdaAutoParameter(New);
> > + }
> > return New;
> > }
> >
> > @@ -9268,9 +9278,38 @@ Decl *Sema::ActOnStartOfFunctionDef(Scop
> > FD = FunTmpl->getTemplatedDecl();
> > else
> > FD = cast<FunctionDecl>(D);
> > -
> > - // Enter a new function scope
> > - PushFunctionScope();
> > + // If we are instantiating a generic lambda call operator, push
> > + // a LambdaScopeInfo onto the function stack. But use the information
> > + // that's already been calculated (ActOnLambdaExpr) when analyzing the
> > + // template version, to prime the current LambdaScopeInfo.
> > + if (getLangOpts().CPlusPlus1y
> > + &&
> isGenericLambdaCallOperatorSpecialization(D)) {
> > + CXXMethodDecl *CallOperator = cast<CXXMethodDecl>(D);
> > + CXXRecordDecl *LambdaClass = CallOperator->getParent();
> > + LambdaExpr *LE = LambdaClass->getLambdaExpr();
> > + assert(LE &&
> > + "No LambdaExpr of closure class when instantiating a generic
> lambda!");
> > + assert(ActiveTemplateInstantiations.size() &&
> > + "There should be an active template instantiation on the stack "
> > + "when instantiating a generic lambda!");
> > + PushLambdaScope();
> > + LambdaScopeInfo *LSI = getCurLambda();
> > + LSI->CallOperator = CallOperator;
> > + LSI->Lambda = LambdaClass;
> > + LSI->ReturnType = CallOperator->getResultType();
> > +
> > + if (LE->getCaptureDefault() == LCD_None)
> > + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None;
> > + else if (LE->getCaptureDefault() == LCD_ByCopy)
> > + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval;
> > + else if (LE->getCaptureDefault() == LCD_ByRef)
> > + LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref;
> > +
> > + LSI->IntroducerRange = LE->getIntroducerRange();
> > + }
> > + else
> > + // Enter a new function scope
> > + PushFunctionScope();
> >
> > // See if this is a redefinition.
> > if (!FD->isLateTemplateParsed())
> >
> > Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed Aug 21 20:49:11 2013
> > @@ -32,6 +32,7 @@
> > #include "clang/Sema/CXXFieldCollector.h"
> > #include "clang/Sema/DeclSpec.h"
> > #include "clang/Sema/Initialization.h"
> > +#include "clang/Sema/SemaLambda.h"
> > #include "clang/Sema/Lookup.h"
> > #include "clang/Sema/ParsedTemplate.h"
> > #include "clang/Sema/Scope.h"
> > @@ -10015,29 +10016,27 @@ void Sema::DefineImplicitLambdaToFunctio
> > SourceLocation CurrentLocation,
> > CXXConversionDecl *Conv)
> > {
> > - CXXRecordDecl *Lambda = Conv->getParent();
> > + CXXRecordDecl *LambdaClass = Conv->getParent();
> >
> > // Make sure that the lambda call operator is marked used.
> > - markLambdaCallOperatorUsed(*this, Lambda);
> > + markLambdaCallOperatorUsed(*this, LambdaClass);
> >
> > Conv->setUsed();
> >
> > SynthesizedFunctionScope Scope(*this, Conv);
> > DiagnosticErrorTrap Trap(Diags);
> >
> > - // Return the address of the __invoke function.
> > - DeclarationName InvokeName = &Context.Idents.get("__invoke");
> > - CXXMethodDecl *Invoke
> > - = cast<CXXMethodDecl>(Lambda->lookup(InvokeName).front());
> > + CXXMethodDecl *Invoke = LambdaClass->getLambdaStaticInvoker();
> > +
> > Expr *FunctionRef = BuildDeclRefExpr(Invoke, Invoke->getType(),
> > VK_LValue,
> Conv->getLocation()).take();
> > - assert(FunctionRef && "Can't refer to __invoke function?");
> > + assert(FunctionRef && "Can't refer to lambda static invoker
> function?");
> > Stmt *Return = ActOnReturnStmt(Conv->getLocation(),
> FunctionRef).take();
> > Conv->setBody(new (Context) CompoundStmt(Context, Return,
> > Conv->getLocation(),
> > Conv->getLocation()));
> >
> > - // Fill in the __invoke function with a dummy implementation. IR
> generation
> > + // Fill in the invoke function with a dummy implementation. IR
> generation
> > // will fill in the actual details.
> > Invoke->setUsed();
> > Invoke->setReferenced();
> >
> > Modified: cfe/trunk/lib/Sema/SemaLambda.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLambda.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaLambda.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaLambda.cpp Wed Aug 21 20:49:11 2013
> > @@ -14,6 +14,7 @@
> > #include "clang/AST/ExprCXX.h"
> > #include "clang/Lex/Preprocessor.h"
> > #include "clang/Sema/Initialization.h"
> > +#include "clang/Sema/SemaLambda.h"
> > #include "clang/Sema/Lookup.h"
> > #include "clang/Sema/Scope.h"
> > #include "clang/Sema/ScopeInfo.h"
> > @@ -120,11 +121,69 @@ Sema::getCurrentMangleNumberContext(cons
> > llvm_unreachable("unexpected context");
> > }
> >
> > +
> > +ParmVarDecl *Sema::ActOnLambdaAutoParameter(ParmVarDecl *PVD) {
> > + LambdaScopeInfo *LSI = getCurLambda();
> > + assert(LSI && "No LambdaScopeInfo on the stack!");
> > + const unsigned TemplateParameterDepth =
> LSI->AutoTemplateParameterDepth;
> > + const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
> > + // Invent a template type parameter corresponding to the auto
> > + // containing parameter.
> > + TemplateTypeParmDecl *TemplateParam =
> > + TemplateTypeParmDecl::Create(Context,
> > + // Temporarily add to the TranslationUnit DeclContext. When the
> > + // associated TemplateParameterList is attached to a template
> > + // declaration (such as FunctionTemplateDecl), the DeclContext
> > + // for each template parameter gets updated appropriately via
> > + // a call to AdoptTemplateParameterList.
> > + Context.getTranslationUnitDecl(),
> > + SourceLocation(),
> > + PVD->getLocation(),
> > + TemplateParameterDepth,
> > + AutoParameterPosition, // our template param index
> > + /* Identifier*/ 0, false, PVD->isParameterPack());
> > + LSI->AutoTemplateParams.push_back(TemplateParam);
> > + QualType AutoTy = PVD->getType();
> > + // Now replace the 'auto' in the function parameter with this invented
> > + // template type parameter.
> > + QualType TemplParamType = QualType(TemplateParam->getTypeForDecl(),
> 0);
> > +
> > + TypeSourceInfo *AutoTSI = PVD->getTypeSourceInfo();
> > + TypeSourceInfo *NewTSI = SubstAutoTypeSourceInfo(AutoTSI,
> TemplParamType);
> > + PVD->setType(NewTSI->getType());
> > + PVD->setTypeSourceInfo(NewTSI);
> > + return PVD;
> > +}
> > +
> > +
> > +static inline TemplateParameterList *
> > + getGenericLambdaTemplateParameterList(LambdaScopeInfo
> *LSI,
> > + Sema &SemaRef) {
> > + if (LSI->GLTemplateParameterList)
> > + return LSI->GLTemplateParameterList;
> > + else if (LSI->AutoTemplateParams.size()) {
> > + SourceRange IntroRange = LSI->IntroducerRange;
> > + SourceLocation LAngleLoc = IntroRange.getBegin();
> > + SourceLocation RAngleLoc = IntroRange.getEnd();
> > + LSI->GLTemplateParameterList =
> > + TemplateParameterList::Create(SemaRef.Context,
> > + /* Template kw loc */ SourceLocation(),
> > + LAngleLoc,
> > + (NamedDecl**)LSI->AutoTemplateParams.data(),
> > + LSI->AutoTemplateParams.size(), RAngleLoc);
> > + }
> > + return LSI->GLTemplateParameterList;
> > +}
> > +
> > +
> > +
> > CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class,
> > SourceRange IntroducerRange,
> > TypeSourceInfo *MethodType,
> > SourceLocation EndLoc,
> > ArrayRef<ParmVarDecl *> Params) {
> > + TemplateParameterList *TemplateParams =
> > + getGenericLambdaTemplateParameterList(getCurLambda(),
> *this);
> > // C++11 [expr.prim.lambda]p5:
> > // The closure type for a lambda-expression has a public inline
> function
> > // call operator (13.5.4) whose parameters and return type are
> described by
> > @@ -152,6 +211,17 @@ CXXMethodDecl *Sema::startLambdaDefiniti
> > // Temporarily set the lexical declaration context to the current
> > // context, so that the Scope stack matches the lexical nesting.
> > Method->setLexicalDeclContext(CurContext);
> > + // Create a function template if we have a template parameter list
> > + FunctionTemplateDecl *const TemplateMethod = TemplateParams ?
> > + FunctionTemplateDecl::Create(Context, Class,
> > + Method->getLocation(),
> MethodName,
> > + TemplateParams,
> > + Method) : 0;
> > + if (TemplateMethod) {
> > + TemplateMethod->setLexicalDeclContext(CurContext);
> > + TemplateMethod->setAccess(AS_public);
> > + Method->setDescribedFunctionTemplate(TemplateMethod);
> > + }
> >
> > // Add parameters.
> > if (!Params.empty()) {
> > @@ -177,15 +247,16 @@ CXXMethodDecl *Sema::startLambdaDefiniti
> > return Method;
> > }
> >
> > -LambdaScopeInfo *Sema::enterLambdaScope(CXXMethodDecl *CallOperator,
> > +void Sema::buildLambdaScope(LambdaScopeInfo *LSI,
> > + CXXMethodDecl *CallOperator,
> > SourceRange IntroducerRange,
> > LambdaCaptureDefault
> CaptureDefault,
> > SourceLocation CaptureDefaultLoc,
> > bool ExplicitParams,
> > bool ExplicitResultType,
> > bool Mutable) {
> > - PushLambdaScope(CallOperator->getParent(), CallOperator);
> > - LambdaScopeInfo *LSI = getCurLambda();
> > + LSI->CallOperator = CallOperator;
> > + LSI->Lambda = CallOperator->getParent();
> > if (CaptureDefault == LCD_ByCopy)
> > LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval;
> > else if (CaptureDefault == LCD_ByRef)
> > @@ -208,8 +279,6 @@ LambdaScopeInfo *Sema::enterLambdaScope(
> > } else {
> > LSI->HasImplicitReturnType = true;
> > }
> > -
> > - return LSI;
> > }
> >
> > void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
> > @@ -358,7 +427,7 @@ static void adjustBlockReturnsToEnum(Sem
> > }
> >
> > void Sema::deduceClosureReturnType(CapturingScopeInfo &CSI) {
> > - assert(CSI.HasImplicitReturnType);
> > + assert(CSI.HasImplicitReturnType ||
> CSI.ReturnType->isUndeducedType());
> >
> > // C++ Core Issue #975, proposed resolution:
> > // If a lambda-expression does not include a trailing-return-type,
> > @@ -392,7 +461,7 @@ void Sema::deduceClosureReturnType(Captu
> > // Second case: at least one return statement has dependent type.
> > // Delay type checking until instantiation.
> > assert(!CSI.ReturnType.isNull() && "We should have a tentative return
> type.");
> > - if (CSI.ReturnType->isDependentType())
> > + if (CSI.ReturnType->isDependentType() ||
> CSI.ReturnType->isUndeducedType())
> > return;
> >
> > // Try to apply the enum-fuzz rule.
> > @@ -519,15 +588,25 @@ FieldDecl *Sema::checkInitCapture(Source
> > }
> >
> > void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro,
> > - Declarator &ParamInfo,
> > - Scope *CurScope) {
> > + Declarator &ParamInfo, Scope *CurScope) {
> > // Determine if we're within a context where we know that the lambda
> will
> > // be dependent, because there are template parameters in scope.
> > bool KnownDependent = false;
> > - if (Scope *TmplScope = CurScope->getTemplateParamParent())
> > - if (!TmplScope->decl_empty())
> > + LambdaScopeInfo *const LSI = getCurLambda();
> > + assert(LSI && "LambdaScopeInfo should be on stack!");
> > + TemplateParameterList *TemplateParams =
> > + getGenericLambdaTemplateParameterList(LSI, *this);
> > +
> > + if (Scope *TmplScope = CurScope->getTemplateParamParent()) {
> > + // Since we have our own TemplateParams, so check if an outer scope
> > + // has template params, only then are we in a dependent scope.
> > + if (TemplateParams) {
> > + TmplScope = TmplScope->getParent();
> > + TmplScope = TmplScope ? TmplScope->getTemplateParamParent() : 0;
> > + }
> > + if (TmplScope && !TmplScope->decl_empty())
> > KnownDependent = true;
> > -
> > + }
> > // Determine the signature of the call operator.
> > TypeSourceInfo *MethodTyInfo;
> > bool ExplicitParams = true;
> > @@ -542,7 +621,11 @@ void Sema::ActOnStartOfLambdaDefinition(
> > FunctionProtoType::ExtProtoInfo EPI;
> > EPI.HasTrailingReturn = true;
> > EPI.TypeQuals |= DeclSpec::TQ_const;
> > - QualType MethodTy = Context.getFunctionType(Context.DependentTy,
> None,
> > + // For C++1y, use the new return type deduction machinery, by
> imaginging
> > + // 'auto' if no trailing return type.
> > + QualType DefaultTypeForNoTrailingReturn = getLangOpts().CPlusPlus1y
> ?
> > + Context.getAutoDeductType() : Context.DependentTy;
> > + QualType MethodTy =
> Context.getFunctionType(DefaultTypeForNoTrailingReturn, None,
> > EPI);
> > MethodTyInfo = Context.getTrivialTypeSourceInfo(MethodTy);
> > ExplicitParams = false;
> > @@ -560,14 +643,15 @@ void Sema::ActOnStartOfLambdaDefinition(
> > if (!FTI.hasMutableQualifier())
> > FTI.TypeQuals |= DeclSpec::TQ_const;
> >
> > + ExplicitResultType = FTI.hasTrailingReturnType();
> > + // In C++11 if there is no explicit return type, the return type is
> > + // artificially set to DependentTy, whereas in C++1y it is set to
> AutoTy
> > + // (through ConvertDeclSpecToType) which allows us to support both
> > + // C++11 and C++1y return type deduction semantics.
> > MethodTyInfo = GetTypeForDeclarator(ParamInfo, CurScope);
> > assert(MethodTyInfo && "no type from lambda-declarator");
> > EndLoc = ParamInfo.getSourceRange().getEnd();
> >
> > - ExplicitResultType
> > - = MethodTyInfo->getType()->getAs<FunctionType>()->getResultType()
> > - !=
> Context.DependentTy;
> > -
> > if (FTI.NumArgs == 1 && !FTI.isVariadic && FTI.ArgInfo[0].Ident == 0
> &&
> >
> cast<ParmVarDecl>(FTI.ArgInfo[0].Param)->getType()->isVoidType()) {
> > // Empty arg list, don't push any params.
> > @@ -588,7 +672,6 @@ void Sema::ActOnStartOfLambdaDefinition(
> >
> > CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range,
> > MethodTyInfo, EndLoc,
> Params);
> > -
> > if (ExplicitParams)
> > CheckCXXDefaultArguments(Method);
> >
> > @@ -598,9 +681,8 @@ void Sema::ActOnStartOfLambdaDefinition(
> > // Introduce the function call operator as the current declaration
> context.
> > PushDeclContext(CurScope, Method);
> >
> > - // Introduce the lambda scope.
> > - LambdaScopeInfo *LSI
> > - = enterLambdaScope(Method,
> > + // Build the lambda scope.
> > + buildLambdaScope(LSI, Method,
> > Intro.Range,
> > Intro.Default, Intro.DefaultLoc,
> > ExplicitParams,
> > @@ -812,6 +894,8 @@ static void addFunctionPointerConversion
> > SourceRange IntroducerRange,
> > CXXRecordDecl *Class,
> > CXXMethodDecl *CallOperator) {
> > + // FIXME: The conversion operator needs to be fixed for generic
> lambdas.
> > + if (Class->isGenericLambda()) return;
> > // Add the conversion to function pointer.
> > const FunctionProtoType *Proto
> > = CallOperator->getType()->getAs<FunctionProtoType>();
> > @@ -849,10 +933,9 @@ static void addFunctionPointerConversion
> > Conversion->setAccess(AS_public);
> > Conversion->setImplicit(true);
> > Class->addDecl(Conversion);
> > -
> > - // Add a non-static member function "__invoke" that will be the
> result of
> > - // the conversion.
> > - Name = &S.Context.Idents.get("__invoke");
> > + // Add a non-static member function that will be the result of
> > + // the conversion with a certain unique ID.
> > + Name = &S.Context.Idents.get(getLambdaStaticInvokerName());
> > CXXMethodDecl *Invoke
> > = CXXMethodDecl::Create(S.Context, Class, Loc,
> > DeclarationNameInfo(Name, Loc), FunctionTy,
> > @@ -1000,8 +1083,11 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
> > // If a lambda-expression does not include a
> > // trailing-return-type, it is as if the trailing-return-type
> > // denotes the following type:
> > + // Skip for C++1y return type deduction semantics which uses
> > + // different machinery currently.
> > + // FIXME: Refactor and Merge the return type deduction machinery.
> > // FIXME: Assumes current resolution to core issue 975.
> > - if (LSI->HasImplicitReturnType) {
> > + if (LSI->HasImplicitReturnType && !getLangOpts().CPlusPlus1y) {
> > deduceClosureReturnType(*LSI);
> >
> > // - if there are no return statements in the
> > @@ -1019,13 +1105,18 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
> > LSI->ReturnType, Proto->getArgTypes(),
> Proto->getExtProtoInfo());
> > CallOperator->setType(FunctionTy);
> > }
> > -
> > // C++ [expr.prim.lambda]p7:
> > // The lambda-expression's compound-statement yields the
> > // function-body (8.4) of the function call operator [...].
> > ActOnFinishFunctionBody(CallOperator, Body, IsInstantiation);
> > CallOperator->setLexicalDeclContext(Class);
> > - Class->addDecl(CallOperator);
> > + Decl *TemplateOrNonTemplateCallOperatorDecl =
> > + !CallOperator->getDescribedFunctionTemplate() ?
> cast<Decl>(CallOperator)
> > + : CallOperator->getDescribedFunctionTemplate();
> > +
> > + TemplateOrNonTemplateCallOperatorDecl->setLexicalDeclContext(Class);
> > + Class->addDecl(TemplateOrNonTemplateCallOperatorDecl);
> > +
> > PopExpressionEvaluationContext();
> >
> > // C++11 [expr.prim.lambda]p6:
> > @@ -1065,7 +1156,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
> > CaptureInits, ArrayIndexVars,
> > ArrayIndexStarts,
> Body->getLocEnd(),
> >
> ContainsUnexpandedParameterPack);
> > -
> > + Class->setLambdaExpr(Lambda);
> > // C++11 [expr.prim.lambda]p2:
> > // A lambda-expression shall not appear in an unevaluated operand
> > // (Clause 5).
> > @@ -1085,7 +1176,15 @@ ExprResult Sema::ActOnLambdaExpr(SourceL
> > break;
> > }
> > }
> > -
> > + // TODO: Implement capturing.
> > + if (Lambda->isGenericLambda()) {
> > + if (Lambda->getCaptureDefault() != LCD_None) {
> > + Diag(Lambda->getIntroducerRange().getBegin(),
> > + diag::err_glambda_not_fully_implemented)
> > + << " capturing not implemented yet";
> > + return ExprError();
> > + }
> > + }
> > return MaybeBindToTemporary(Lambda);
> > }
> >
> >
> > Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Aug 21 20:49:11 2013
> > @@ -8670,6 +8670,10 @@ void DiagnoseBadDeduction(Sema &S, Decl
> > }
> > }
> > }
> > + // FIXME: For generic lambda parameters, check if the function is a
> lambda
> > + // call operator, and if so, emit a prettier and more informative
> > + // diagnostic that mentions 'auto' and lambda in addition to
> > + // (or instead of?) the canonical template type parameters.
> > S.Diag(Templated->getLocation(),
> > diag::note_ovl_candidate_non_deduced_mismatch)
> > << FirstTA << SecondTA;
> >
> > Modified: cfe/trunk/lib/Sema/SemaStmt.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaStmt.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaStmt.cpp Wed Aug 21 20:49:11 2013
> > @@ -2487,12 +2487,31 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > // [expr.prim.lambda]p4 in C++11; block literals follow the same rules.
> > CapturingScopeInfo *CurCap =
> cast<CapturingScopeInfo>(getCurFunction());
> > QualType FnRetType = CurCap->ReturnType;
> > -
> > - // For blocks/lambdas with implicit return types, we check each return
> > - // statement individually, and deduce the common return type when the
> block
> > - // or lambda is completed.
> > - if (CurCap->HasImplicitReturnType) {
> > - // FIXME: Fold this into the 'auto' codepath below.
> > + LambdaScopeInfo *const LambdaSI = getCurLambda();
> > + // In C++1y, an implicit return type behaves as if 'auto' was
> > + // the return type.
> > + if (FnRetType.isNull() && getLangOpts().CPlusPlus1y) {
> > + if (LambdaSI) {
> > + FunctionDecl *CallOp = LambdaSI->CallOperator;
> > + FnRetType = CallOp->getResultType();
> > + assert(FnRetType->getContainedAutoType());
> > + }
> > + }
> > +
> > + // For blocks/lambdas with implicit return types in C++11, we check
> each
> > + // return statement individually, and deduce the common return type
> when
> > + // the block or lambda is completed. In C++1y, the return type
> deduction
> > + // of a lambda is specified in terms of auto.
> > + // Notably, in C++11, we take the type of the expression after decay
> and
> > + // lvalue-to-rvalue conversion, so a class type can be cv-qualified.
> > + // In C++1y, we perform template argument deduction as if the return
> > + // type were 'auto', so an implicit return type is never cv-qualified.
> > + // i.e if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())
> > + // FnRetType = FnRetType.getUnqualifiedType();
> > + // Return type deduction is unchanged for blocks in C++1y.
> > + // FIXME: Fold this into the 'auto' codepath below.
> > + if (CurCap->HasImplicitReturnType &&
> > + (!LambdaSI || !getLangOpts().CPlusPlus1y)) {
> > if (RetValExp && !isa<InitListExpr>(RetValExp)) {
> > ExprResult Result =
> DefaultFunctionArrayLvalueConversion(RetValExp);
> > if (Result.isInvalid())
> > @@ -2500,13 +2519,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > RetValExp = Result.take();
> >
> > if (!CurContext->isDependentContext()) {
> > - FnRetType = RetValExp->getType();
> > - // In C++11, we take the type of the expression after decay and
> > - // lvalue-to-rvalue conversion, so a class type can be
> cv-qualified.
> > - // In C++1y, we perform template argument deduction as if the
> return
> > - // type were 'auto', so an implicit return type is never
> cv-qualified.
> > - if (getLangOpts().CPlusPlus1y && FnRetType.hasQualifiers())
> > - FnRetType = FnRetType.getUnqualifiedType();
> > + FnRetType = RetValExp->getType();
> > } else
> > FnRetType = CurCap->ReturnType = Context.DependentTy;
> > } else {
> > @@ -2517,7 +2530,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > Diag(ReturnLoc, diag::err_lambda_return_init_list)
> > << RetValExp->getSourceRange();
> > }
> > -
> > FnRetType = Context.VoidTy;
> > }
> >
> > @@ -2526,7 +2538,8 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > if (CurCap->ReturnType.isNull())
> > CurCap->ReturnType = FnRetType;
> > } else if (AutoType *AT =
> > - FnRetType.isNull() ? 0 :
> FnRetType->getContainedAutoType()) {
> > + (FnRetType.isNull() || !LambdaSI) ? 0
> > + : FnRetType->getContainedAutoType()) {
> > // In C++1y, the return type may involve 'auto'.
> > FunctionDecl *FD = cast<LambdaScopeInfo>(CurCap)->CallOperator;
> > if (CurContext->isDependentContext()) {
> > @@ -2534,7 +2547,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > // Return type deduction [...] occurs when the definition is
> > // instantiated even if the function body contains a return
> > // statement with a non-type-dependent operand.
> > - CurCap->ReturnType = FnRetType = Context.DependentTy;
> > + CurCap->ReturnType = FnRetType;
> > } else if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc,
> RetValExp, AT)) {
> > FD->setInvalidDecl();
> > return StmtError();
> > @@ -2564,7 +2577,7 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> > // pickier with blocks than for normal functions because we don't have
> GCC
> > // compatibility to worry about here.
> > const VarDecl *NRVOCandidate = 0;
> > - if (FnRetType->isDependentType()) {
> > + if (FnRetType->isDependentType() || FnRetType->isUndeducedType()) {
> > // Delay processing for now. TODO: there are lots of dependent
> > // types we can conclusively prove aren't void.
> > } else if (FnRetType->isVoidType()) {
> > @@ -2624,7 +2637,6 @@ Sema::ActOnCapScopeReturnStmt(SourceLoca
> >
> > return Owned(Result);
> > }
> > -
> > /// Deduce the return type for a function from a returned expression, per
> > /// C++1y [dcl.spec.auto]p6.
> > bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
> > @@ -2634,7 +2646,6 @@ bool Sema::DeduceFunctionTypeFromReturnE
> > TypeLoc OrigResultType = FD->getTypeSourceInfo()->getTypeLoc().
> > IgnoreParens().castAs<FunctionProtoTypeLoc>().getResultLoc();
> > QualType Deduced;
> > -
> > if (RetExpr && isa<InitListExpr>(RetExpr)) {
> > // If the deduction is for a return statement and the initializer is
> > // a braced-init-list, the program is ill-formed.
> > @@ -2692,9 +2703,18 @@ bool Sema::DeduceFunctionTypeFromReturnE
> > AutoType *NewAT = Deduced->getContainedAutoType();
> > if (!FD->isDependentContext() &&
> > !Context.hasSameType(AT->getDeducedType(),
> NewAT->getDeducedType())) {
> > - Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
> > - << (AT->isDecltypeAuto() ? 1 : 0)
> > - << NewAT->getDeducedType() << AT->getDeducedType();
> > + LambdaScopeInfo *const LambdaSI = getCurLambda();
> > + if (LambdaSI && LambdaSI->HasImplicitReturnType) {
> > + Diag(ReturnLoc,
> > + diag::err_typecheck_missing_return_type_incompatible)
> > + << NewAT->getDeducedType() << AT->getDeducedType()
> > + << true /*IsLambda*/;
> > + }
> > + else {
> > + Diag(ReturnLoc, diag::err_auto_fn_different_deductions)
> > + << (AT->isDecltypeAuto() ? 1 : 0)
> > + << NewAT->getDeducedType() << AT->getDeducedType();
> > + }
> > return true;
> > }
> > } else if (!FD->isInvalidDecl()) {
> > @@ -2710,10 +2730,8 @@ Sema::ActOnReturnStmt(SourceLocation Ret
> > // Check for unexpanded parameter packs.
> > if (RetValExp && DiagnoseUnexpandedParameterPack(RetValExp))
> > return StmtError();
> > -
> > if (isa<CapturingScopeInfo>(getCurFunction()))
> > return ActOnCapScopeReturnStmt(ReturnLoc, RetValExp);
> > -
> > QualType FnRetType;
> > QualType RelatedRetType;
> > if (const FunctionDecl *FD = getCurFunctionDecl()) {
> >
> > Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Wed Aug 21 20:49:11 2013
> > @@ -3766,7 +3766,8 @@ namespace {
> > QualType Result =
> > SemaRef.Context.getAutoType(Dependent ? QualType() :
> Replacement,
> > TL.getTypePtr()->isDecltypeAuto(),
> > - Dependent);
> > + Dependent, TL.getTypePtr()->
> > +
> containsUnexpandedParameterPack());
> > AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result);
> > NewTL.setNameLoc(TL.getNameLoc());
> > return Result;
> > @@ -3907,8 +3908,16 @@ Sema::DeduceAutoType(TypeLoc Type, Expr
> > return DAR_Succeeded;
> > }
> >
> > -QualType Sema::SubstAutoType(QualType Type, QualType Deduced) {
> > - return SubstituteAutoTransform(*this, Deduced).TransformType(Type);
> > +QualType Sema::SubstAutoType(QualType TypeWithAuto,
> > + QualType TypeToReplaceAuto) {
> > + return SubstituteAutoTransform(*this, TypeToReplaceAuto).
> > + TransformType(TypeWithAuto);
> > +}
> > +
> > +TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo
> *TypeWithAuto,
> > + QualType TypeToReplaceAuto) {
> > + return SubstituteAutoTransform(*this, TypeToReplaceAuto).
> > + TransformType(TypeWithAuto);
> > }
> >
> > void Sema::DiagnoseAutoDeductionFailure(VarDecl *VDecl, Expr *Init) {
> >
> > Modified: cfe/trunk/lib/Sema/SemaType.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/SemaType.cpp (original)
> > +++ cfe/trunk/lib/Sema/SemaType.cpp Wed Aug 21 20:49:11 2013
> > @@ -781,7 +781,13 @@ static QualType ConvertDeclSpecToType(Ty
> > // specified with a trailing return type or inferred.
> > if (declarator.getContext() == Declarator::LambdaExprContext ||
> > isOmittedBlockReturnType(declarator)) {
> > - Result = Context.DependentTy;
> > + // In C++1y (n3690 CD), 5.1.2 [expr.prim.lambda]/4 : The lambda
> return
> > + // type is auto, which is replaced by the trailing-return-type if
> > + // provided and/or deduced from return statements as described
> > + // in 7.1.6.4.
> > + Result = S.getLangOpts().CPlusPlus1y &&
> > + declarator.getContext() == Declarator::LambdaExprContext
> > + ? Context.getAutoDeductType() : Context.DependentTy;
> > break;
> > }
> >
> > @@ -1006,11 +1012,17 @@ static QualType ConvertDeclSpecToType(Ty
> >
> > case DeclSpec::TST_auto:
> > // TypeQuals handled by caller.
> > - Result = Context.getAutoType(QualType(), /*decltype(auto)*/false);
> > + Result = Context.getAutoType(QualType(),
> > + /*decltype(auto)*/false,
> > + /*IsDependent*/ false,
> > + /*IsParameterPack*/
> declarator.hasEllipsis());
> > break;
> >
> > case DeclSpec::TST_decltype_auto:
> > - Result = Context.getAutoType(QualType(), /*decltype(auto)*/true);
> > + Result = Context.getAutoType(QualType(),
> > + /*decltype(auto)*/true,
> > + /*IsDependent*/ false,
> > + /*IsParameterPack*/ false);
> > break;
> >
> > case DeclSpec::TST_unknown_anytype:
> > @@ -1557,7 +1569,7 @@ QualType Sema::BuildArrayType(QualType T
> > ASM = ArrayType::Normal;
> > }
> > } else if (!T->isDependentType() && !T->isVariablyModifiedType() &&
> > - !T->isIncompleteType()) {
> > + !T->isIncompleteType() && !T->isUndeducedType()) {
> > // Is the array too large?
> > unsigned ActiveSizeBits
> > = ConstantArrayType::getNumAddressingBits(Context, T, ConstVal);
> > @@ -2097,6 +2109,7 @@ static QualType GetDeclSpecTypeForDeclar
> > // In C++11, a function declarator using 'auto' must have a trailing
> return
> > // type (this is checked later) and we can skip this. In other
> languages
> > // using auto, we need to check regardless.
> > + // Generic Lambdas (C++14) allow 'auto' in their parameters.
> > if (ContainsPlaceholderType &&
> > (!SemaRef.getLangOpts().CPlusPlus11 || !D.isFunctionDeclarator()))
> {
> > int Error = -1;
> > @@ -2109,7 +2122,12 @@ static QualType GetDeclSpecTypeForDeclar
> > case Declarator::ObjCParameterContext:
> > case Declarator::ObjCResultContext:
> > case Declarator::PrototypeContext:
> > - Error = 0; // Function prototype
> > + Error = 0;
> > + break;
> > + case Declarator::LambdaExprParameterContext:
> > + if (!(SemaRef.getLangOpts().CPlusPlus1y
> > + && D.getDeclSpec().getTypeSpecType() ==
> DeclSpec::TST_auto))
> > + Error = 0;
> > break;
> > case Declarator::MemberContext:
> > if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)
> > @@ -2189,8 +2207,13 @@ static QualType GetDeclSpecTypeForDeclar
> > AutoRange = D.getName().getSourceRange();
> >
> > if (Error != -1) {
> > + if (D.getDeclSpec().getTypeSpecType() ==
> DeclSpec::TST_decltype_auto) {
> > + SemaRef.Diag(AutoRange.getBegin(),
> > +
> diag::err_decltype_auto_function_declarator_not_declaration);
> > + } else {
> > SemaRef.Diag(AutoRange.getBegin(), diag::err_auto_not_allowed)
> > << Error << AutoRange;
> > + }
> > T = SemaRef.Context.IntTy;
> > D.setInvalidType(true);
> > } else
> > @@ -2240,6 +2263,7 @@ static QualType GetDeclSpecTypeForDeclar
> > D.setInvalidType(true);
> > break;
> > case Declarator::PrototypeContext:
> > + case Declarator::LambdaExprParameterContext:
> > case Declarator::ObjCParameterContext:
> > case Declarator::ObjCResultContext:
> > case Declarator::KNRTypeListContext:
> > @@ -2613,8 +2637,11 @@ static TypeSourceInfo *GetFullTypeForDec
> > }
> > }
> > }
> > -
> > - if (const AutoType *AT = T->getContainedAutoType()) {
> > + const AutoType *AT = T->getContainedAutoType();
> > + // Allow arrays of auto if we are a generic lambda parameter.
> > + // i.e. [](auto (&array)[5]) { return array[0]; }; OK
> > + if (AT && !(S.getLangOpts().CPlusPlus1y &&
> > + D.getContext() ==
> Declarator::LambdaExprParameterContext)) {
> > // We've already diagnosed this for decltype(auto).
> > if (!AT->isDecltypeAuto())
> > S.Diag(DeclType.Loc, diag::err_illegal_decl_array_of_auto)
> > @@ -3110,6 +3137,7 @@ static TypeSourceInfo *GetFullTypeForDec
> > // is a parameter pack (14.5.3). [...]
> > switch (D.getContext()) {
> > case Declarator::PrototypeContext:
> > + case Declarator::LambdaExprParameterContext:
> > // C++0x [dcl.fct]p13:
> > // [...] When it is part of a parameter-declaration-clause, the
> > // parameter pack is a function parameter pack (14.5.3). The
> type T
> > @@ -3128,7 +3156,6 @@ static TypeSourceInfo *GetFullTypeForDec
> > T = Context.getPackExpansionType(T, None);
> > }
> > break;
> > -
> > case Declarator::TemplateParamContext:
> > // C++0x [temp.param]p15:
> > // If a template-parameter is a [...] is a parameter-declaration
> that
> >
> > Modified: cfe/trunk/lib/Sema/TreeTransform.h
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/TreeTransform.h?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Sema/TreeTransform.h (original)
> > +++ cfe/trunk/lib/Sema/TreeTransform.h Wed Aug 21 20:49:11 2013
> > @@ -782,7 +782,10 @@ public:
> > // Note, IsDependent is always false here: we implicitly convert an
> 'auto'
> > // which has been deduced to a dependent type into an undeduced
> 'auto', so
> > // that we'll retry deduction after the transformation.
> > - return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto);
> > + // FIXME: Can we assume the same about IsParameterPack?
> > + return SemaRef.Context.getAutoType(Deduced, IsDecltypeAuto,
> > + /*IsDependent*/ false,
> > + /*IsParameterPack*/ false);
> > }
> >
> > /// \brief Build a new template specialization type.
> > @@ -3494,7 +3497,9 @@ TreeTransform<Derived>::TransformQualifi
> > Qs.removeObjCLifetime();
> > Deduced =
> SemaRef.Context.getQualifiedType(Deduced.getUnqualifiedType(),
> > Qs);
> > - Result = SemaRef.Context.getAutoType(Deduced,
> AutoTy->isDecltypeAuto());
> > + Result = SemaRef.Context.getAutoType(Deduced,
> AutoTy->isDecltypeAuto(),
> > + AutoTy->isDependentType(),
> > +
> AutoTy->containsUnexpandedParameterPack());
> > TLB.TypeWasModifiedSafely(Result);
> > } else {
> > // Otherwise, complain about the addition of a qualifier to an
> > @@ -8193,6 +8198,14 @@ TreeTransform<Derived>::TransformCXXTemp
> > template<typename Derived>
> > ExprResult
> > TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
> > +
> > + // FIXME: Implement nested generic lambda transformations.
> > + if (E->isGenericLambda()) {
> > + getSema().Diag(E->getIntroducerRange().getBegin(),
> > + diag::err_glambda_not_fully_implemented)
> > + << " nested lambdas not implemented yet";
> > + return ExprError();
> > + }
> > // Transform the type of the lambda parameters and start the
> definition of
> > // the lambda itself.
> > TypeSourceInfo *MethodTy
> > @@ -8215,7 +8228,10 @@ TreeTransform<Derived>::TransformLambdaE
> > E->getCallOperator()->param_size(),
> > 0, ParamTypes, &Params))
> > return ExprError();
> > -
> > + getSema().PushLambdaScope();
> > + LambdaScopeInfo *LSI = getSema().getCurLambda();
> > + // TODO: Fix for nested lambdas
> > + LSI->GLTemplateParameterList = 0;
> > // Build the call operator.
> > CXXMethodDecl *CallOperator
> > = getSema().startLambdaDefinition(Class, E->getIntroducerRange(),
> > @@ -8250,9 +8266,9 @@ TreeTransform<Derived>::TransformLambdaS
> > // Introduce the context of the call operator.
> > Sema::ContextRAII SavedContext(getSema(), CallOperator);
> >
> > + LambdaScopeInfo *const LSI = getSema().getCurLambda();
> > // Enter the scope of the lambda.
> > - sema::LambdaScopeInfo *LSI
> > - = getSema().enterLambdaScope(CallOperator, E->getIntroducerRange(),
> > + getSema().buildLambdaScope(LSI, CallOperator, E->getIntroducerRange(),
> > E->getCaptureDefault(),
> > E->getCaptureDefaultLoc(),
> > E->hasExplicitParameters(),
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReader.cpp Wed Aug 21 20:49:11 2013
> > @@ -4740,7 +4740,9 @@ QualType ASTReader::readTypeRecord(unsig
> > QualType Deduced = readType(*Loc.F, Record, Idx);
> > bool IsDecltypeAuto = Record[Idx++];
> > bool IsDependent = Deduced.isNull() ? Record[Idx++] : false;
> > - return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent);
> > + bool IsParameterPack = Record[Idx++];
> > + return Context.getAutoType(Deduced, IsDecltypeAuto, IsDependent,
> > + IsParameterPack);
> > }
> >
> > case TYPE_RECORD: {
> >
> > Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Wed Aug 21 20:49:11
> 2013
> > @@ -1201,6 +1201,7 @@ void ASTDeclReader::ReadCXXDefinitionDat
> > =
> (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures);
> > Capture *ToCapture = Lambda.Captures;
> > Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx);
> > + Lambda.TheLambdaExpr = cast<LambdaExpr>(Reader.ReadExpr(F));
> > for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
> > SourceLocation Loc = ReadSourceLocation(Record, Idx);
> > bool IsImplicit = Record[Idx++];
> >
> > Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
> > +++ cfe/trunk/lib/Serialization/ASTWriter.cpp Wed Aug 21 20:49:11 2013
> > @@ -253,6 +253,7 @@ void ASTTypeWriter::VisitAutoType(const
> > Record.push_back(T->isDecltypeAuto());
> > if (T->getDeducedType().isNull())
> > Record.push_back(T->isDependentType());
> > + Record.push_back(T->containsUnexpandedParameterPack());
> > Code = TYPE_AUTO;
> > }
> >
> > @@ -5136,6 +5137,7 @@ void ASTWriter::AddCXXDefinitionData(con
> > Record.push_back(Lambda.ManglingNumber);
> > AddDeclRef(Lambda.ContextDecl, Record);
> > AddTypeSourceInfo(Lambda.MethodTyInfo, Record);
> > + AddStmt(Lambda.TheLambdaExpr);
> > for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) {
> > LambdaExpr::Capture &Capture = Lambda.Captures[I];
> > AddSourceLocation(Capture.getLocation(), Record);
> >
> > Added:
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp?rev=188977&view=auto
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
> (added)
> > +++
> cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p3-generic-lambda-1y.cpp
> Wed Aug 21 20:49:11 2013
> > @@ -0,0 +1,75 @@
> > +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
> > +
> > +//FIXME: These tests were written when return type deduction had not
> been implemented
> > +// for generic lambdas, hence
> > +template<class T> T id(T t);
> > +template<class ... Ts> int vfoo(Ts&& ... ts);
> > +auto GL1 = [](auto a, int i) -> int { return id(a); };
> > +
> > +auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
> > +auto GL3 = [](int i, char c, auto* ... As) -> int { return vfoo(As...);
> };
> > +
> > +auto GL4 = [](int i, char c, auto* ... As) -> int { return vfoo(As...);
> };
> > +
> > +
> > +void foo() {
> > + auto GL1 = [](auto a, int i) -> int { return id(a); };
> > +
> > + auto GL2 = [](auto ... As) -> int { return vfoo(As...); };
> > +}
> > +
> > +
> > +int main()
> > +{
> > + auto l1 = [](auto a) -> int { return a + 5; };
> > + auto l2 = [](auto *p) -> int { return p + 5; };
> > +
> > + struct A { int i; char f(int) { return 'c'; } };
> > + auto l3 = [](auto &&ur,
> > + auto &lr,
> > + auto v,
> > + int i,
> > + auto* p,
> > + auto A::*memvar,
> > + auto (A::*memfun)(int),
> > + char c,
> > + decltype (v)* pv
> > + , auto (&array)[5]
> > + ) -> int { return v + i + c
> > + + array[0];
> > + };
> > + int arr[5] = {0, 1, 2, 3, 4 };
> > + int lval = 0;
> > + double d = 3.14;
> > + l3(3, lval, d, lval, &lval, &A::i, &A::f, 'c', &d, arr);
> > + auto l4 = [](decltype(auto) a) -> int { return 0; };
> //expected-error{{decltype(auto)}}
> > + {
> > + struct Local {
> > + static int ifi(int i) { return i; }
> > + static char cfi(int) { return 'a'; }
> > + static double dfi(int i) { return i + 3.14; }
> > + static Local localfi(int) { return Local{}; }
> > + };
> > + auto l4 = [](auto (*fp)(int)) -> int { return fp(3); };
> //expected-error{{no viable conversion from 'Local' to 'int'}}
> > + l4(&Local::ifi);
> > + l4(&Local::cfi);
> > + l4(&Local::dfi);
> > + l4(&Local::localfi); //expected-note{{in instantiation of function
> template specialization}}
> > + }
> > + {
> > + auto unnamed_parameter = [](auto, auto) -> void { };
> > + unnamed_parameter(3, '4');
> > + }
> > + {
> > + auto l = [](auto
> > + (*)(auto)) { }; //expected-error{{'auto' not
> allowed}}
> > + //FIXME: These diagnostics might need some work.
> > + auto l2 = [](char auto::*pm) { }; //expected-error{{cannot combine
> with previous}}\
> > + expected-error{{'pm' does not
> point into a class}}
> > + auto l3 = [](char (auto::*pmf)()) { }; //expected-error{{'auto'
> not allowed}}\
> > + expected-error{{'pmf'
> does not point into a class}}\
> > + expected-error{{function
> cannot return function type 'char ()'}}
> > + }
> > +}
> > +
> > +
> >
> > Added:
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp?rev=188977&view=auto
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
> (added)
> > +++
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp
> Wed Aug 21 20:49:11 2013
> > @@ -0,0 +1,50 @@
> > +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -emit-llvm
> > +namespace return_type_deduction_ok {
> > +// FIXME: Once return type deduction is implemented for generic lambdas
> > +// this will need to be updated.
> > + auto l = [](auto a) ->auto { return a; }(2);
> > + auto l2 = [](auto a) ->decltype(auto) { return a; }(2);
> > + auto l3 = [](auto a) { return a; }(2);
> > +
> > +
> > +}
> > +
> > +namespace lambda_capturing {
> > +// FIXME: Once return type deduction is implemented for generic lambdas
> > +// this will need to be updated.
> > +void test() {
> > + int i = 10;
> > + auto L = [=](auto a) -> int { //expected-error{{unimplemented}}
> > + return i + a;
> > + };
> > + L(3);
> > +}
> > +
> > +}
> > +
> > +namespace nested_generic_lambdas {
> > +void test() {
> > + auto L = [](auto a) -> int {
> > + auto M = [](auto b, decltype(a) b2) -> int {
> //expected-error{{unimplemented}}
> > + return 1;
> > + };
> > + M(a, a);
> > + };
> > + L(3); //expected-note{{in instantiation of}}
> > +}
> > +}
> > +
> > +namespace conversion_operator {
> > +void test() {
> > + auto L = [](auto a) -> int { return a; };
> > + int (*fp)(int) = L; //expected-error{{no viable conversion}}
> > + }
> > +}
> > +
> > +namespace generic_lambda_as_default_argument_ok {
> > + void test(int i = [](auto a)->int { return a; }(3)) {
> > +
> > + }
> > +
> > +}
> > +
> >
> > Added:
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp?rev=188977&view=auto
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
> (added)
> > +++
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p2-generic-lambda-1y.cpp
> Wed Aug 21 20:49:11 2013
> > @@ -0,0 +1,23 @@
> > +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
> > +
> > +// prvalue
> > +void prvalue() {
> > + auto&& x = [](auto a)->void { };
> > + auto& y = [](auto *a)->void { }; // expected-error{{cannot bind to a
> temporary of type}}
> > +}
> > +
> > +namespace std {
> > + class type_info;
> > +}
> > +
> > +struct P {
> > + virtual ~P();
> > +};
> > +
> > +void unevaluated_operand(P &p, int i) {
> > + // FIXME: this should only emit one error.
> > + int i2 = sizeof([](auto a, auto b)->void{}(3, '4')); //
> expected-error{{lambda expression in an unevaluated operand}} \
> > + //
> expected-error{{invalid application of 'sizeof'}}
> > + const std::type_info &ti1 = typeid([](auto &a) -> P& { static P p;
> return p; }(i));
> > + const std::type_info &ti2 = typeid([](auto) -> int { return i; }(i));
> // expected-error{{lambda expression in an unevaluated operand}}
> > +}
> >
> > Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp
> (original)
> > +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4-1y.cpp Wed Aug
> 21 20:49:11 2013
> > @@ -7,3 +7,60 @@ int &d = [] (int &r) -> auto & { return
> > int &e = [] (int &r) -> auto { return r; } (a); // expected-error
> {{cannot bind to a temporary}}
> > int &f = [] (int r) -> decltype(auto) { return r; } (a); //
> expected-error {{cannot bind to a temporary}}
> > int &g = [] (int r) -> decltype(auto) { return (r); } (a); //
> expected-warning {{reference to stack}}
> > +
> > +
> > +int test_explicit_auto_return()
> > +{
> > + struct X {};
> > + auto L = [](auto F, auto a) { return F(a); };
> > + auto M = [](auto a) -> auto { return a; }; // OK
> > + auto MRef = [](auto b) -> auto& { return b; };
> //expected-warning{{reference to stack}}
> > + auto MPtr = [](auto c) -> auto* { return &c; };
> //expected-warning{{address of stack}}
> > + auto MDeclType = [](auto&& d) -> decltype(auto) { return
> static_cast<decltype(d)>(d); }; //OK
> > + M(3);
> > +
> > + auto &&x = MDeclType(X{});
> > + auto &&x1 = M(X{});
> > + auto &&x2 = MRef(X{});//expected-note{{in instantiation of}}
> > + auto &&x3 = MPtr(X{}); //expected-note{{in instantiation of}}
> > + return 0;
> > +}
> > +
> > +int test_implicit_auto_return()
> > +{
> > + {
> > + auto M = [](auto a) { return a; };
> > + struct X {};
> > + X x = M(X{});
> > +
> > + }
> > +}
> > +
> > +int test_multiple_returns() {
> > + auto M = [](auto a) {
> > + bool k;
> > + if (k)
> > + return a;
> > + else
> > + return 5; //expected-error{{deduced as 'int' here}}
> > + };
> > + M(3); // OK
> > + M('a'); //expected-note{{in instantiation of}}
> > + return 0;
> > +}
> > +int test_no_parameter_list()
> > +{
> > + static int si = 0;
> > + auto M = [] { return 5; }; // OK
> > + auto M2 = [] -> auto&& { return si; }; // expected-error{{lambda
> requires '()'}}
> > + M();
> > +}
> > +
> > +int test_conditional_in_return() {
> > + auto Fac = [](auto f, auto n) {
> > + return n <= 0 ? n : f(f, n - 1) * n;
> > + };
> > + // FIXME: this test causes a recursive limit - need to error more
> gracefully.
> > + //Fac(Fac, 3);
> > +
> > +}
> > \ No newline at end of file
> >
> > Modified: cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp?rev=188977&r1=188976&r2=188977&view=diff
> >
> ==============================================================================
> > --- cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp (original)
> > +++ cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp Wed Aug 21
> 20:49:11 2013
> > @@ -1,5 +1,5 @@
> > // RUN: %clang_cc1 -fsyntax-only -std=c++11 %s -verify
> > -// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify
> > +// RUN: %clang_cc1 -fsyntax-only -std=c++1y %s -verify -DCPP1Y
> >
> > void missing_lambda_declarator() {
> > [](){}();
> > @@ -18,7 +18,7 @@ void infer_void_return_type(int i) {
> > switch (x) {
> > case 0: return get<void>();
> > case 1: return;
> > - case 2: return { 1, 2.0 }; // expected-error{{cannot deduce lambda
> return type from initializer list}}
> > + case 2: return { 1, 2.0 }; //expected-error{{cannot deduce}}
> > }
> > }(7);
> > }
> >
> > Added:
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
> > URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp?rev=188977&view=auto
> >
> ==============================================================================
> > ---
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
> (added)
> > +++
> cfe/trunk/test/CXX/expr/expr.prim/expr.prim.lambda/p5-generic-lambda-1y.cpp
> Wed Aug 21 20:49:11 2013
> > @@ -0,0 +1,135 @@
> > +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1y -DCXX1Y
> -emit-llvm
> > +
> > +namespace test_factorial {
> > +
> > +auto Fact = [](auto Self, unsigned n) -> unsigned {
> > + return !n ? 1 : Self(Self, n - 1) * n;
> > +};
> > +
> > +auto six = Fact(Fact, 3);
> > +
> > +}
> > +
> > +namespace overload_generic_lambda {
> > + template <class F1, class F2> struct overload : F1, F2 {
> > + using F1::operator();
> > + using F2::operator();
> > + overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
> > + };
> > +
> > + auto NumParams = [](auto Self, auto h, auto ... rest) -> unsigned {
> > + return 1 + Self(Self, rest...);
> > + };
> > + auto Base = [](auto Self, auto h) -> unsigned {
> > + return 1;
> > + };
> > + overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);
> > + int num_params = O(O, 5, 3, "abc", 3.14, 'a');
> > +}
> > +
> > +
> > +namespace overload_generic_lambda_return_type_deduction {
> > + template <class F1, class F2> struct overload : F1, F2 {
> > + using F1::operator();
> > + using F2::operator();
> > + overload(F1 f1, F2 f2) : F1(f1), F2(f2) { }
> > + };
> > +
> > + auto NumParams = [](auto Self, auto h, auto ... rest) {
> > + return 1 + Self(Self, rest...);
> > + };
> > + auto Base = [](auto Self, auto h) {
> > + return 1;
> > + };
> > + overload<decltype(Base), decltype(NumParams)> O(Base, NumParams);
> > + int num_params = O(O, 5, 3, "abc", 3.14, 'a');
> > +}
> > +
> > +namespace test_standard_p5 {
> > +// FIXME: This test should eventually compile without an explicit
> trailing return type
> > +auto glambda = [](auto a, auto&& b) ->bool { return a < b; };
> > +bool b = glambda(3, 3.14); // OK
> > +
> > +}
> > +namespace test_deduction_failure {
> > + int test() {
> > + auto g = [](auto *a) { //expected-note{{candidate template ignored}}
> > + return a;
> > + };
> > + struct X { };
> > + X *x;
> > + g(x);
> > + g(3); //expected-error{{no matching function}}
> > + return 0;
> > + }
> > +
> > +}
> > +
> > +namespace test_instantiation_or_sfinae_failure {
> > +int test2() {
> > + {
> > + auto L = [](auto *a) {
> > + return (*a)(a); }; //expected-error{{called object type
> 'double' is not a function}}
> > + //l(&l);
> > + double d;
> > + L(&d); //expected-note{{in instantiation of}}
> > + auto M = [](auto b) { return b; };
> > + L(&M); // ok
> > + }
> > + {
> > + auto L = [](auto *a) ->decltype (a->foo()) {
> //expected-note2{{candidate template ignored:}}
> > + return (*a)(a); };
> > + //l(&l);
> > + double d;
> > + L(&d); //expected-error{{no matching function for call}}
> > + auto M = [](auto b) { return b; };
> > + L(&M); //expected-error{{no matching function for call}}
> > +
> > + }
> > + return 0;
> > +}
> > +
> > +
> > +}
> > +
> > +namespace test_misc {
> > +auto GL = [](auto a, decltype(a) b) //expected-note{{candidate
> function}}
> > + -> int { return a + b; };
> > +
> > +void test() {
> > + struct X { };
> > + GL(3, X{}); //expected-error{{no matching function}}
> > +}
> > +
> > +void test2() {
> > + auto l = [](auto *a) -> int {
> > + (*a)(a); return 0; }; //expected-error{{called object
> type 'double' is not a function}}
> > + l(&l);
> > + double d;
> > + l(&d); //expected-note{{in instantiation of}}
> > +}
> > +
> > +}
> > +
> > +namespace nested_lambdas {
> > + int test() {
> > + auto L = [](auto a) {
> > + return [=](auto b) { //expected-error{{unimplemented}}
> > + return a + b;
> > + };
> > + };
> > + // auto M = L(3.14);
> > + // return M('4');
> > + }
> > + auto get_lambda() {
> > + return [](auto a) {
> > + return a;
> > + };
> > + };
> > +
> > + int test2() {
> > + auto L = get_lambda();
> > + L(3);
> > + }
> > +}
> > +
> >
> >
> > _______________________________________________
> > cfe-commits mailing list
> > cfe-commits at cs.uiuc.edu
> > http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130822/3caf563d/attachment.html>
More information about the cfe-commits
mailing list