From: Peter Collingbourne Date: Thu, 29 Jul 2010 16:11:51 +0000 (+0000) Subject: Refactor redeclarable template declarations X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9eabebafc165a67812eacc184806e7bf34c5f0a5;p=clang Refactor redeclarable template declarations This patch refactors much of the common code in ClassTemplateDecl and FunctionTemplateDecl into a common base class RedeclarableTemplateDecl together with support functions in a template class RedeclarableTemplate. The patch also includes similar refactoring for these classes' PCH reader and writer implementations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109754 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 4084fccbdb..3c678cc3ff 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -23,6 +23,7 @@ namespace clang { class TemplateParameterList; class TemplateDecl; +class RedeclarableTemplateDecl; class FunctionTemplateDecl; class ClassTemplateDecl; class ClassTemplatePartialSpecializationDecl; @@ -259,6 +260,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const TemplateDecl *D) { return true; } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } @@ -481,145 +483,271 @@ public: } }; -/// Declaration of a template function. -class FunctionTemplateDecl : public TemplateDecl { - static void DeallocateCommon(void *Ptr); - -protected: - /// \brief Data that is common to all of the declarations of a given - /// function template. - struct Common { - Common() : InstantiatedFromMember(0, false) { } +/// Declaration of a redeclarable template. +class RedeclarableTemplateDecl : public TemplateDecl { - /// \brief The function template specializations for this function - /// template, including explicit specializations and instantiations. - llvm::FoldingSet Specializations; + RedeclarableTemplateDecl *getPreviousDeclarationImpl() { + return CommonOrPrev.dyn_cast(); + } + + RedeclarableTemplateDecl *getCanonicalDeclImpl(); + + void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev) { + if (Prev) + CommonOrPrev = Prev; + } + + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() { + return getCommonPtr()->InstantiatedFromMember.getPointer(); + } + + void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) { + assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); + getCommonPtr()->InstantiatedFromMember.setPointer(TD); + } - /// \brief The member function template from which this was most +protected: + struct CommonBase { + CommonBase() : InstantiatedFromMember(0, false) { } + + /// \brief The template from which this was most /// directly instantiated (or null). /// - /// The boolean value indicates whether this member function template + /// The boolean value indicates whether this template /// was explicitly specialized. - llvm::PointerIntPair InstantiatedFromMember; + llvm::PointerIntPair + InstantiatedFromMember; }; /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this function - /// template. - llvm::PointerUnion CommonOrPrev; + /// or to the data that is common to all declarations of this template. + llvm::PointerUnion CommonOrPrev; - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same function template. Calling this routine - /// may implicitly allocate memory for the common pointer. - Common *getCommonPtr(); + /// \brief Retrieves the "common" pointer shared by all (re-)declarations of + /// the same template. Calling this routine may implicitly allocate memory + /// for the common pointer. + CommonBase *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); + virtual CommonBase *newCommon() = 0; - FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, - TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + // Construct a template decl with name, parameters, and templated element. + RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, TemplateParameterList *Params, + NamedDecl *Decl) + : TemplateDecl(DK, DC, L, Name, Params, Decl), + CommonOrPrev((CommonBase*)0) { } public: - /// Get the underlying function declaration of the template. - FunctionDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl); + template friend class RedeclarableTemplate; + + RedeclarableTemplateDecl *getCanonicalDecl() { + return getCanonicalDeclImpl(); } - /// \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 template, or + /// NULL if no such declaration exists. + RedeclarableTemplateDecl *getPreviousDeclaration() { + return getPreviousDeclarationImpl(); + } + /// \brief Retrieve the previous declaration of this template, or + /// NULL if no such declaration exists. + const RedeclarableTemplateDecl *getPreviousDeclaration() const { + return + const_cast(this)->getPreviousDeclaration(); + } + + /// \brief Determines whether this template was a specialization of a + /// member template. + /// + /// In the following example, the function template \c X::f and the + /// member template \c X::Inner are member specializations. + /// + /// \code + /// template + /// struct X { + /// template void f(T, U); + /// template struct Inner; + /// }; + /// + /// template<> template + /// void X::f(int, T); + /// template<> template + /// struct X::Inner { /* ... */ }; + /// \endcode + bool isMemberSpecialization() { + return getCommonPtr()->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + assert(getCommonPtr()->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + getCommonPtr()->InstantiatedFromMember.setInt(true); + } + + /// \brief Retrieve the previous declaration of this template, or + /// NULL if no such declaration exists. + RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { + return getInstantiatedFromMemberTemplateImpl(); + } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const RedeclarableTemplateDecl *D) { return true; } + static bool classof(const FunctionTemplateDecl *D) { return true; } + static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; + } + + friend class PCHDeclReader; +}; + +template +class RedeclarableTemplate { + RedeclarableTemplateDecl *thisDecl() { + return static_cast(this); + } + +public: /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - const FunctionTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast(); + decl_type *getPreviousDeclaration() { + return static_cast(thisDecl()->getPreviousDeclarationImpl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. - FunctionTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast(); + const decl_type *getPreviousDeclaration() const { + return const_cast(this)->getPreviousDeclaration(); } /// \brief Set the previous declaration of this function template. - void setPreviousDeclaration(FunctionTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; + void setPreviousDeclaration(decl_type *Prev) { + thisDecl()->setPreviousDeclarationImpl(Prev); + } + + decl_type *getCanonicalDecl() { + return static_cast(thisDecl()->getCanonicalDeclImpl()); } - virtual FunctionTemplateDecl *getCanonicalDecl(); + const decl_type *getCanonicalDecl() const { + return const_cast(this)->getCanonicalDecl(); + } - /// \brief Retrieve the member function template that this function template - /// was instantiated from. + /// \brief Retrieve the member template that this template was instantiated + /// from. /// - /// This routine will return non-NULL for member function templates of + /// This routine will return non-NULL for member templates of /// class templates. For example, given: /// /// \code /// template /// struct X { /// template void f(); + /// template struct A {}; /// }; /// \endcode /// - /// X::A is a CXXMethodDecl (whose parent is X, a + /// X::f is a CXXMethodDecl (whose parent is X, a /// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will /// return X::f, a FunctionTemplateDecl (whose parent is again /// X) for which getInstantiatedFromMemberTemplate() will return /// X::f, a FunctionTemplateDecl (whose parent is X, a /// ClassTemplateDecl). /// - /// \returns NULL if this is not an instantiation of a member function - /// template. - FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); + /// X::A is a ClassTemplateSpecializationDecl (whose parent + /// is X, also a CTSD) for which getSpecializedTemplate() will + /// return X::A, a ClassTemplateDecl (whose parent is again + /// X) for which getInstantiatedFromMemberTemplate() will return + /// X::A, a ClassTemplateDecl (whose parent is X, also a CTD). + /// + /// \returns NULL if this is not an instantiation of a member template. + decl_type *getInstantiatedFromMemberTemplate() { + return static_cast( + thisDecl()->getInstantiatedFromMemberTemplateImpl()); } - void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(FTD); + void setInstantiatedFromMemberTemplate(decl_type *TD) { + thisDecl()->setInstantiatedFromMemberTemplateImpl(TD); } +}; - /// \brief Determines whether this template was a specialization of a - /// member template. - /// - /// In the following example, the function template \c X::f is a - /// member specialization. - /// - /// \code - /// template - /// struct X { - /// template void f(T, U); - /// }; - /// - /// template<> template - /// void X::f(int, T); - /// \endcode - bool isMemberSpecialization() { - return getCommonPtr()->InstantiatedFromMember.getInt(); +/// Declaration of a template function. +class FunctionTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate { + static void DeallocateCommon(void *Ptr); + +protected: + typedef RedeclarableTemplate redeclarable_base; + + /// \brief Data that is common to all of the declarations of a given + /// function template. + struct Common : CommonBase { + /// \brief The function template specializations for this function + /// template, including explicit specializations and instantiations. + llvm::FoldingSet Specializations; + }; + + FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast(RedeclarableTemplateDecl::getCommonPtr()); } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); + + friend void FunctionDecl::setFunctionTemplateSpecialization( + FunctionTemplateDecl *Template, + const TemplateArgumentList *TemplateArgs, + void *InsertPos, + TemplateSpecializationKind TSK, + const TemplateArgumentListInfo *TemplateArgsAsWritten, + SourceLocation PointOfInstantiation); + + /// \brief Retrieve the set of function template specializations of this + /// function template. + llvm::FoldingSet &getSpecializations() { + return getCommonPtr()->Specializations; } +public: + /// Get the underlying function declaration of the template. + FunctionDecl *getTemplatedDecl() const { + return static_cast(TemplatedDecl); + } + + /// \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); + + FunctionTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const FunctionTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + FunctionTemplateDecl *getPreviousDeclaration() { + return redeclarable_base::getPreviousDeclaration(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const FunctionTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); + } + + FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); + } + /// Create a template function node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1371,15 +1499,16 @@ public: }; /// Declaration of a class template. -class ClassTemplateDecl : public TemplateDecl { +class ClassTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate { static void DeallocateCommon(void *Ptr); protected: + typedef RedeclarableTemplate redeclarable_base; + /// \brief Data that is common to all of the declarations of a given /// class template. - struct Common { - Common() : InstantiatedFromMember(0, 0) {} - + struct Common : CommonBase { /// \brief The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSet Specializations; @@ -1391,24 +1520,8 @@ protected: /// \brief The injected-class-name type for this class template. QualType InjectedClassNameType; - - /// \brief The templated member class from which this was most - /// directly instantiated (or null). - /// - /// The boolean value indicates whether this member class template - /// was explicitly specialized. - llvm::PointerIntPair InstantiatedFromMember; }; - /// \brief A pointer to the previous declaration (if this is a redeclaration) - /// or to the data that is common to all declarations of this class template. - llvm::PointerUnion CommonOrPrev; - - /// \brief Retrieves the "common" pointer shared by all - /// (re-)declarations of the same class template. Calling this routine - /// 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; @@ -1423,8 +1536,13 @@ protected: ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl) - : TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), - CommonOrPrev((Common*)0) { } + : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(); + + Common *getCommonPtr() { + return static_cast(RedeclarableTemplateDecl::getCommonPtr()); + } public: /// Get the underlying class declarations of the template. @@ -1432,30 +1550,6 @@ public: return static_cast(TemplatedDecl); } - /// \brief Retrieve the previous declaration of this class template, or - /// NULL if no such declaration exists. - const ClassTemplateDecl *getPreviousDeclaration() const { - return CommonOrPrev.dyn_cast(); - } - - /// \brief Retrieve the previous declaration of this function template, or - /// NULL if no such declaration exists. - ClassTemplateDecl *getPreviousDeclaration() { - return CommonOrPrev.dyn_cast(); - } - - /// \brief Set the previous declaration of this class template. - void setPreviousDeclaration(ClassTemplateDecl *Prev) { - if (Prev) - CommonOrPrev = Prev; - } - - virtual ClassTemplateDecl *getCanonicalDecl(); - - const ClassTemplateDecl *getCanonicalDecl() const { - return const_cast(this)->getCanonicalDecl(); - } - /// Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, @@ -1476,6 +1570,29 @@ public: getSpecializations().InsertNode(D, InsertPos); } + ClassTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const ClassTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this class template, or + /// NULL if no such declaration exists. + ClassTemplateDecl *getPreviousDeclaration() { + return redeclarable_base::getPreviousDeclaration(); + } + + /// \brief Retrieve the previous declaration of this class template, or + /// NULL if no such declaration exists. + const ClassTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); + } + + ClassTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); + } + /// \brief Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. ClassTemplatePartialSpecializationDecl * @@ -1536,61 +1653,6 @@ public: /// \endcode QualType getInjectedClassNameSpecialization(); - /// \brief Retrieve the member class template that this class template was - /// derived from. - /// - /// This routine will return non-NULL for templated member classes of - /// class templates. For example, given: - /// - /// \code - /// template - /// struct X { - /// template struct A {}; - /// }; - /// \endcode - /// - /// X::A is a ClassTemplateSpecializationDecl (whose parent - /// is X, also a CTSD) for which getSpecializedTemplate() will - /// return X::A, a TemplateClassDecl (whose parent is again - /// X) for which getInstantiatedFromMemberTemplate() will return - /// X::A, a TemplateClassDecl (whose parent is X, also a TCD). - /// - /// \returns null if this is not an instantiation of a member class template. - ClassTemplateDecl *getInstantiatedFromMemberTemplate() { - return getCommonPtr()->InstantiatedFromMember.getPointer(); - } - - void setInstantiatedFromMemberTemplate(ClassTemplateDecl *CTD) { - assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); - getCommonPtr()->InstantiatedFromMember.setPointer(CTD); - } - - /// \brief Determines whether this template was a specialization of a - /// member template. - /// - /// In the following example, the member template \c X::Inner is a - /// member specialization. - /// - /// \code - /// template - /// struct X { - /// template struct Inner; - /// }; - /// - /// template<> template - /// struct X::Inner { /* ... */ }; - /// \endcode - bool isMemberSpecialization() { - return getCommonPtr()->InstantiatedFromMember.getInt(); - } - - /// \brief Note that this member template is a specialization. - void setMemberSpecialization() { - assert(getCommonPtr()->InstantiatedFromMember.getPointer() && - "Only member templates can be member template specializations"); - getCommonPtr()->InstantiatedFromMember.setInt(true); - } - // Implement isa/cast/dyncast support static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const ClassTemplateDecl *D) { return true; } diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 203fb451e3..e2f93e02c5 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -43,8 +43,9 @@ def Named : Decl<1>; def ParmVar : DDecl; def NonTypeTemplateParm : DDecl; def Template : DDecl; - def FunctionTemplate : DDecl