From: Argyrios Kyrtzidis Date: Wed, 8 Sep 2010 19:31:22 +0000 (+0000) Subject: Fix C++ PCH issues. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6b5415196327fa8ef00f028ba175fafef1738ae1;p=clang Fix C++ PCH issues. PCH got a severe beating by the boost-using test case reported here: http://llvm.org/PR8099 Fix issues like: -When PCH reading, make sure Decl's getASTContext() doesn't get called since a Decl in the parent hierarchy may be initializing. -In ASTDeclReader::VisitFunctionDecl VisitRedeclarable should be called before using FunctionDecl's isCanonicalDecl() -In ASTDeclReader::VisitRedeclarableTemplateDecl CommonOrPrev must be initialized before anything else. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113391 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 6749255322..1f848f7e1c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1136,6 +1136,42 @@ private: /// declaration name embedded in the DeclaratorDecl base class. DeclarationNameLoc DNLoc; + /// \brief Specify that this function declaration is actually a function + /// template specialization. + /// + /// \param C the ASTContext. + /// + /// \param Template the function template that this function template + /// specialization specializes. + /// + /// \param TemplateArgs the template arguments that produced this + /// function template specialization from the template. + /// + /// \param InsertPos If non-NULL, the position in the function template + /// specialization set where the function template specialization data will + /// be inserted. + /// + /// \param TSK the kind of template specialization this is. + /// + /// \param TemplateArgsAsWritten location info of template arguments. + /// + /// \param PointOfInstantiation point at which the function template + /// specialization was first instantiated. + void setFunctionTemplateSpecialization(ASTContext &C, + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + + /// \brief Specify that this record is an instantiation of the + /// member function FD. + void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, + TemplateSpecializationKind TSK); + + void setParams(ASTContext &C, ParmVarDecl **NewParamInfo, unsigned NumParams); + protected: FunctionDecl(Kind DK, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, @@ -1343,7 +1379,9 @@ public: assert(i < getNumParams() && "Illegal param #"); return ParamInfo[i]; } - void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams); + void setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { + setParams(getASTContext(), NewParamInfo, NumParams); + } /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of @@ -1432,7 +1470,9 @@ public: /// \brief Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, - TemplateSpecializationKind TSK); + TemplateSpecializationKind TSK) { + setInstantiationOfMemberFunction(getASTContext(), FD, TSK); + } /// \brief Retrieves the function template that is described by this /// function declaration. @@ -1526,43 +1566,11 @@ public: void *InsertPos, TemplateSpecializationKind TSK = TSK_ImplicitInstantiation, const TemplateArgumentListInfo *TemplateArgsAsWritten = 0, - SourceLocation PointOfInstantiation = SourceLocation()); - - /// \brief Specify that this function declaration is actually a function - /// template specialization. - /// - /// \param Template the function template that this function template - /// specialization specializes. - /// - /// \param NumTemplateArgs number of template arguments that produced this - /// function template specialization from the template. - /// - /// \param TemplateArgs array of template arguments that produced this - /// function template specialization from the template. - /// - /// \param TSK the kind of template specialization this is. - /// - /// \param NumTemplateArgsAsWritten number of template arguments that produced - /// this function template specialization from the template. - /// - /// \param TemplateArgsAsWritten array of location info for the template - /// arguments. - /// - /// \param LAngleLoc location of left angle token. - /// - /// \param RAngleLoc location of right angle token. - /// - /// \param PointOfInstantiation point at which the function template - /// specialization was first instantiated. - void setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - unsigned NumTemplateArgs, - const TemplateArgument *TemplateArgs, - TemplateSpecializationKind TSK, - unsigned NumTemplateArgsAsWritten, - TemplateArgumentLoc *TemplateArgsAsWritten, - SourceLocation LAngleLoc, - SourceLocation RAngleLoc, - SourceLocation PointOfInstantiation); + SourceLocation PointOfInstantiation = SourceLocation()) { + setFunctionTemplateSpecialization(getASTContext(), Template, TemplateArgs, + InsertPos, TSK, TemplateArgsAsWritten, + PointOfInstantiation); + } /// \brief Specifies that this function declaration is actually a /// dependent function template specialization. diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index b532668242..ab8a13ce50 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -584,7 +584,7 @@ protected: /// for the common pointer. CommonBase *getCommonPtr(); - virtual CommonBase *newCommon() = 0; + virtual CommonBase *newCommon(ASTContext &C) = 0; // Construct a template decl with name, parameters, and templated element. RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, @@ -789,19 +789,13 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(); + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } - friend void FunctionDecl::setFunctionTemplateSpecialization( - FunctionTemplateDecl *Template, - const TemplateArgumentList *TemplateArgs, - void *InsertPos, - TemplateSpecializationKind TSK, - const TemplateArgumentListInfo *TemplateArgsAsWritten, - SourceLocation PointOfInstantiation); + friend class FunctionDecl; /// \brief Retrieve the set of function template specializations of this /// function template. @@ -1659,7 +1653,7 @@ protected: TemplateParameterList *Params, NamedDecl *Decl) : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } - CommonBase *newCommon(); + CommonBase *newCommon(ASTContext &C); Common *getCommonPtr() { return static_cast(RedeclarableTemplateDecl::getCommonPtr()); diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index b7be02d745..b2beb131c5 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1093,13 +1093,14 @@ unsigned FunctionDecl::getNumParams() const { } -void FunctionDecl::setParams(ParmVarDecl **NewParamInfo, unsigned NumParams) { +void FunctionDecl::setParams(ASTContext &C, + ParmVarDecl **NewParamInfo, unsigned NumParams) { assert(ParamInfo == 0 && "Already has param info!"); assert(NumParams == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. if (NumParams) { - void *Mem = getASTContext().Allocate(sizeof(ParmVarDecl*)*NumParams); + void *Mem = C.Allocate(sizeof(ParmVarDecl*)*NumParams); ParamInfo = new (Mem) ParmVarDecl*[NumParams]; memcpy(ParamInfo, NewParamInfo, sizeof(ParmVarDecl*)*NumParams); @@ -1271,12 +1272,13 @@ MemberSpecializationInfo *FunctionDecl::getMemberSpecializationInfo() const { } void -FunctionDecl::setInstantiationOfMemberFunction(FunctionDecl *FD, +FunctionDecl::setInstantiationOfMemberFunction(ASTContext &C, + FunctionDecl *FD, TemplateSpecializationKind TSK) { assert(TemplateOrSpecialization.isNull() && "Member function is already a specialization"); MemberSpecializationInfo *Info - = new (getASTContext()) MemberSpecializationInfo(FD, TSK); + = new (C) MemberSpecializationInfo(FD, TSK); TemplateOrSpecialization = Info; } @@ -1362,7 +1364,8 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { } void -FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, +FunctionDecl::setFunctionTemplateSpecialization(ASTContext &C, + FunctionTemplateDecl *Template, const TemplateArgumentList *TemplateArgs, void *InsertPos, TemplateSpecializationKind TSK, @@ -1373,7 +1376,7 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, FunctionTemplateSpecializationInfo *Info = TemplateOrSpecialization.dyn_cast(); if (!Info) - Info = new (getASTContext()) FunctionTemplateSpecializationInfo; + Info = new (C) FunctionTemplateSpecializationInfo; Info->Function = this; Info->Template.setPointer(Template); @@ -1400,28 +1403,6 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, } } -void -FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, - unsigned NumTemplateArgs, - const TemplateArgument *TemplateArgs, - TemplateSpecializationKind TSK, - unsigned NumTemplateArgsAsWritten, - TemplateArgumentLoc *TemplateArgsAsWritten, - SourceLocation LAngleLoc, - SourceLocation RAngleLoc, - SourceLocation PointOfInstantiation) { - ASTContext &Ctx = getASTContext(); - TemplateArgumentList *TemplArgs - = new (Ctx) TemplateArgumentList(Ctx, TemplateArgs, NumTemplateArgs); - TemplateArgumentListInfo *TemplArgsInfo - = new (Ctx) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); - for (unsigned i=0; i != NumTemplateArgsAsWritten; ++i) - TemplArgsInfo->addArgument(TemplateArgsAsWritten[i]); - - setFunctionTemplateSpecialization(Template, TemplArgs, /*InsertPos=*/0, TSK, - TemplArgsInfo, PointOfInstantiation); -} - void FunctionDecl::setDependentTemplateSpecialization(ASTContext &Context, const UnresolvedSetImpl &Templates, diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index e69338a773..66321d3ec2 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -92,7 +92,7 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { RedeclarableTemplateDecl *First = getCanonicalDecl(); if (First->CommonOrPrev.isNull()) { - CommonBase *CommonPtr = First->newCommon(); + CommonBase *CommonPtr = First->newCommon(getASTContext()); First->CommonOrPrev = CommonPtr; CommonPtr->Latest = First; } @@ -156,9 +156,10 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C, return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); } -RedeclarableTemplateDecl::CommonBase *FunctionTemplateDecl::newCommon() { - Common *CommonPtr = new (getASTContext()) Common; - getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); +RedeclarableTemplateDecl::CommonBase * +FunctionTemplateDecl::newCommon(ASTContext &C) { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; } @@ -188,9 +189,10 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, return New; } -RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() { - Common *CommonPtr = new (getASTContext()) Common; - getASTContext().AddDeallocation(DeallocateCommon, CommonPtr); +RedeclarableTemplateDecl::CommonBase * +ClassTemplateDecl::newCommon(ASTContext &C) { + Common *CommonPtr = new (C) Common; + C.AddDeallocation(DeallocateCommon, CommonPtr); return CommonPtr; } diff --git a/lib/AST/TemplateName.cpp b/lib/AST/TemplateName.cpp index ef7b315314..439f4e81ad 100644 --- a/lib/AST/TemplateName.cpp +++ b/lib/AST/TemplateName.cpp @@ -44,8 +44,14 @@ TemplateDecl *TemplateName::getAsTemplateDecl() const { bool TemplateName::isDependent() const { if (TemplateDecl *Template = getAsTemplateDecl()) { - return isa(Template) || - Template->getDeclContext()->isDependentContext(); + if (isa(Template)) + return true; + // FIXME: Hack, getDeclContext() can be null if Template is still + // initializing due to PCH reading, so we check it before using it. + // Should probably modify TemplateSpecializationType to allow constructing + // it without the isDependent() checking. + return Template->getDeclContext() && + Template->getDeclContext()->isDependentContext(); } assert(!getAsOverloadedTemplate() && diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 7adbe1220f..653878209f 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -183,8 +183,8 @@ void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { void ASTDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); - TD->IdentifierNamespace = Record[Idx++]; VisitRedeclarable(TD); + TD->IdentifierNamespace = Record[Idx++]; TD->setTagKind((TagDecl::TagKind)Record[Idx++]); TD->setDefinition(Record[Idx++]); TD->setEmbeddedInDeclarator(Record[Idx++]); @@ -234,6 +234,7 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { VisitDeclaratorDecl(FD); + VisitRedeclarable(FD); // FIXME: read DeclarationNameLoc. FD->IdentifierNamespace = Record[Idx++]; @@ -250,7 +251,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FunctionDecl *InstFD = cast(Reader.GetDecl(Record[Idx++])); TemplateSpecializationKind TSK = (TemplateSpecializationKind)Record[Idx++]; SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - FD->setInstantiationOfMemberFunction(InstFD, TSK); + FD->setInstantiationOfMemberFunction(*Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); break; } @@ -279,12 +280,26 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - if (FD->isCanonicalDecl()) // if canonical add to template's set. - FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(), - TemplArgs.data(), TSK, - TemplArgLocs.size(), - TemplArgLocs.data(), - LAngleLoc, RAngleLoc, POI); + if (FD->isCanonicalDecl()) { // if canonical add to template's set. + ASTContext &C = *Reader.getContext(); + TemplateArgumentList *TemplArgList + = new (C) TemplateArgumentList(C, TemplArgs.data(), TemplArgs.size()); + TemplateArgumentListInfo *TemplArgsInfo + = new (C) TemplateArgumentListInfo(LAngleLoc, RAngleLoc); + for (unsigned i=0, e = TemplArgLocs.size(); i != e; ++i) + TemplArgsInfo->addArgument(TemplArgLocs[i]); + + llvm::FoldingSetNodeID ID; + FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(), + TemplArgs.size(), C); + void *InsertPos = 0; + FunctionTemplateSpecializationInfo *PrevFTInfo = + Template->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + (void)PrevFTInfo; + assert(!PrevFTInfo && "Another specialization already inserted!"); + FD->setFunctionTemplateSpecialization(C, Template, TemplArgList, InsertPos, + TSK, TemplArgsInfo, POI); + } break; } case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { @@ -311,7 +326,6 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { // FunctionDecl's body is handled last at ASTDeclReader::Visit, // after everything else is read. - VisitRedeclarable(FD); FD->setStorageClass((StorageClass)Record[Idx++]); FD->setStorageClassAsWritten((StorageClass)Record[Idx++]); FD->setInlineSpecified(Record[Idx++]); @@ -331,7 +345,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { Params.reserve(NumParams); for (unsigned I = 0; I != NumParams; ++I) Params.push_back(cast(Reader.GetDecl(Record[Idx++]))); - FD->setParams(Params.data(), NumParams); + FD->setParams(*Reader.getContext(), Params.data(), NumParams); } void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { @@ -567,13 +581,13 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { void ASTDeclReader::VisitVarDecl(VarDecl *VD) { VisitDeclaratorDecl(VD); + VisitRedeclarable(VD); VD->setStorageClass((StorageClass)Record[Idx++]); VD->setStorageClassAsWritten((StorageClass)Record[Idx++]); VD->setThreadSpecified(Record[Idx++]); VD->setCXXDirectInitializer(Record[Idx++]); VD->setExceptionVariable(Record[Idx++]); VD->setNRVOVariable(Record[Idx++]); - VisitRedeclarable(VD); if (Record[Idx++]) VD->setInit(Reader.ReadExpr(Cursor)); @@ -864,9 +878,10 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { } void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - VisitTemplateDecl(D); + // Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr() + // can be used while this is still initializing. - D->IdentifierNamespace = Record[Idx++]; + assert(D->CommonOrPrev.isNull() && "getCommonPtr was called earlier on this"); RedeclarableTemplateDecl *PrevDecl = cast_or_null(Reader.GetDecl(Record[Idx++])); assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) && @@ -874,6 +889,7 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { if (PrevDecl) D->CommonOrPrev = PrevDecl; if (PrevDecl == 0) { + D->CommonOrPrev = D->newCommon(*Reader.getContext()); if (RedeclarableTemplateDecl *RTD = cast_or_null(Reader.GetDecl(Record[Idx++]))) { assert(RTD->getKind() == D->getKind() && @@ -907,6 +923,9 @@ void ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { assert(LatestDecl->getKind() == D->getKind() && "Latest kind mismatch"); D->getCommonPtr()->Latest = LatestDecl; } + + VisitTemplateDecl(D); + D->IdentifierNamespace = Record[Idx++]; } void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index ce39a1076b..a615c0f9c2 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -163,8 +163,8 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { void ASTDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); - Record.push_back(D->getIdentifierNamespace()); VisitRedeclarable(D); + Record.push_back(D->getIdentifierNamespace()); Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding Record.push_back(D->isDefinition()); Record.push_back(D->isEmbeddedInDeclarator()); @@ -214,6 +214,7 @@ void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { VisitDeclaratorDecl(D); + VisitRedeclarable(D); // FIXME: write DeclarationNameLoc. Record.push_back(D->getIdentifierNamespace()); @@ -281,7 +282,6 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { // FunctionDecl's body is handled last at ASTWriterDecl::Visit, // after everything else is written. - VisitRedeclarable(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->getStorageClassAsWritten()); Record.push_back(D->isInlineSpecified()); @@ -513,13 +513,13 @@ void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { void ASTDeclWriter::VisitVarDecl(VarDecl *D) { VisitDeclaratorDecl(D); + VisitRedeclarable(D); Record.push_back(D->getStorageClass()); // FIXME: stable encoding Record.push_back(D->getStorageClassAsWritten()); Record.push_back(D->isThreadSpecified()); Record.push_back(D->hasCXXDirectInitializer()); Record.push_back(D->isExceptionVariable()); Record.push_back(D->isNRVOVariable()); - VisitRedeclarable(D); Record.push_back(D->getInit() ? 1 : 0); if (D->getInit()) Writer.AddStmt(D->getInit()); @@ -840,9 +840,9 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { } void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { - VisitTemplateDecl(D); + // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that + // getCommonPtr() can be used while this is still initializing. - Record.push_back(D->getIdentifierNamespace()); Writer.AddDeclRef(D->getPreviousDeclaration(), Record); if (D->getPreviousDeclaration() == 0) { // This TemplateDecl owns the CommonPtr; write it. @@ -866,6 +866,9 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { Writer.FirstLatestDecls[First] = D; } } + + VisitTemplateDecl(D); + Record.push_back(D->getIdentifierNamespace()); } void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {