From dde579056237504c1ff12237ef81ceda4a4fe1f5 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 20 Jul 2010 13:59:58 +0000 Subject: [PATCH] Hide FunctionTemplateDecl's specializations folding set as implementation detail and introduce FunctionTemplateDecl::findSpecialization. Redeclarations of specializations will not cause the previous decl to be removed from the set, the set will keep the canonical decl. findSpecialization will return the most recent redeclaration. llvm-svn: 108834 --- clang/include/clang/AST/DeclTemplate.h | 23 +++++++++++---- clang/lib/AST/Decl.cpp | 13 +++++---- clang/lib/AST/DeclTemplate.cpp | 10 +++++++ clang/lib/Frontend/PCHReaderDecl.cpp | 11 ++++---- clang/lib/Frontend/PCHWriterDecl.cpp | 5 +++- .../lib/Sema/SemaTemplateInstantiateDecl.cpp | 28 +++++++------------ 6 files changed, 55 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h index d2506e97a84d..f6421736cd92 100644 --- a/clang/include/clang/AST/DeclTemplate.h +++ b/clang/include/clang/AST/DeclTemplate.h @@ -522,6 +522,20 @@ protected: /// may implicitly allocate memory for the common pointer. Common *getCommonPtr(); + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet &getSpecializations() { + return getCommonPtr()->Specializations; + } + + friend void FunctionDecl::setFunctionTemplateSpecialization( + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), @@ -535,11 +549,10 @@ public: return static_cast(TemplatedDecl); } - /// \brief Retrieve the set of function template specializations of this - /// function template. - llvm::FoldingSet &getSpecializations() { - return getCommonPtr()->Specializations; - } + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + FunctionDecl *findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos); /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 149938fc5c86..e695310c3734 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1400,14 +1400,15 @@ FunctionDecl::setFunctionTemplateSpecialization(FunctionTemplateDecl *Template, if (InsertPos) Template->getSpecializations().InsertNode(Info, InsertPos); else { - // Try to insert the new node. If there is an existing node, remove it - // first. + // Try to insert the new node. If there is an existing node, leave it, the + // set will contain the canonical decls while + // FunctionTemplateDecl::findSpecialization will return + // the most recent redeclarations. FunctionTemplateSpecializationInfo *Existing = Template->getSpecializations().GetOrInsertNode(Info); - if (Existing) { - Template->getSpecializations().RemoveNode(Existing); - Template->getSpecializations().GetOrInsertNode(Info); - } + (void)Existing; + assert((!Existing || Existing->Function->isCanonicalDecl()) && + "Set is supposed to only contain canonical decls"); } } diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp index a75c1c0d5826..f308d71d5f69 100644 --- a/clang/lib/AST/DeclTemplate.cpp +++ b/clang/lib/AST/DeclTemplate.cpp @@ -119,6 +119,16 @@ void FunctionTemplateDecl::Destroy(ASTContext &C) { Decl::Destroy(C); } +FunctionDecl * +FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos) { + llvm::FoldingSetNodeID ID; + FunctionTemplateSpecializationInfo::Profile(ID,Args,NumArgs, getASTContext()); + FunctionTemplateSpecializationInfo *Info + = getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + return Info ? Info->Function->getMostRecentDeclaration() : 0; +} + FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() { FunctionTemplateDecl *FunTmpl = this; while (FunTmpl->getPreviousDeclaration()) diff --git a/clang/lib/Frontend/PCHReaderDecl.cpp b/clang/lib/Frontend/PCHReaderDecl.cpp index 5b41280138fb..e021d3cabab6 100644 --- a/clang/lib/Frontend/PCHReaderDecl.cpp +++ b/clang/lib/Frontend/PCHReaderDecl.cpp @@ -254,11 +254,12 @@ void PCHDeclReader::VisitFunctionDecl(FunctionDecl *FD) { SourceLocation POI = Reader.ReadSourceLocation(Record, Idx); - 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. + FD->setFunctionTemplateSpecialization(Template, TemplArgs.size(), + TemplArgs.data(), TSK, + TemplArgLocs.size(), + TemplArgLocs.data(), + LAngleLoc, RAngleLoc, POI); break; } case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { diff --git a/clang/lib/Frontend/PCHWriterDecl.cpp b/clang/lib/Frontend/PCHWriterDecl.cpp index 5d6a6d267e95..eb7c52ae95b3 100644 --- a/clang/lib/Frontend/PCHWriterDecl.cpp +++ b/clang/lib/Frontend/PCHWriterDecl.cpp @@ -929,8 +929,11 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { Record.push_back(D->getSpecializations().size()); for (llvm::FoldingSet::iterator I = D->getSpecializations().begin(), - E = D->getSpecializations().end() ; I != E; ++I) + E = D->getSpecializations().end() ; I != E; ++I) { + assert(I->Function->isCanonicalDecl() && + "Expected only canonical decls in set"); Writer.AddDeclRef(I->Function, Record); + } Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); if (D->getInstantiatedFromMemberTemplate()) diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 7e0617568bf7..4209fd7a14b2 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -968,20 +968,16 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); void *InsertPos = 0; if (FunctionTemplate && !TemplateParams) { - llvm::FoldingSetNodeID ID; std::pair Innermost = TemplateArgs.getInnermost(); - FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first, - Innermost.second, - SemaRef.Context); - FunctionTemplateSpecializationInfo *Info - = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, - InsertPos); + FunctionDecl *SpecFunc + = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, + InsertPos); // If we already have a function template specialization, return it. - if (Info) - return Info->Function; + if (SpecFunc) + return SpecFunc; } bool isFriend; @@ -1222,20 +1218,16 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, // We are creating a function template specialization from a function // template. Check whether there is already a function template // specialization for this particular set of template arguments. - llvm::FoldingSetNodeID ID; std::pair Innermost = TemplateArgs.getInnermost(); - FunctionTemplateSpecializationInfo::Profile(ID, Innermost.first, - Innermost.second, - SemaRef.Context); - FunctionTemplateSpecializationInfo *Info - = FunctionTemplate->getSpecializations().FindNodeOrInsertPos(ID, - InsertPos); + FunctionDecl *SpecFunc + = FunctionTemplate->findSpecialization(Innermost.first, Innermost.second, + InsertPos); // If we already have a function template specialization, return it. - if (Info) - return Info->Function; + if (SpecFunc) + return SpecFunc; } bool isFriend;