From: Eli Friedman Date: Wed, 19 Sep 2012 01:18:11 +0000 (+0000) Subject: Add the TypeSourceInfo for the lambda call operator to the lambda's X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8da8a660128180a31479216111ff9b19b11c95b4;p=clang Add the TypeSourceInfo for the lambda call operator to the lambda's definition info; it needs to be there because the mangler needs to access it before we're finished defining the lambda class. PR12808. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164186 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 8d963c80a5..76be4086c9 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -563,9 +563,10 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData : public DefinitionData { typedef LambdaExpr::Capture Capture; - LambdaDefinitionData(CXXRecordDecl *D, bool Dependent) + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) : DefinitionData(D), Dependent(Dependent), NumCaptures(0), - NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0) + NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0), + MethodTyInfo(Info) { IsLambda = true; } @@ -598,7 +599,10 @@ class CXXRecordDecl : public RecordDecl { /// \brief The list of captures, both explicit and implicit, for this /// lambda. - Capture *Captures; + Capture *Captures; + + /// \brief The type of the call method. + TypeSourceInfo *MethodTyInfo; }; struct DefinitionData &data() { @@ -705,7 +709,8 @@ public: IdentifierInfo *Id, CXXRecordDecl* PrevDecl=0, bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, - SourceLocation Loc, bool DependentLambda); + TypeSourceInfo *Info, SourceLocation Loc, + bool DependentLambda); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { @@ -1500,7 +1505,11 @@ public: bool isDependentLambda() const { return isLambda() && getLambdaData().Dependent; } - + + TypeSourceInfo *getLambdaTypeInfo() const { + return getLambdaData().MethodTyInfo; + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstCXXRecord && K <= lastCXXRecord; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9a8eb310af..8c10af9b13 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -4026,7 +4026,8 @@ public: /// \brief Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, - bool KnownDependent = false); + TypeSourceInfo *Info, + 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 d2549eedd5..9db33357a6 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -90,11 +90,12 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, } CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, - SourceLocation Loc, bool Dependent) { + TypeSourceInfo *Info, SourceLocation Loc, + 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, Dependent); + R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, Dependent); C.getTypeDeclType(R, /*PrevDecl=*/0); return R; } diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 1a663a055d..afd425b5ea 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -1342,11 +1342,8 @@ void CXXNameMangler::mangleLambda(const CXXRecordDecl *Lambda) { } Out << "Ul"; - DeclarationName Name - = getASTContext().DeclarationNames.getCXXOperatorName(OO_Call); - const FunctionProtoType *Proto - = cast(*Lambda->lookup(Name).first)->getType()-> - getAs(); + const FunctionProtoType *Proto = Lambda->getLambdaTypeInfo()->getType()-> + getAs(); mangleBareFunctionType(Proto, /*MangleReturnType=*/false); Out << "E"; diff --git a/lib/Sema/SemaLambda.cpp b/lib/Sema/SemaLambda.cpp index 7cbfc364f6..489c895c99 100644 --- a/lib/Sema/SemaLambda.cpp +++ b/lib/Sema/SemaLambda.cpp @@ -22,13 +22,14 @@ using namespace clang; using namespace sema; CXXRecordDecl *Sema::createLambdaClosureType(SourceRange IntroducerRange, + TypeSourceInfo *Info, bool KnownDependent) { DeclContext *DC = CurContext; while (!(DC->isFunctionOrMethod() || DC->isRecord() || DC->isFileContext())) DC = DC->getParent(); // Start constructing the lambda class. - CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, + CXXRecordDecl *Class = CXXRecordDecl::CreateLambda(Context, DC, Info, IntroducerRange.getBegin(), KnownDependent); DC->addDecl(Class); @@ -369,8 +370,6 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (!TmplScope->decl_empty()) KnownDependent = true; - CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, KnownDependent); - // Determine the signature of the call operator. TypeSourceInfo *MethodTyInfo; bool ExplicitParams = true; @@ -419,7 +418,10 @@ void Sema::ActOnStartOfLambdaDefinition(LambdaIntroducer &Intro, if (MethodTyInfo->getType()->containsUnexpandedParameterPack()) ContainsUnexpandedParameterPack = true; } - + + CXXRecordDecl *Class = createLambdaClosureType(Intro.Range, MethodTyInfo, + KnownDependent); + CXXMethodDecl *Method = startLambdaDefinition(Class, Intro.Range, MethodTyInfo, EndLoc, Params); diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index 3d9a6ca11b..71d95ef41f 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -7856,12 +7856,6 @@ TreeTransform::TransformCXXTemporaryObjectExpr( template ExprResult TreeTransform::TransformLambdaExpr(LambdaExpr *E) { - // Create the local class that will describe the lambda. - CXXRecordDecl *Class - = getSema().createLambdaClosureType(E->getIntroducerRange(), - /*KnownDependent=*/false); - getDerived().transformedLocalDecl(E->getLambdaClass(), Class); - // Transform the type of the lambda parameters and start the definition of // the lambda itself. TypeSourceInfo *MethodTy @@ -7869,6 +7863,13 @@ TreeTransform::TransformLambdaExpr(LambdaExpr *E) { if (!MethodTy) return ExprError(); + // Create the local class that will describe the lambda. + CXXRecordDecl *Class + = getSema().createLambdaClosureType(E->getIntroducerRange(), + MethodTy, + /*KnownDependent=*/false); + getDerived().transformedLocalDecl(E->getLambdaClass(), Class); + // Transform lambda parameters. llvm::SmallVector ParamTypes; llvm::SmallVector Params; diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 816cb38a12..109d378105 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1136,6 +1136,7 @@ void ASTDeclReader::ReadCXXDefinitionData( Lambda.Captures = (Capture*)Reader.Context.Allocate(sizeof(Capture)*Lambda.NumCaptures); Capture *ToCapture = Lambda.Captures; + Lambda.MethodTyInfo = GetTypeSourceInfo(Record, Idx); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { SourceLocation Loc = ReadSourceLocation(Record, Idx); bool IsImplicit = Record[Idx++]; @@ -1156,7 +1157,8 @@ void ASTDeclReader::VisitCXXRecordDecl(CXXRecordDecl *D) { // allocate the appropriate DefinitionData structure. bool IsLambda = Record[Idx++]; if (IsLambda) - D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, false); + D->DefinitionData = new (C) CXXRecordDecl::LambdaDefinitionData(D, 0, + false); else D->DefinitionData = new (C) struct CXXRecordDecl::DefinitionData(D); diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp index 4a3987cbdc..b86df49bfe 100644 --- a/lib/Serialization/ASTWriter.cpp +++ b/lib/Serialization/ASTWriter.cpp @@ -4404,6 +4404,7 @@ void ASTWriter::AddCXXDefinitionData(const CXXRecordDecl *D, RecordDataImpl &Rec Record.push_back(Lambda.NumExplicitCaptures); Record.push_back(Lambda.ManglingNumber); AddDeclRef(Lambda.ContextDecl, Record); + AddTypeSourceInfo(Lambda.MethodTyInfo, Record); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { LambdaExpr::Capture &Capture = Lambda.Captures[I]; AddSourceLocation(Capture.getLocation(), Record);