diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 9a53b9e9fc2fddb8e91f951aa73362a154ea33f7..bb97b55f123c7ed4732a2fc11817ccc0a6cedb56 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -514,12 +514,10 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData : public DefinitionData { typedef LambdaExpr::Capture Capture; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) - : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), - CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), - ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info) + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) + : DefinitionData(D), Dependent(Dependent), NumCaptures(0), + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), + Captures(0), MethodTyInfo(Info), TheLambdaExpr(0) { IsLambda = true; } @@ -534,17 +532,11 @@ class CXXRecordDecl : public RecordDecl { /// artifact of having to parse the default arguments before. unsigned Dependent : 1; - /// \brief Whether this lambda is a generic lambda. - unsigned IsGenericLambda : 1; - - /// \brief The Default Capture. - unsigned CaptureDefault : 2; - - /// \brief The number of captures in this lambda is limited 2^NumCaptures. - unsigned NumCaptures : 15; + /// \brief The number of captures in this lambda. + unsigned NumCaptures : 16; /// \brief The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 13; + unsigned NumExplicitCaptures : 15; /// \brief The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. @@ -562,6 +554,9 @@ class CXXRecordDecl : public RecordDecl { /// \brief The type of the call method. TypeSourceInfo *MethodTyInfo; + + /// \brief The AST node of the lambda expression. + LambdaExpr *TheLambdaExpr; }; @@ -674,8 +669,7 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda, bool IsGeneric, - LambdaCaptureDefault CaptureDefault); + bool DependentLambda); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { @@ -1019,11 +1013,17 @@ public: /// lambda. TemplateParameterList *getGenericLambdaTemplateParameterList() const; - LambdaCaptureDefault getLambdaCaptureDefault() const { - assert(isLambda()); - return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); + /// \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. diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 00e74a812f58444e36622ecc22d5973c74c79fe3..abbf512f3c15f0c6d6bbd791d6cee6bd9999d743 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4453,8 +4453,7 @@ public: /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - bool KnownDependent, - LambdaCaptureDefault CaptureDefault); + bool KnownDependent); /// \brief Start the definition of a lambda expression. CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index ee25f65d49da1a7e14e60be3ac1d950e52335577..cdf5e9f1f5c0cffef561a430eb2af4a06d01fcce 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -108,15 +108,11 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) { + bool Dependent) { CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, 0, 0); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, - Dependent, - IsGeneric, - CaptureDefault); + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent); R->MayHaveOutOfDateDef = false; R->setImplicit(true); C.getTypeDeclType(R, /*PrevDecl=*/0); @@ -946,10 +942,10 @@ bool CXXRecordDecl::isCLike() const { return isPOD() && data().HasOnlyCMembers; } - + bool CXXRecordDecl::isGenericLambda() const { - if (!isLambda()) return false; - return getLambdaData().IsGenericLambda; + return isLambda() && + getLambdaCallOperator()->getDescribedFunctionTemplate(); } CXXMethodDecl* CXXRecordDecl::getLambdaCallOperator() const { diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index bc7be6d4593ea4bfb253891a3e628d39e26642cb..80f95e68690098b8d693d7e2fa89c0d0e1b4f10e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -9401,29 +9401,6 @@ Sema::CheckForFunctionRedefinition(FunctionDecl *FD, Diag(Definition->getLocation(), diag::note_previous_definition); FD->setInvalidDecl(); } -static void RebuildLambdaScopeInfo(CXXMethodDecl *CallOperator, - Sema &S) { - CXXRecordDecl *const LambdaClass = CallOperator->getParent(); - S.PushLambdaScope(); - LambdaScopeInfo *LSI = S.getCurLambda(); - LSI->CallOperator = CallOperator; - LSI->Lambda = LambdaClass; - LSI->ReturnType = CallOperator->getResultType(); - const LambdaCaptureDefault LCD = LambdaClass->getLambdaCaptureDefault(); - - if (LCD == LCD_None) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_None; - else if (LCD == LCD_ByCopy) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByval; - else if (LCD == LCD_ByRef) - LSI->ImpCaptureStyle = CapturingScopeInfo::ImpCap_LambdaByref; - DeclarationNameInfo DNI = CallOperator->getNameInfo(); - - LSI->IntroducerRange = DNI.getCXXOperatorNameRange(); - LSI->Mutable = !CallOperator->isConst(); - - // FIXME: Add the captures to the LSI. -} Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { // Clear the last template instantiation error context. @@ -9439,18 +9416,31 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D) { FD = cast<FunctionDecl>(D); // 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) to prime the current - // LambdaScopeInfo. - // When the template operator is being specialized, the LambdaScopeInfo, - // has to be properly restored so that tryCaptureVariable doesn't try - // and capture any new variables. In addition when calculating potential - // captures during transformation of nested lambdas, it is necessary to - // have the LSI properly restored. + // that's already been calculated (ActOnLambdaExpr) when analyzing the + // template version, to prime the current LambdaScopeInfo. if (isGenericLambdaCallOperatorSpecialization(FD)) { + 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!"); - RebuildLambdaScopeInfo(cast<CXXMethodDecl>(D), *this); + 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 @@ -9814,6 +9804,7 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body, PopDeclContext(); PopFunctionScopeInfo(ActivePolicy, dcl); + // If any errors have occurred, clear out any temporaries that may have // been leftover. This ensures that these temporaries won't be picked up for // deletion in some later function. diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 9b3afc999020004b5f2d30b0c782c0fbb582a65a..32a385caaa559fe349bd376464e371a55758d112 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -24,43 +24,17 @@ using namespace clang; using namespace sema; - -static inline TemplateParameterList * -getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { - if (LSI->GLTemplateParameterList) - return LSI->GLTemplateParameterList; - - 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; -} - - - CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, - bool KnownDependent, - LambdaCaptureDefault CaptureDefault) { + bool KnownDependent) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); - bool IsGenericLambda = getGenericLambdaTemplateParameterList(getCurLambda(), - *this); + // Start constructing the lambda class. CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info, IntroducerRange.getBegin(), - KnownDependent, - IsGenericLambda, - CaptureDefault); + KnownDependent); DC->addDecl(Class); return Class; @@ -157,6 +131,25 @@ Sema::ExpressionEvaluationContextRecord::getMangleNumberingContext( return *MangleNumbering; } +static inline TemplateParameterList * +getGenericLambdaTemplateParameterList(LambdaScopeInfo *LSI, Sema &SemaRef) { + if (LSI->GLTemplateParameterList) + return LSI->GLTemplateParameterList; + else if (LSI->AutoTemplateParams.size()) { + SourceRange IntroRange = LSI->IntroducerRange; + SourceLocation LAngleLoc = IntroRange.getBegin(); + SourceLocation RAngleLoc = IntroRange.getEnd(); + LSI->GLTemplateParameterList = + TemplateParameterList::Create(SemaRef.Context, + /* Template kw loc */ SourceLocation(), + LAngleLoc, + (NamedDecl**)LSI->AutoTemplateParams.data(), + LSI->AutoTemplateParams.size(), RAngleLoc); + } + return LSI->GLTemplateParameterList; +} + + CXXMethodDecl *Sema::startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodTypeInfo, @@ -250,8 +243,7 @@ void Sema::buildLambdaScope(LambdaScopeInfo *LSI, bool ExplicitResultType, bool Mutable) { LSI->CallOperator = CallOperator; - CXXRecordDecl *LambdaClass = CallOperator->getParent(); - LSI->Lambda = LambdaClass; + LSI->Lambda = CallOperator->getParent(); if (CaptureDefault == LCD_ByCopy) LSI->ImpCaptureStyle = LambdaScopeInfo::ImpCap_LambdaByval; else if (CaptureDefault == LCD_ByRef) @@ -636,7 +628,7 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, } CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, - KnownDependent, Intro.Default); + KnownDependent); CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); @@ -1163,6 +1155,7 @@ ExprResult Sema::ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, 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). diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3c621dafab9dc33e02337e8dab5356fe25827c5f..f13b14bd0f1bcf654c87552f4899c5271b3d39bb 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -14,7 +14,6 @@ #include "TreeTransform.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/ASTLambda.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/Basic/LangOptions.h" @@ -131,11 +130,6 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, assert(Function->getPrimaryTemplate() && "No function template?"); if (Function->getPrimaryTemplate()->isMemberSpecialization()) break; - - // If this function is a generic lambda specialization, we are done. - if (isGenericLambdaCallOperatorSpecialization(Function)) - break; - } else if (FunctionTemplateDecl *FunTmpl = Function->getDescribedFunctionTemplate()) { // Add the "injected" template arguments. @@ -917,36 +911,13 @@ namespace { } ExprResult TransformLambdaScope(LambdaExpr *E, - CXXMethodDecl *NewCallOperator) { - CXXMethodDecl *const OldCallOperator = E->getCallOperator(); - // In the generic lambda case, we set the NewTemplate to be considered - // an "instantiation" of the OldTemplate. - if (FunctionTemplateDecl *const NewCallOperatorTemplate = - NewCallOperator->getDescribedFunctionTemplate()) { - - FunctionTemplateDecl *const OldCallOperatorTemplate = - OldCallOperator->getDescribedFunctionTemplate(); - NewCallOperatorTemplate->setInstantiatedFromMemberTemplate( - OldCallOperatorTemplate); - // Mark the NewCallOperatorTemplate a specialization. - NewCallOperatorTemplate->setMemberSpecialization(); - } else - // For a non-generic lambda we set the NewCallOperator to - // be an instantiation of the OldCallOperator. - NewCallOperator->setInstantiationOfMemberFunction(OldCallOperator, - TSK_ImplicitInstantiation); - - return inherited::TransformLambdaScope(E, NewCallOperator); - } - TemplateParameterList *TransformTemplateParameterList( - TemplateParameterList *OrigTPL) { - if (!OrigTPL || !OrigTPL->size()) return OrigTPL; - - DeclContext *Owner = OrigTPL->getParam(0)->getDeclContext(); - TemplateDeclInstantiator DeclInstantiator(getSema(), - /* DeclContext *Owner */ Owner, TemplateArgs); - return DeclInstantiator.SubstTemplateParams(OrigTPL); + CXXMethodDecl *CallOperator) { + CallOperator->setInstantiationOfMemberFunction(E->getCallOperator(), + TSK_ImplicitInstantiation); + return TreeTransform<TemplateInstantiator>:: + TransformLambdaScope(E, CallOperator); } + private: ExprResult transformNonTypeTemplateParmRef(NonTypeTemplateParmDecl *parm, SourceLocation loc, diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index d0c3ac69144e79178f3f7b915c9ba807a96b0e0e..d1512c271c0166773ebcf1fba5230205f12d2ba9 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -4174,8 +4174,7 @@ DeclContext *Sema::FindInstantiatedContext(SourceLocation Loc, DeclContext* DC, NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs) { DeclContext *ParentDC = D->getDeclContext(); - - if (isa<NonTypeTemplateParmDecl>(D) || + if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) || (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) || (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) { diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 2d22e4ca6473a808f444e64372d81dda4aa9a85c..97e12d77a194258b6a84a996df755e5a7a6ffddf 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -593,11 +593,6 @@ public: /// \brief Transform the captures and body of a lambda expression. ExprResult TransformLambdaScope(LambdaExpr *E, CXXMethodDecl *CallOperator); - TemplateParameterList *TransformTemplateParameterList( - TemplateParameterList *TPL) { - return TPL; - } - ExprResult TransformAddressOfOperand(Expr *E); ExprResult TransformDependentScopeDeclRefExpr(DependentScopeDeclRefExpr *E, bool IsAddressOfOperand); @@ -8272,102 +8267,48 @@ template<typename Derived> ExprResult TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { - getSema().PushLambdaScope(); - LambdaScopeInfo *LSI = getSema().getCurLambda(); - // Transform the template parameters, and add them to the current - // instantiation scope. The null case is handled correctly. - LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList( - E->getTemplateParameterList()); - - // Check to see if the TypeSourceInfo of the call operator needs to - // be transformed, and if so do the transformation in the - // CurrentInstantiationScope. - - TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo(); - FunctionProtoTypeLoc OldCallOpFPTL = - OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>(); - TypeSourceInfo *NewCallOpTSI = 0; - - const bool CallOpWasAlreadyTransformed = - getDerived().AlreadyTransformed(OldCallOpTSI->getType()); - - // Use the Old Call Operator's TypeSourceInfo if it is already transformed. - if (CallOpWasAlreadyTransformed) - NewCallOpTSI = OldCallOpTSI; - else { - // Transform the TypeSourceInfo of the Original Lambda's Call Operator. - // The transformation MUST be done in the CurrentInstantiationScope since - // it introduces a mapping of the original to the newly created - // transformed parameters. - - TypeLocBuilder NewCallOpTLBuilder; - QualType NewCallOpType = TransformFunctionProtoType(NewCallOpTLBuilder, - OldCallOpFPTL, - 0, 0); - NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, - NewCallOpType); - } - // Extract the ParmVarDecls from the NewCallOpTSI and add them to - // the vector below - this will be used to synthesize the - // NewCallOperator. Additionally, add the parameters of the untransformed - // lambda call operator to the CurrentInstantiationScope. - SmallVector<ParmVarDecl *, 4> Params; - { - FunctionProtoTypeLoc NewCallOpFPTL = - NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>(); - ParmVarDecl **NewParamDeclArray = NewCallOpFPTL.getParmArray(); - const unsigned NewNumArgs = NewCallOpFPTL.getNumArgs(); - - for (unsigned I = 0; I < NewNumArgs; ++I) { - // If this call operator's type does not require transformation, - // the parameters do not get added to the current instantiation scope, - // - so ADD them! This allows the following to compile when the enclosing - // template is specialized and the entire lambda expression has to be - // transformed. - // template<class T> void foo(T t) { - // auto L = [](auto a) { - // auto M = [](char b) { <-- note: non-generic lambda - // auto N = [](auto c) { - // int x = sizeof(a); - // x = sizeof(b); <-- specifically this line - // x = sizeof(c); - // }; - // }; - // }; - // } - // foo('a') - if (CallOpWasAlreadyTransformed) - getDerived().transformedLocalDecl(NewParamDeclArray[I], - NewParamDeclArray[I]); - // Add to Params array, so these parameters can be used to create - // the newly transformed call operator. - Params.push_back(NewParamDeclArray[I]); - } + // FIXME: Implement nested generic lambda transformations. + if (E->isGenericLambda()) { + getSema().Diag(E->getIntroducerRange().getBegin(), + diag::err_glambda_not_fully_implemented) + << " template transformation of generic lambdas not implemented yet"; + return ExprError(); } - - if (!NewCallOpTSI) + // Transform the type of the lambda parameters and start the definition of + // the lambda itself. + TypeSourceInfo *MethodTy + = TransformType(E->getCallOperator()->getTypeSourceInfo()); + if (!MethodTy) return ExprError(); // Create the local class that will describe the lambda. CXXRecordDecl *Class = getSema().createLambdaClosureType(E->getIntroducerRange(), - NewCallOpTSI, - /*KnownDependent=*/false, - E->getCaptureDefault()); - + MethodTy, + /*KnownDependent=*/false); getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + // Transform lambda parameters. + SmallVector<QualType, 4> ParamTypes; + SmallVector<ParmVarDecl *, 4> Params; + if (getDerived().TransformFunctionTypeParams(E->getLocStart(), + E->getCallOperator()->param_begin(), + 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 *NewCallOperator + CXXMethodDecl *CallOperator = getSema().startLambdaDefinition(Class, E->getIntroducerRange(), - NewCallOpTSI, + MethodTy, E->getCallOperator()->getLocEnd(), Params); - LSI->CallOperator = NewCallOperator; - - getDerived().transformAttrs(E->getCallOperator(), NewCallOperator); + getDerived().transformAttrs(E->getCallOperator(), CallOperator); - return getDerived().TransformLambdaScope(E, NewCallOperator); + return getDerived().TransformLambdaScope(E, CallOperator); } template<typename Derived> diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 0c885bc5792146a7a0b8752c5e1034b9bed5f67c..463af777986f9cb212f9b8f4a0913dd3dc13378f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1226,8 +1226,6 @@ void ASTDeclReader::ReadCXXDefinitionData( CXXRecordDecl::LambdaDefinitionData &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); Lambda.Dependent = Record[Idx++]; - Lambda.IsGenericLambda = Record[Idx++]; - Lambda.CaptureDefault = Record[Idx++]; Lambda.NumCaptures = Record[Idx++]; Lambda.NumExplicitCaptures = Record[Idx++]; Lambda.ManglingNumber = Record[Idx++]; @@ -1236,6 +1234,7 @@ void ASTDeclReader::ReadCXXDefinitionData( = (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++]; @@ -1267,8 +1266,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { bool IsLambda = Record[Idx++]; if (IsLambda) D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0, - false, - false, LCD_None); + false); else D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 3d14512540fa79ff6df19078184c4be755ba8662..3ee9830e7cb036356bcd20b9ecd3244502db907d 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -5129,13 +5129,12 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec if (Data.IsLambda) { CXXRecordDecl::LambdaDefinitionData &Lambda = D->getLambdaData(); Record.push_back(Lambda.Dependent); - Record.push_back(Lambda.IsGenericLambda); - Record.push_back(Lambda.CaptureDefault); Record.push_back(Lambda.NumCaptures); Record.push_back(Lambda.NumExplicitCaptures); 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); diff --git a/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp b/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp index 92dd7ad1876c54aeaf50314782899dc8571fd5f2..a43a98bb18f859a939a46d630561c6d238e9e9bc 100644 --- a/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp +++ b/test/CXX/expr/expr.prim/expr.prim.lambda/generic-lambda-unimplemented-1y.cpp @@ -29,3 +29,20 @@ void test() { } +namespace nested_generic_lambdas { +void test() { + auto L = [](auto a) -> int { + auto M = [](auto b, decltype(a) b2) -> int { //expected-error{{unimplemented}} + return 1; + }; + M(a, a); + }; + L(3); //expected-note{{in instantiation of}} +} +template<class T> void foo(T) { + auto L = [](auto a) { return a; }; //expected-error{{unimplemented}} +} +template void foo(int); //expected-note{{in instantiation of}} +} + + diff --git a/test/PCH/cxx1y-lambdas.mm b/test/PCH/cxx1y-lambdas.mm deleted file mode 100644 index ee4a2ba3ecc97e3b956d7c2b65b359c1cb101fe7..0000000000000000000000000000000000000000 --- a/test/PCH/cxx1y-lambdas.mm +++ /dev/null @@ -1,58 +0,0 @@ -// RUN: %clang_cc1 -pedantic-errors -fblocks -std=c++1y -emit-pch %s -o %t-cxx1y -// RUN: %clang_cc1 -ast-print -pedantic-errors -fblocks -std=c++1y -include-pch %t-cxx1y %s | FileCheck -check-prefix=CHECK-PRINT %s - -#ifndef HEADER_INCLUDED - -#define HEADER_INCLUDED -template<typename T> -T add_slowly(const T& x, const T &y) { - return [](auto z, int y = 0) { return z + y; }(5); -}; - -inline int add_int_slowly_twice(int x, int y) { - int i = add_slowly(x, y); - auto lambda = [](auto z) { return z + z; }; - return i + lambda(y); -} - -inline int sum_array(int n) { - auto lambda = [](auto N) -> int { - int sum = 0; - int array[5] = { 1, 2, 3, 4, 5}; - - for (unsigned I = 0; I < N; ++I) - sum += array[N]; - return sum; - }; - - return lambda(n); -} - -inline int to_block_pointer(int n) { - auto lambda = [=](int m) { return n + m; }; - int (^block)(int) = lambda; - return block(17); -} - -template<typename T> -int init_capture(T t) { - return [&, x(t)] { return sizeof(x); }; -} - -#else - -// CHECK-PRINT: T add_slowly -// CHECK-PRINT: return [] -template float add_slowly(const float&, const float&); - -int add(int x, int y) { - return add_int_slowly_twice(x, y) + sum_array(4) + to_block_pointer(5); -} - -// CHECK-PRINT: inline int add_int_slowly_twice -// CHECK-PRINT: lambda = [] ($auto-0-0 z - -// CHECK-PRINT: init_capture -// CHECK-PRINT: [&, x( t )] - -#endif diff --git a/test/SemaCXX/cxx1y-generic-lambdas.cpp b/test/SemaCXX/cxx1y-generic-lambdas.cpp index 64b9ff14215e2bad5d004786f043045e190001af..b66825a536dc3939b7df65135325df5f42847984 100644 --- a/test/SemaCXX/cxx1y-generic-lambdas.cpp +++ b/test/SemaCXX/cxx1y-generic-lambdas.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -emit-llvm -o - %s +// RUN: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks %s // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing %s -DDELAYED_TEMPLATE_PARSING // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fms-extensions %s -DMS_EXTENSIONS // DONTRUNYET: %clang_cc1 -std=c++1y -verify -fsyntax-only -fblocks -fdelayed-template-parsing -fms-extensions %s -DMS_EXTENSIONS -DDELAYED_TEMPLATE_PARSING @@ -99,8 +99,10 @@ void test() { //expected-note{{candidate}} } } + } + namespace return_type_deduction_ok { auto l = [](auto a) ->auto { return a; }(2); auto l2 = [](auto a) ->decltype(auto) { return a; }(2); @@ -112,516 +114,3 @@ namespace generic_lambda_as_default_argument_ok { void test(int i = [](auto a)->int { return a; }(3)) { } } - -namespace nested_non_capturing_lambda_tests { -template<class ... Ts> void print(Ts ...) { } -int test() { -{ - auto L = [](auto a) { - return [](auto b) { - return b; - }; - }; - auto M = L(3); - M(4.15); - } -{ - int i = 10; //expected-note{{declared here}} - auto L = [](auto a) { - return [](auto b) { //expected-note{{begins here}} - i = b; //expected-error{{cannot be implicitly captured}} - return b; - }; - }; - auto M = L(3); - M(4.15); //expected-note{{instantiation}} - } - { - auto L = [](auto a) { - print("a = ", a, "\n"); - return [](auto b) ->decltype(a) { - print("b = ", b, "\n"); - return b; - }; - }; - auto M = L(3); - M(4.15); - } - -{ - auto L = [](auto a) ->decltype(a) { - print("a = ", a, "\n"); - return [](auto b) ->decltype(a) { //expected-error{{no viable conversion}}\ - //expected-note{{candidate template ignored}} - print("b = ", b, "\n"); - return b; - }; - }; - auto M = L(3); //expected-note{{in instantiation of}} - } -{ - auto L = [](auto a) { - print("a = ", a, "\n"); - return [](auto ... b) ->decltype(a) { - print("b = ", b ..., "\n"); - return 4; - }; - }; - auto M = L(3); - M(4.15, 3, "fv"); -} - -{ - auto L = [](auto a) { - print("a = ", a, "\n"); - return [](auto ... b) ->decltype(a) { - print("b = ", b ..., "\n"); - return 4; - }; - }; - auto M = L(3); - int (*fp)(double, int, const char*) = M; - fp(4.15, 3, "fv"); -} - -{ - auto L = [](auto a) { - print("a = ", a, "\n"); - return [](char b) { - return [](auto ... c) ->decltype(b) { - print("c = ", c ..., "\n"); - return 42; - }; - }; - }; - L(4); - auto M = L(3); - M('a'); - auto N = M('x'); - N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - char (*np)(const char*, int, const char*, double, const char*, int) = N; - np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -} - - -{ - auto L = [](auto a) { - print("a = ", a, "\n"); - return [](decltype(a) b) { - return [](auto ... c) ->decltype(b) { - print("c = ", c ..., "\n"); - return 42; - }; - }; - }; - L('4'); - auto M = L('3'); - M('a'); - auto N = M('x'); - N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - char (*np)(const char*, int, const char*, double, const char*, int) = N; - np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -} - - -{ - struct X { - static void foo(double d) { } - void test() { - auto L = [](auto a) { - print("a = ", a, "\n"); - foo(a); - return [](decltype(a) b) { - foo(b); - foo(sizeof(a) + sizeof(b)); - return [](auto ... c) ->decltype(b) { - print("c = ", c ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return 42; - }; - }; - }; - L('4'); - auto M = L('3'); - M('a'); - auto N = M('x'); - N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - char (*np)(const char*, int, const char*, double, const char*, int) = N; - np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - } -}; -X x; -x.test(); -} -// Make sure we can escape the function -{ - struct X { - static void foo(double d) { } - auto test() { - auto L = [](auto a) { - print("a = ", a, "\n"); - foo(a); - return [](decltype(a) b) { - foo(b); - foo(sizeof(a) + sizeof(b)); - return [](auto ... c) ->decltype(b) { - print("c = ", c ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return 42; - }; - }; - }; - return L; - } -}; - X x; - auto L = x.test(); - L('4'); - auto M = L('3'); - M('a'); - auto N = M('x'); - N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - char (*np)(const char*, int, const char*, double, const char*, int) = N; - np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -} - -{ - struct X { - static void foo(double d) { } - auto test() { - auto L = [](auto a) { - print("a = ", a, "\n"); - foo(a); - return [](decltype(a) b) { - foo(b); - foo(sizeof(a) + sizeof(b)); - return [](auto ... c) { - print("c = ", c ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} - print("d = ", d ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return decltype(a){}; - }; - }; - }; - }; - return L; - } -}; - X x; - auto L = x.test(); - L('4'); - auto M = L('3'); - M('a'); - auto N = M('x'); - auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - char (*np)(const char*, int, const char*, double, const char*, int) = O; - np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); - int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} - -} -} // end test() - -namespace wrapped_within_templates { - -namespace explicit_return { -template<class T> int fooT(T t) { - auto L = [](auto a) -> void { - auto M = [](char b) -> void { - auto N = [](auto c) -> void { - int x = 0; - x = sizeof(a); - x = sizeof(b); - x = sizeof(c); - }; - N('a'); - N(decltype(a){}); - }; - }; - L(t); - L(3.14); - return 0; -} - -int run = fooT('a') + fooT(3.14); - -} // end explicit_return - -namespace implicit_return_deduction { -template<class T> auto fooT(T t) { - auto L = [](auto a) { - auto M = [](char b) { - auto N = [](auto c) { - int x = 0; - x = sizeof(a); - x = sizeof(b); - x = sizeof(c); - }; - N('a'); - N(decltype(a){}); - }; - }; - L(t); - L(3.14); - return 0; -} - -int run = fooT('a') + fooT(3.14); - -template<class ... Ts> void print(Ts ... ts) { } - -template<class F, class ... Rest> using first = F; - -template<class ... Ts> auto fooV(Ts ... ts) { - auto L = [](auto ... a) { - auto M = [](decltype(a) ... b) { - auto N = [](auto c) { - int x = 0; - x = sizeof...(a); - x = sizeof...(b); - x = sizeof(c); - }; - N('a'); - N(N); - N(first<Ts...>{}); - }; - M(a...); - print("a = ", a..., "\n"); - }; - L(L, ts...); - print("ts = ", ts..., "\n"); - return 0; -} - -int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); - -} //implicit_return_deduction - - -} //wrapped_within_templates - -namespace at_ns_scope { - void foo(double d) { } - auto test() { - auto L = [](auto a) { - print("a = ", a, "\n"); - foo(a); - return [](decltype(a) b) { - foo(b); - foo(sizeof(a) + sizeof(b)); - return [](auto ... c) { - print("c = ", c ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} - print("d = ", d ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return decltype(a){}; - }; - }; - }; - }; - return L; - } -auto L = test(); -auto L_test = L('4'); -auto M = L('3'); -auto M_test = M('a'); -auto N = M('x'); -auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -char (*np)(const char*, int, const char*, double, const char*, int) = O; -auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} - - - -} - -namespace variadic_tests_1 { -template<class ... Ts> void print(Ts ... ts) { } - -template<class F, class ... Rest> using FirstType = F; -template<class F, class ... Rest> F& FirstArg(F& f, Rest...) { return f; } - -template<class ... Ts> int fooV(Ts ... ts) { - auto L = [](auto ... a) -> void { - auto M = [](decltype(a) ... b) -> void { - auto N = [](auto c) -> void { - int x = 0; - x = sizeof...(a); - x = sizeof...(b); - x = sizeof(c); - }; - N('a'); - N(N); - N(FirstType<Ts...>{}); - }; - M(a...); - print("a = ", a..., "\n"); - }; - L(L, ts...); - print("ts = ", ts..., "\n"); - return 0; -} - -int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); - -namespace more_variadic_1 { - -template<class ... Ts> int fooV(Ts ... ts) { - auto L = [](auto ... a) { - auto M = [](decltype(a) ... b) -> void { - auto N = [](auto c) -> void { - int x = 0; - x = sizeof...(a); - x = sizeof...(b); - x = sizeof(c); - }; - N('a'); - N(N); - N(FirstType<Ts...>{}); - }; - M(a...); - return M; - }; - auto M = L(L, ts...); - decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; - void (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...); - - { - auto L = [](auto ... a) { - auto M = [](decltype(a) ... b) { - auto N = [](auto c) -> void { - int x = 0; - x = sizeof...(a); - x = sizeof...(b); - x = sizeof(c); - }; - N('a'); - N(N); - N(FirstType<Ts...>{}); - return N; - }; - M(a...); - return M; - }; - auto M = L(L, ts...); - decltype(L(L, ts...)) (*fp)(decltype(L), decltype(ts) ...) = L; - fp(L, ts...); - decltype(L(L, ts...)(L, ts...)) (*fp2)(decltype(L), decltype(ts) ...) = L(L, ts...); - fp2 = fp(L, ts...); - void (*fp3)(char) = fp2(L, ts...); - fp3('a'); - } - return 0; -} - -int run2 = fooV(3.14, " ", '4', 5) + fooV("BC", 3, 2.77, 'A', float{}, short{}, unsigned{}); - - -} //end ns more_variadic_1 - -} // end ns variadic_tests_1 - -namespace at_ns_scope_within_class_member { - struct X { - static void foo(double d) { } - auto test() { - auto L = [](auto a) { - print("a = ", a, "\n"); - foo(a); - return [](decltype(a) b) { - foo(b); - foo(sizeof(a) + sizeof(b)); - return [](auto ... c) { - print("c = ", c ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return [](decltype(c) ... d) ->decltype(a) { //expected-note{{candidate}} - print("d = ", d ..., "\n"); - foo(decltype(b){}); - foo(sizeof(decltype(a)*) + sizeof(decltype(b)*)); - return decltype(a){}; - }; - }; - }; - }; - return L; - } -}; -X x; -auto L = x.test(); -auto L_test = L('4'); -auto M = L('3'); -auto M_test = M('a'); -auto N = M('x'); -auto O = N("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -char (*np)(const char*, int, const char*, double, const char*, int) = O; -auto NP_result = np("\n3 = ", 3, "\n6.14 = ", 6.14, "\n4'123'456 = ", 4'123'456); -int (*np2)(const char*, int, const char*, double, const char*, int) = O; // expected-error{{no viable conversion}} - -} //end at_ns_scope_within_class_member - - -namespace nested_generic_lambdas_123 { -void test() { - auto L = [](auto a) -> int { - auto M = [](auto b, decltype(a) b2) -> int { - return 1; - }; - M(a, a); - }; - L(3); -} -template<class T> void foo(T) { - auto L = [](auto a) { return a; }; -} -template void foo(int); -} // end ns nested_generic_lambdas_123 - - -} // end ns nested_non_capturing_lambda_tests - -namespace PR17476 { -struct string { - string(const char *__s) { } - string &operator+=(const string &__str) { return *this; } -}; - -template <class T> -void finalizeDefaultAtomValues() { - auto startEnd = [](const char * sym) -> void { - string start("__"); - start += sym; - }; - startEnd("preinit_array"); -} - -void f() { finalizeDefaultAtomValues<char>(); } - -} - -namespace PR17476_variant { -struct string { - string(const char *__s) { } - string &operator+=(const string &__str) { return *this; } -}; - -template <class T> -void finalizeDefaultAtomValues() { - auto startEnd = [](const T *sym) -> void { - string start("__"); - start += sym; - }; - startEnd("preinit_array"); -} - -void f() { finalizeDefaultAtomValues<char>(); } - -} \ No newline at end of file