From: Argyrios Kyrtzidis Date: Tue, 20 Jul 2010 13:59:28 +0000 (+0000) Subject: Hide the specializations folding sets of ClassTemplateDecl as an implementation detai... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=cc0b1bc979b650a8a8b34b2032a074fd7724a90d;p=clang Hide the specializations folding sets of ClassTemplateDecl as an implementation detail (InsertPos leaks though) and add methods to its interface for adding/finding specializations. Simplifies its users a bit and we no longer need to replace specializations in the folding set with their redeclarations. We just return the most recent redeclarations. As a bonus, it fixes http://llvm.org/PR7670. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108832 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 135dd3ae78..d2506e97a8 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -997,6 +997,17 @@ public: const PrintingPolicy &Policy, bool Qualified) const; + ClassTemplateSpecializationDecl *getMostRecentDeclaration() { + CXXRecordDecl *Recent + = cast(CXXRecordDecl::getMostRecentDeclaration()); + if (!isa(Recent)) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration()); + Recent = Recent->getPreviousDeclaration(); + } + return cast(Recent); + } + /// \brief Retrieve the template that this specialization specializes. ClassTemplateDecl *getSpecializedTemplate() const; @@ -1242,6 +1253,11 @@ public: static ClassTemplatePartialSpecializationDecl * Create(ASTContext &Context, EmptyShell Empty); + ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() { + return cast( + ClassTemplateSpecializationDecl::getMostRecentDeclaration()); + } + /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { return TemplateParams; @@ -1393,6 +1409,18 @@ protected: /// may implicitly allocate memory for the common pointer. Common *getCommonPtr(); + /// \brief Retrieve the set of specializations of this class template. + llvm::FoldingSet &getSpecializations() { + return getCommonPtr()->Specializations; + } + + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSet & + getPartialSpecializations() { + return getCommonPtr()->PartialSpecializations; + } + ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), @@ -1436,16 +1464,34 @@ public: NamedDecl *Decl, ClassTemplateDecl *PrevDecl); - /// \brief Retrieve the set of specializations of this class template. - llvm::FoldingSet &getSpecializations() { - return getCommonPtr()->Specializations; + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + ClassTemplateSpecializationDecl * + findSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified specialization knowing that it is not already + /// in. InsertPos must be obtained from findSpecialization. + void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) { + getSpecializations().InsertNode(D, InsertPos); } - /// \brief Retrieve the set of partial specializations of this class - /// template. - llvm::FoldingSet & - getPartialSpecializations() { - return getCommonPtr()->PartialSpecializations; + /// \brief Return the partial specialization with the provided arguments if it + /// exists, otherwise return the insertion point. + ClassTemplatePartialSpecializationDecl * + findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified partial specialization knowing that it is not + /// already in. InsertPos must be obtained from findPartialSpecialization. + void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, + void *InsertPos) { + getPartialSpecializations().InsertNode(D, InsertPos); + } + + /// \brief Return the next partial specialization sequence number. + unsigned getNextPartialSpecSequenceNumber() { + return getPartialSpecializations().size(); } /// \brief Retrieve the partial specializations as an ordered list. @@ -1455,12 +1501,24 @@ public: /// \brief Find a class template partial specialization with the given /// type T. /// - /// \brief A dependent type that names a specialization of this class + /// \param T a dependent type that names a specialization of this class /// template. /// /// \returns the class template partial specialization that exactly matches /// the type \p T, or NULL if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); + + /// \brief Find a class template partial specialization which was instantiated + /// from the given member partial specialization. + /// + /// \param D a member class template partial specialization. + /// + /// \returns the class template partial specialization which was instantiated + /// from the given member partial specialization, or NULL if no such partial + /// specialization exists. + ClassTemplatePartialSpecializationDecl * + findPartialSpecInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *D); /// \brief Retrieve the template specialization type of the /// injected-class-name for this class template. diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp index 9e1d79d79d..a75c1c0d58 100644 --- a/lib/AST/DeclTemplate.cpp +++ b/lib/AST/DeclTemplate.cpp @@ -171,6 +171,28 @@ void ClassTemplateDecl::Destroy(ASTContext& C) { Decl::Destroy(C); } +ClassTemplateSpecializationDecl * +ClassTemplateDecl::findSpecialization(const TemplateArgument *Args, + unsigned NumArgs, void *&InsertPos) { + llvm::FoldingSetNodeID ID; + ClassTemplateSpecializationDecl::Profile(ID, Args, NumArgs, getASTContext()); + ClassTemplateSpecializationDecl *D + = getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + return D ? D->getMostRecentDeclaration() : 0; +} + +ClassTemplatePartialSpecializationDecl * +ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args, + unsigned NumArgs, + void *&InsertPos) { + llvm::FoldingSetNodeID ID; + ClassTemplatePartialSpecializationDecl::Profile(ID, Args, NumArgs, + getASTContext()); + ClassTemplatePartialSpecializationDecl *D + = getPartialSpecializations().FindNodeOrInsertPos(ID, InsertPos); + return D ? D->getMostRecentDeclaration() : 0; +} + void ClassTemplateDecl::getPartialSpecializations( llvm::SmallVectorImpl &PS) { llvm::FoldingSet &PartialSpecs @@ -181,7 +203,7 @@ void ClassTemplateDecl::getPartialSpecializations( P = PartialSpecs.begin(), PEnd = PartialSpecs.end(); P != PEnd; ++P) { assert(!PS[P->getSequenceNumber()]); - PS[P->getSequenceNumber()] = &*P; + PS[P->getSequenceNumber()] = P->getMostRecentDeclaration(); } } @@ -194,7 +216,22 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) { PEnd = getPartialSpecializations().end(); P != PEnd; ++P) { if (Context.hasSameType(P->getInjectedSpecializationType(), T)) - return &*P; + return P->getMostRecentDeclaration(); + } + + return 0; +} + +ClassTemplatePartialSpecializationDecl * +ClassTemplateDecl::findPartialSpecInstantiatedFromMember( + ClassTemplatePartialSpecializationDecl *D) { + Decl *DCanon = D->getCanonicalDecl(); + for (llvm::FoldingSet::iterator + P = getPartialSpecializations().begin(), + PEnd = getPartialSpecializations().end(); + P != PEnd; ++P) { + if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) + return P->getMostRecentDeclaration(); } return 0; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 4cb9433589..c8b5338f28 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -1477,14 +1477,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, = dyn_cast(Template)) { // Find the class template specialization declaration that // corresponds to these arguments. - llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *Decl - = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + = ClassTemplate->findSpecialization(Converted.getFlatArguments(), + Converted.flatSize(), InsertPos); if (!Decl) { // This is the first time we have referenced this class template // specialization. Create the canonical declaration and add it to @@ -1495,7 +1491,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name, ClassTemplate->getLocation(), ClassTemplate, Converted, 0); - ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos); + ClassTemplate->AddSpecialization(Decl, InsertPos); Decl->setLexicalDeclContext(CurContext); } @@ -3727,7 +3723,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, // Find the class template (partial) specialization declaration that // corresponds to these arguments. - llvm::FoldingSetNodeID ID; if (isPartialSpecialization) { bool MirrorsPrimaryTemplate; if (CheckClassTemplatePartialSpecializationArgs( @@ -3760,30 +3755,22 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized) << ClassTemplate->getDeclName(); isPartialSpecialization = false; - } else { - // FIXME: Template parameter list matters, too - ClassTemplatePartialSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); } } - - if (!isPartialSpecialization) - ClassTemplateSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); + void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl = 0; if (isPartialSpecialization) + // FIXME: Template parameter list matters, too PrevDecl - = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, - InsertPos); + = ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(), + Converted.flatSize(), + InsertPos); else PrevDecl - = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + = ClassTemplate->findSpecialization(Converted.getFlatArguments(), + Converted.flatSize(), InsertPos); ClassTemplateSpecializationDecl *Specialization = 0; @@ -3821,7 +3808,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, ClassTemplatePartialSpecializationDecl *PrevPartial = cast_or_null(PrevDecl); unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber() - : ClassTemplate->getPartialSpecializations().size(); + : ClassTemplate->getNextPartialSpecSequenceNumber(); ClassTemplatePartialSpecializationDecl *Partial = ClassTemplatePartialSpecializationDecl::Create(Context, Kind, ClassTemplate->getDeclContext(), @@ -3840,12 +3827,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, (TemplateParameterList**) TemplateParameterLists.release()); } - if (PrevPartial) { - ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial); - ClassTemplate->getPartialSpecializations().GetOrInsertNode(Partial); - } else { - ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos); - } + if (!PrevPartial) + ClassTemplate->AddPartialSpecialization(Partial, InsertPos); Specialization = Partial; // If we are providing an explicit specialization of a member class @@ -3902,13 +3885,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, (TemplateParameterList**) TemplateParameterLists.release()); } - if (PrevDecl) { - ClassTemplate->getSpecializations().RemoveNode(PrevDecl); - ClassTemplate->getSpecializations().GetOrInsertNode(Specialization); - } else { - ClassTemplate->getSpecializations().InsertNode(Specialization, - InsertPos); - } + if (!PrevDecl) + ClassTemplate->AddSpecialization(Specialization, InsertPos); CanonType = Context.getTypeDeclType(Specialization); } @@ -4701,14 +4679,10 @@ Sema::ActOnExplicitInstantiation(Scope *S, // Find the class template specialization declaration that // corresponds to these arguments. - llvm::FoldingSetNodeID ID; - ClassTemplateSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); + = ClassTemplate->findSpecialization(Converted.getFlatArguments(), + Converted.flatSize(), InsertPos); TemplateSpecializationKind PrevDecl_TSK = PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared; @@ -4761,15 +4735,9 @@ Sema::ActOnExplicitInstantiation(Scope *S, Converted, PrevDecl); SetNestedNameSpecifier(Specialization, SS); - if (!HasNoEffect) { - if (PrevDecl) { - // Remove the previous declaration from the folding set, since we want - // to introduce a new declaration. - ClassTemplate->getSpecializations().RemoveNode(PrevDecl); - ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos); - } + if (!HasNoEffect && !PrevDecl) { // Insert the new specialization. - ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos); + ClassTemplate->AddSpecialization(Specialization, InsertPos); } } diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 79b5532aef..7e0617568b 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -857,16 +857,7 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl( if (!InstClassTemplate) return 0; - Decl *DCanon = D->getCanonicalDecl(); - for (llvm::FoldingSet::iterator - P = InstClassTemplate->getPartialSpecializations().begin(), - PEnd = InstClassTemplate->getPartialSpecializations().end(); - P != PEnd; ++P) { - if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon) - return &*P; - } - - return 0; + return InstClassTemplate->findPartialSpecInstantiatedFromMember(D); } Decl * @@ -1804,15 +1795,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Figure out where to insert this class template partial specialization // in the member template's set of class template partial specializations. - llvm::FoldingSetNodeID ID; - ClassTemplatePartialSpecializationDecl::Profile(ID, - Converted.getFlatArguments(), - Converted.flatSize(), - SemaRef.Context); void *InsertPos = 0; ClassTemplateSpecializationDecl *PrevDecl - = ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID, - InsertPos); + = ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(), + Converted.flatSize(), InsertPos); // Build the canonical type that describes the converted template // arguments of the class template partial specialization. @@ -1871,7 +1857,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( InstTemplateArgs, CanonType, 0, - ClassTemplate->getPartialSpecializations().size()); + ClassTemplate->getNextPartialSpecSequenceNumber()); // Substitute the nested name specifier, if any. if (SubstQualifier(PartialSpec, InstPartialSpec)) return 0; @@ -1881,8 +1867,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization( // Add this partial specialization to the set of class template partial // specializations. - ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec, - InsertPos); + ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos); return false; } diff --git a/test/PCH/cxx-templates.h b/test/PCH/cxx-templates.h index 8cffa3f10d..42c47f0307 100644 --- a/test/PCH/cxx-templates.h +++ b/test/PCH/cxx-templates.h @@ -103,3 +103,8 @@ class basic_streambuf // PR 7660 template struct S_PR7660 { void g(void (*)(T)); }; template<> void S_PR7660::g(void(*)(int)) {} + +// PR 7670 +template class C_PR7670; +template<> class C_PR7670; +template<> class C_PR7670;