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. llvm-svn: 109754
This commit is contained in:
parent
0bdcb8a239
commit
91b25b7419
|
@ -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,42 +483,221 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Declaration of a template function.
|
||||
class FunctionTemplateDecl : public TemplateDecl {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
/// Declaration of a redeclarable template.
|
||||
class RedeclarableTemplateDecl : public TemplateDecl {
|
||||
|
||||
RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
|
||||
return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// function template.
|
||||
struct Common {
|
||||
Common() : InstantiatedFromMember(0, false) { }
|
||||
struct CommonBase {
|
||||
CommonBase() : InstantiatedFromMember(0, false) { }
|
||||
|
||||
/// \brief The function template specializations for this function
|
||||
/// template, including explicit specializations and instantiations.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
|
||||
|
||||
/// \brief The member function template from which this was most
|
||||
/// \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<FunctionTemplateDecl*, 1, bool> InstantiatedFromMember;
|
||||
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
|
||||
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<Common*, FunctionTemplateDecl*> CommonOrPrev;
|
||||
/// or to the data that is common to all declarations of this template.
|
||||
llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> 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
|
||||
virtual CommonBase *newCommon() = 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:
|
||||
template <class decl_type> friend class RedeclarableTemplate;
|
||||
|
||||
RedeclarableTemplateDecl *getCanonicalDecl() {
|
||||
return getCanonicalDeclImpl();
|
||||
}
|
||||
|
||||
/// \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<RedeclarableTemplateDecl*>(this)->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief Determines whether this template was a specialization of a
|
||||
/// member template.
|
||||
///
|
||||
/// In the following example, the function template \c X<int>::f and the
|
||||
/// member template \c X<int>::Inner are member specializations.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T>
|
||||
/// struct X {
|
||||
/// template<typename U> void f(T, U);
|
||||
/// template<typename U> struct Inner;
|
||||
/// };
|
||||
///
|
||||
/// template<> template<typename T>
|
||||
/// void X<int>::f(int, T);
|
||||
/// template<> template<typename T>
|
||||
/// struct X<int>::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 decl_type>
|
||||
class RedeclarableTemplate {
|
||||
RedeclarableTemplateDecl *thisDecl() {
|
||||
return static_cast<decl_type*>(this);
|
||||
}
|
||||
|
||||
public:
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
decl_type *getPreviousDeclaration() {
|
||||
return static_cast<decl_type*>(thisDecl()->getPreviousDeclarationImpl());
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
const decl_type *getPreviousDeclaration() const {
|
||||
return const_cast<RedeclarableTemplate*>(this)->getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief Set the previous declaration of this function template.
|
||||
void setPreviousDeclaration(decl_type *Prev) {
|
||||
thisDecl()->setPreviousDeclarationImpl(Prev);
|
||||
}
|
||||
|
||||
decl_type *getCanonicalDecl() {
|
||||
return static_cast<decl_type*>(thisDecl()->getCanonicalDeclImpl());
|
||||
}
|
||||
|
||||
const decl_type *getCanonicalDecl() const {
|
||||
return const_cast<RedeclarableTemplate*>(this)->getCanonicalDecl();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the member template that this template was instantiated
|
||||
/// from.
|
||||
///
|
||||
/// This routine will return non-NULL for member templates of
|
||||
/// class templates. For example, given:
|
||||
///
|
||||
/// \code
|
||||
/// template <typename T>
|
||||
/// struct X {
|
||||
/// template <typename U> void f();
|
||||
/// template <typename U> struct A {};
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// X<int>::f<float> is a CXXMethodDecl (whose parent is X<int>, a
|
||||
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
|
||||
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
|
||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
||||
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
|
||||
/// ClassTemplateDecl).
|
||||
///
|
||||
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
|
||||
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
|
||||
/// return X<int>::A<U>, a ClassTemplateDecl (whose parent is again
|
||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
||||
/// X<T>::A<U>, a ClassTemplateDecl (whose parent is X<T>, also a CTD).
|
||||
///
|
||||
/// \returns NULL if this is not an instantiation of a member template.
|
||||
decl_type *getInstantiatedFromMemberTemplate() {
|
||||
return static_cast<decl_type*>(
|
||||
thisDecl()->getInstantiatedFromMemberTemplateImpl());
|
||||
}
|
||||
|
||||
void setInstantiatedFromMemberTemplate(decl_type *TD) {
|
||||
thisDecl()->setInstantiatedFromMemberTemplateImpl(TD);
|
||||
}
|
||||
};
|
||||
|
||||
/// Declaration of a template function.
|
||||
class FunctionTemplateDecl : public RedeclarableTemplateDecl,
|
||||
public RedeclarableTemplate<FunctionTemplateDecl> {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
typedef RedeclarableTemplate<FunctionTemplateDecl> redeclarable_base;
|
||||
|
||||
/// \brief Data that is common to all of the declarations of a given
|
||||
/// function template.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||
return getCommonPtr()->Specializations;
|
||||
struct Common : CommonBase {
|
||||
/// \brief The function template specializations for this function
|
||||
/// template, including explicit specializations and instantiations.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> 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<Common *>(RedeclarableTemplateDecl::getCommonPtr());
|
||||
}
|
||||
|
||||
friend void FunctionDecl::setFunctionTemplateSpecialization(
|
||||
|
@ -527,10 +708,11 @@ protected:
|
|||
const TemplateArgumentListInfo *TemplateArgsAsWritten,
|
||||
SourceLocation PointOfInstantiation);
|
||||
|
||||
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
|
||||
TemplateParameterList *Params, NamedDecl *Decl)
|
||||
: TemplateDecl(FunctionTemplate, DC, L, Name, Params, Decl),
|
||||
CommonOrPrev((Common*)0) { }
|
||||
/// \brief Retrieve the set of function template specializations of this
|
||||
/// function template.
|
||||
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &getSpecializations() {
|
||||
return getCommonPtr()->Specializations;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Get the underlying function declaration of the template.
|
||||
|
@ -543,81 +725,27 @@ public:
|
|||
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.
|
||||
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
||||
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||
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 CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
|
||||
return redeclarable_base::getPreviousDeclaration();
|
||||
}
|
||||
|
||||
/// \brief Set the previous declaration of this function template.
|
||||
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
|
||||
if (Prev)
|
||||
CommonOrPrev = Prev;
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
const FunctionTemplateDecl *getPreviousDeclaration() const {
|
||||
return redeclarable_base::getPreviousDeclaration();
|
||||
}
|
||||
|
||||
virtual FunctionTemplateDecl *getCanonicalDecl();
|
||||
|
||||
/// \brief Retrieve the member function template that this function template
|
||||
/// was instantiated from.
|
||||
///
|
||||
/// This routine will return non-NULL for member function templates of
|
||||
/// class templates. For example, given:
|
||||
///
|
||||
/// \code
|
||||
/// template <typename T>
|
||||
/// struct X {
|
||||
/// template <typename U> void f();
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// X<int>::A<float> is a CXXMethodDecl (whose parent is X<int>, a
|
||||
/// ClassTemplateSpecializationDecl) for which getPrimaryTemplate() will
|
||||
/// return X<int>::f, a FunctionTemplateDecl (whose parent is again
|
||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
||||
/// X<T>::f, a FunctionTemplateDecl (whose parent is X<T>, a
|
||||
/// ClassTemplateDecl).
|
||||
///
|
||||
/// \returns NULL if this is not an instantiation of a member function
|
||||
/// template.
|
||||
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
|
||||
return getCommonPtr()->InstantiatedFromMember.getPointer();
|
||||
}
|
||||
|
||||
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) {
|
||||
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
|
||||
getCommonPtr()->InstantiatedFromMember.setPointer(FTD);
|
||||
}
|
||||
|
||||
/// \brief Determines whether this template was a specialization of a
|
||||
/// member template.
|
||||
///
|
||||
/// In the following example, the function template \c X<int>::f is a
|
||||
/// member specialization.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T>
|
||||
/// struct X {
|
||||
/// template<typename U> void f(T, U);
|
||||
/// };
|
||||
///
|
||||
/// template<> template<typename T>
|
||||
/// void X<int>::f(int, T);
|
||||
/// \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);
|
||||
return redeclarable_base::getInstantiatedFromMemberTemplate();
|
||||
}
|
||||
|
||||
/// Create a template function node.
|
||||
|
@ -1371,15 +1499,16 @@ public:
|
|||
};
|
||||
|
||||
/// Declaration of a class template.
|
||||
class ClassTemplateDecl : public TemplateDecl {
|
||||
class ClassTemplateDecl : public RedeclarableTemplateDecl,
|
||||
public RedeclarableTemplate<ClassTemplateDecl> {
|
||||
static void DeallocateCommon(void *Ptr);
|
||||
|
||||
protected:
|
||||
typedef RedeclarableTemplate<ClassTemplateDecl> 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<ClassTemplateSpecializationDecl> 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<ClassTemplateDecl *, 1, bool> 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<Common*, ClassTemplateDecl*> 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<ClassTemplateSpecializationDecl> &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<Common *>(RedeclarableTemplateDecl::getCommonPtr());
|
||||
}
|
||||
|
||||
public:
|
||||
/// Get the underlying class declarations of the template.
|
||||
|
@ -1432,30 +1550,6 @@ public:
|
|||
return static_cast<CXXRecordDecl *>(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<ClassTemplateDecl*>();
|
||||
}
|
||||
|
||||
/// \brief Retrieve the previous declaration of this function template, or
|
||||
/// NULL if no such declaration exists.
|
||||
ClassTemplateDecl *getPreviousDeclaration() {
|
||||
return CommonOrPrev.dyn_cast<ClassTemplateDecl*>();
|
||||
}
|
||||
|
||||
/// \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<ClassTemplateDecl*>(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 <typename T>
|
||||
/// struct X {
|
||||
/// template <typename U> struct A {};
|
||||
/// };
|
||||
/// \endcode
|
||||
///
|
||||
/// X<int>::A<float> is a ClassTemplateSpecializationDecl (whose parent
|
||||
/// is X<int>, also a CTSD) for which getSpecializedTemplate() will
|
||||
/// return X<int>::A<U>, a TemplateClassDecl (whose parent is again
|
||||
/// X<int>) for which getInstantiatedFromMemberTemplate() will return
|
||||
/// X<T>::A<U>, a TemplateClassDecl (whose parent is X<T>, 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<int>::Inner is a
|
||||
/// member specialization.
|
||||
///
|
||||
/// \code
|
||||
/// template<typename T>
|
||||
/// struct X {
|
||||
/// template<typename U> struct Inner;
|
||||
/// };
|
||||
///
|
||||
/// template<> template<typename T>
|
||||
/// struct X<int>::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; }
|
||||
|
|
|
@ -43,8 +43,9 @@ def Named : Decl<1>;
|
|||
def ParmVar : DDecl<Var>;
|
||||
def NonTypeTemplateParm : DDecl<Var>;
|
||||
def Template : DDecl<Named, 1>;
|
||||
def FunctionTemplate : DDecl<Template>;
|
||||
def ClassTemplate : DDecl<Template>;
|
||||
def RedeclarableTemplate : DDecl<Template, 1>;
|
||||
def FunctionTemplate : DDecl<RedeclarableTemplate>;
|
||||
def ClassTemplate : DDecl<RedeclarableTemplate>;
|
||||
def TemplateTemplateParm : DDecl<Template>;
|
||||
def Using : DDecl<Named>;
|
||||
def UsingShadow : DDecl<Named>;
|
||||
|
|
|
@ -83,6 +83,29 @@ unsigned TemplateParameterList::getDepth() const {
|
|||
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// RedeclarableTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
|
||||
// Find the first declaration of this function template.
|
||||
RedeclarableTemplateDecl *First = getCanonicalDecl();
|
||||
|
||||
if (First->CommonOrPrev.isNull()) {
|
||||
CommonBase *CommonPtr = First->newCommon();
|
||||
First->CommonOrPrev = CommonPtr;
|
||||
}
|
||||
return First->CommonOrPrev.get<CommonBase*>();
|
||||
}
|
||||
|
||||
|
||||
RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
|
||||
RedeclarableTemplateDecl *Tmpl = this;
|
||||
while (Tmpl->getPreviousDeclaration())
|
||||
Tmpl = Tmpl->getPreviousDeclaration();
|
||||
return Tmpl;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// FunctionTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -100,6 +123,12 @@ 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);
|
||||
return CommonPtr;
|
||||
}
|
||||
|
||||
FunctionDecl *
|
||||
FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
||||
unsigned NumArgs, void *&InsertPos) {
|
||||
|
@ -110,27 +139,6 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
|||
return Info ? Info->Function->getMostRecentDeclaration() : 0;
|
||||
}
|
||||
|
||||
FunctionTemplateDecl *FunctionTemplateDecl::getCanonicalDecl() {
|
||||
FunctionTemplateDecl *FunTmpl = this;
|
||||
while (FunTmpl->getPreviousDeclaration())
|
||||
FunTmpl = FunTmpl->getPreviousDeclaration();
|
||||
return FunTmpl;
|
||||
}
|
||||
|
||||
FunctionTemplateDecl::Common *FunctionTemplateDecl::getCommonPtr() {
|
||||
// Find the first declaration of this function template.
|
||||
FunctionTemplateDecl *First = this;
|
||||
while (First->getPreviousDeclaration())
|
||||
First = First->getPreviousDeclaration();
|
||||
|
||||
if (First->CommonOrPrev.isNull()) {
|
||||
Common *CommonPtr = new (getASTContext()) Common;
|
||||
getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
|
||||
First->CommonOrPrev = CommonPtr;
|
||||
}
|
||||
return First->CommonOrPrev.get<Common*>();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// ClassTemplateDecl Implementation
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -139,13 +147,6 @@ void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
|
|||
static_cast<Common *>(Ptr)->~Common();
|
||||
}
|
||||
|
||||
ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
|
||||
ClassTemplateDecl *Template = this;
|
||||
while (Template->getPreviousDeclaration())
|
||||
Template = Template->getPreviousDeclaration();
|
||||
return Template;
|
||||
}
|
||||
|
||||
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
||||
DeclContext *DC,
|
||||
SourceLocation L,
|
||||
|
@ -158,6 +159,12 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
|
|||
return New;
|
||||
}
|
||||
|
||||
RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() {
|
||||
Common *CommonPtr = new (getASTContext()) Common;
|
||||
getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
|
||||
return CommonPtr;
|
||||
}
|
||||
|
||||
ClassTemplateSpecializationDecl *
|
||||
ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
|
||||
unsigned NumArgs, void *&InsertPos) {
|
||||
|
@ -263,20 +270,6 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
|
|||
return CommonPtr->InjectedClassNameType;
|
||||
}
|
||||
|
||||
ClassTemplateDecl::Common *ClassTemplateDecl::getCommonPtr() {
|
||||
// Find the first declaration of this function template.
|
||||
ClassTemplateDecl *First = this;
|
||||
while (First->getPreviousDeclaration())
|
||||
First = First->getPreviousDeclaration();
|
||||
|
||||
if (First->CommonOrPrev.isNull()) {
|
||||
Common *CommonPtr = new (getASTContext()) Common;
|
||||
getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
|
||||
First->CommonOrPrev = CommonPtr;
|
||||
}
|
||||
return First->CommonOrPrev.get<Common*>();
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// TemplateTypeParm Allocation/Deallocation Method Implementations
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -78,6 +78,7 @@ namespace clang {
|
|||
void VisitParmVarDecl(ParmVarDecl *PD);
|
||||
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
||||
void VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
||||
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
|
||||
|
@ -895,14 +896,32 @@ void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
|
|||
D->init(TemplatedDecl, TemplateParams);
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
|
||||
D->IdentifierNamespace = Record[Idx++];
|
||||
ClassTemplateDecl *PrevDecl =
|
||||
cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
|
||||
D->setPreviousDeclaration(PrevDecl);
|
||||
RedeclarableTemplateDecl *PrevDecl =
|
||||
cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
|
||||
assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) &&
|
||||
"PrevDecl kind mismatch");
|
||||
if (PrevDecl)
|
||||
D->CommonOrPrev = PrevDecl;
|
||||
if (PrevDecl == 0) {
|
||||
if (RedeclarableTemplateDecl *RTD
|
||||
= cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
|
||||
assert(RTD->getKind() == D->getKind() &&
|
||||
"InstantiatedFromMemberTemplate kind mismatch");
|
||||
D->setInstantiatedFromMemberTemplateImpl(RTD);
|
||||
if (Record[Idx++])
|
||||
D->setMemberSpecialization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
if (D->getPreviousDeclaration() == 0) {
|
||||
// This ClassTemplateDecl owns a CommonPtr; read it.
|
||||
|
||||
// FoldingSets are filled in VisitClassTemplateSpecializationDecl.
|
||||
|
@ -916,13 +935,6 @@ void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
|||
Reader.GetDecl(Record[Idx++]));
|
||||
|
||||
// InjectedClassNameType is computed.
|
||||
|
||||
if (ClassTemplateDecl *CTD
|
||||
= cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
|
||||
D->setInstantiatedFromMemberTemplate(CTD);
|
||||
if (Record[Idx++])
|
||||
D->setMemberSpecialization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -993,13 +1005,9 @@ void PCHDeclReader::VisitClassTemplatePartialSpecializationDecl(
|
|||
}
|
||||
|
||||
void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
D->IdentifierNamespace = Record[Idx++];
|
||||
FunctionTemplateDecl *PrevDecl =
|
||||
cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
|
||||
D->setPreviousDeclaration(PrevDecl);
|
||||
if (PrevDecl == 0) {
|
||||
if (D->getPreviousDeclaration() == 0) {
|
||||
// This FunctionTemplateDecl owns a CommonPtr; read it.
|
||||
|
||||
// Read the function specialization declarations.
|
||||
|
@ -1008,13 +1016,6 @@ void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
|||
unsigned NumSpecs = Record[Idx++];
|
||||
while (NumSpecs--)
|
||||
Reader.GetDecl(Record[Idx++]);
|
||||
|
||||
if (FunctionTemplateDecl *CTD
|
||||
= cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
|
||||
D->setInstantiatedFromMemberTemplate(CTD);
|
||||
if (Record[Idx++])
|
||||
D->setMemberSpecialization();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ namespace clang {
|
|||
void VisitParmVarDecl(ParmVarDecl *D);
|
||||
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
|
||||
void VisitTemplateDecl(TemplateDecl *D);
|
||||
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
|
||||
void VisitClassTemplateDecl(ClassTemplateDecl *D);
|
||||
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
|
||||
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
|
||||
|
@ -839,15 +840,25 @@ void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
|
|||
Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
|
||||
}
|
||||
|
||||
void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
|
||||
Record.push_back(D->getIdentifierNamespace());
|
||||
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
||||
if (D->getPreviousDeclaration() == 0) {
|
||||
// This ClassTemplateDecl owns the CommonPtr; write it.
|
||||
// This TemplateDecl owns the CommonPtr; write it.
|
||||
assert(D->isCanonicalDecl());
|
||||
|
||||
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
||||
if (D->getInstantiatedFromMemberTemplate())
|
||||
Record.push_back(D->isMemberSpecialization());
|
||||
}
|
||||
}
|
||||
|
||||
void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
if (D->getPreviousDeclaration() == 0) {
|
||||
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
|
||||
CTSDSetTy &CTSDSet = D->getSpecializations();
|
||||
Record.push_back(CTSDSet.size());
|
||||
|
@ -865,10 +876,6 @@ void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
|
|||
}
|
||||
|
||||
// InjectedClassNameType is computed, no need to write it.
|
||||
|
||||
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
||||
if (D->getInstantiatedFromMemberTemplate())
|
||||
Record.push_back(D->isMemberSpecialization());
|
||||
}
|
||||
Code = pch::DECL_CLASS_TEMPLATE;
|
||||
}
|
||||
|
@ -929,10 +936,8 @@ void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
|
|||
}
|
||||
|
||||
void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
||||
VisitTemplateDecl(D);
|
||||
VisitRedeclarableTemplateDecl(D);
|
||||
|
||||
Record.push_back(D->getIdentifierNamespace());
|
||||
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
|
||||
if (D->getPreviousDeclaration() == 0) {
|
||||
// This FunctionTemplateDecl owns the CommonPtr; write it.
|
||||
|
||||
|
@ -945,10 +950,6 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
|
|||
"Expected only canonical decls in set");
|
||||
Writer.AddDeclRef(I->Function, Record);
|
||||
}
|
||||
|
||||
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
|
||||
if (D->getInstantiatedFromMemberTemplate())
|
||||
Record.push_back(D->isMemberSpecialization());
|
||||
}
|
||||
Code = pch::DECL_FUNCTION_TEMPLATE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue