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:
Peter Collingbourne 2010-07-29 16:11:51 +00:00
parent 0bdcb8a239
commit 91b25b7419
5 changed files with 341 additions and 283 deletions

View File

@ -23,6 +23,7 @@ namespace clang {
class TemplateParameterList; class TemplateParameterList;
class TemplateDecl; class TemplateDecl;
class RedeclarableTemplateDecl;
class FunctionTemplateDecl; class FunctionTemplateDecl;
class ClassTemplateDecl; class ClassTemplateDecl;
class ClassTemplatePartialSpecializationDecl; class ClassTemplatePartialSpecializationDecl;
@ -259,6 +260,7 @@ public:
// Implement isa/cast/dyncast/etc. // Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const TemplateDecl *D) { return true; } 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 FunctionTemplateDecl *D) { return true; }
static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; }
static bool classof(const TemplateTemplateParmDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; }
@ -481,133 +483,97 @@ public:
} }
}; };
/// Declaration of a template function. /// Declaration of a redeclarable template.
class FunctionTemplateDecl : public TemplateDecl { class RedeclarableTemplateDecl : 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) { }
/// \brief The function template specializations for this function RedeclarableTemplateDecl *getPreviousDeclarationImpl() {
/// template, including explicit specializations and instantiations. return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>();
llvm::FoldingSet<FunctionTemplateSpecializationInfo> Specializations;
/// \brief The member function template from which this was most
/// directly instantiated (or null).
///
/// The boolean value indicates whether this member function template
/// was explicitly specialized.
llvm::PointerIntPair<FunctionTemplateDecl*, 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;
/// \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 Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSet<FunctionTemplateSpecializationInfo> &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),
CommonOrPrev((Common*)0) { }
public:
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(TemplatedDecl);
} }
/// \brief Return the specialization with the provided arguments if it exists, RedeclarableTemplateDecl *getCanonicalDeclImpl();
/// otherwise return the insertion point.
FunctionDecl *findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos);
/// \brief Retrieve the previous declaration of this function template, or void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev) {
/// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDeclaration() {
return CommonOrPrev.dyn_cast<FunctionTemplateDecl*>();
}
/// \brief Set the previous declaration of this function template.
void setPreviousDeclaration(FunctionTemplateDecl *Prev) {
if (Prev) if (Prev)
CommonOrPrev = Prev; CommonOrPrev = Prev;
} }
virtual FunctionTemplateDecl *getCanonicalDecl(); RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
/// \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(); return getCommonPtr()->InstantiatedFromMember.getPointer();
} }
void setInstantiatedFromMemberTemplate(FunctionTemplateDecl *FTD) { void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer()); assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(FTD); getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}
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 template
/// was explicitly specialized.
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 template.
llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev;
/// \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();
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 /// \brief Determines whether this template was a specialization of a
/// member template. /// member template.
/// ///
/// In the following example, the function template \c X<int>::f is a /// In the following example, the function template \c X<int>::f and the
/// member specialization. /// member template \c X<int>::Inner are member specializations.
/// ///
/// \code /// \code
/// template<typename T> /// template<typename T>
/// struct X { /// struct X {
/// template<typename U> void f(T, U); /// template<typename U> void f(T, U);
/// template<typename U> struct Inner;
/// }; /// };
/// ///
/// template<> template<typename T> /// template<> template<typename T>
/// void X<int>::f(int, T); /// void X<int>::f(int, T);
/// template<> template<typename T>
/// struct X<int>::Inner { /* ... */ };
/// \endcode /// \endcode
bool isMemberSpecialization() { bool isMemberSpecialization() {
return getCommonPtr()->InstantiatedFromMember.getInt(); return getCommonPtr()->InstantiatedFromMember.getInt();
@ -620,6 +586,168 @@ public:
getCommonPtr()->InstantiatedFromMember.setInt(true); 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.
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(
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<FunctionTemplateSpecializationInfo> &getSpecializations() {
return getCommonPtr()->Specializations;
}
public:
/// Get the underlying function declaration of the template.
FunctionDecl *getTemplatedDecl() const {
return static_cast<FunctionDecl*>(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. /// Create a template function node.
static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation L,
@ -1371,15 +1499,16 @@ public:
}; };
/// Declaration of a class template. /// Declaration of a class template.
class ClassTemplateDecl : public TemplateDecl { class ClassTemplateDecl : public RedeclarableTemplateDecl,
public RedeclarableTemplate<ClassTemplateDecl> {
static void DeallocateCommon(void *Ptr); static void DeallocateCommon(void *Ptr);
protected: protected:
typedef RedeclarableTemplate<ClassTemplateDecl> redeclarable_base;
/// \brief Data that is common to all of the declarations of a given /// \brief Data that is common to all of the declarations of a given
/// class template. /// class template.
struct Common { struct Common : CommonBase {
Common() : InstantiatedFromMember(0, 0) {}
/// \brief The class template specializations for this class /// \brief The class template specializations for this class
/// template, including explicit specializations and instantiations. /// template, including explicit specializations and instantiations.
llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations; llvm::FoldingSet<ClassTemplateSpecializationDecl> Specializations;
@ -1391,24 +1520,8 @@ protected:
/// \brief The injected-class-name type for this class template. /// \brief The injected-class-name type for this class template.
QualType InjectedClassNameType; 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. /// \brief Retrieve the set of specializations of this class template.
llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() { llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
return getCommonPtr()->Specializations; return getCommonPtr()->Specializations;
@ -1423,8 +1536,13 @@ protected:
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl) TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl), : RedeclarableTemplateDecl(ClassTemplate, DC, L, Name, Params, Decl) { }
CommonOrPrev((Common*)0) { }
CommonBase *newCommon();
Common *getCommonPtr() {
return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr());
}
public: public:
/// Get the underlying class declarations of the template. /// Get the underlying class declarations of the template.
@ -1432,30 +1550,6 @@ public:
return static_cast<CXXRecordDecl *>(TemplatedDecl); 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. /// Create a class template node.
static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L, SourceLocation L,
@ -1476,6 +1570,29 @@ public:
getSpecializations().InsertNode(D, InsertPos); 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 /// \brief Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point. /// exists, otherwise return the insertion point.
ClassTemplatePartialSpecializationDecl * ClassTemplatePartialSpecializationDecl *
@ -1536,61 +1653,6 @@ public:
/// \endcode /// \endcode
QualType getInjectedClassNameSpecialization(); 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 // Implement isa/cast/dyncast support
static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; }

View File

@ -43,8 +43,9 @@ def Named : Decl<1>;
def ParmVar : DDecl<Var>; def ParmVar : DDecl<Var>;
def NonTypeTemplateParm : DDecl<Var>; def NonTypeTemplateParm : DDecl<Var>;
def Template : DDecl<Named, 1>; def Template : DDecl<Named, 1>;
def FunctionTemplate : DDecl<Template>; def RedeclarableTemplate : DDecl<Template, 1>;
def ClassTemplate : DDecl<Template>; def FunctionTemplate : DDecl<RedeclarableTemplate>;
def ClassTemplate : DDecl<RedeclarableTemplate>;
def TemplateTemplateParm : DDecl<Template>; def TemplateTemplateParm : DDecl<Template>;
def Using : DDecl<Named>; def Using : DDecl<Named>;
def UsingShadow : DDecl<Named>; def UsingShadow : DDecl<Named>;

View File

@ -83,6 +83,29 @@ unsigned TemplateParameterList::getDepth() const {
return cast<TemplateTemplateParmDecl>(FirstParm)->getDepth(); 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 // FunctionTemplateDecl Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -100,6 +123,12 @@ FunctionTemplateDecl *FunctionTemplateDecl::Create(ASTContext &C,
return new (C) FunctionTemplateDecl(DC, L, Name, Params, Decl); 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 * FunctionDecl *
FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args, FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos) { unsigned NumArgs, void *&InsertPos) {
@ -110,27 +139,6 @@ FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
return Info ? Info->Function->getMostRecentDeclaration() : 0; 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 // ClassTemplateDecl Implementation
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
@ -139,13 +147,6 @@ void ClassTemplateDecl::DeallocateCommon(void *Ptr) {
static_cast<Common *>(Ptr)->~Common(); static_cast<Common *>(Ptr)->~Common();
} }
ClassTemplateDecl *ClassTemplateDecl::getCanonicalDecl() {
ClassTemplateDecl *Template = this;
while (Template->getPreviousDeclaration())
Template = Template->getPreviousDeclaration();
return Template;
}
ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C, ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
DeclContext *DC, DeclContext *DC,
SourceLocation L, SourceLocation L,
@ -158,6 +159,12 @@ ClassTemplateDecl *ClassTemplateDecl::Create(ASTContext &C,
return New; return New;
} }
RedeclarableTemplateDecl::CommonBase *ClassTemplateDecl::newCommon() {
Common *CommonPtr = new (getASTContext()) Common;
getASTContext().AddDeallocation(DeallocateCommon, CommonPtr);
return CommonPtr;
}
ClassTemplateSpecializationDecl * ClassTemplateSpecializationDecl *
ClassTemplateDecl::findSpecialization(const TemplateArgument *Args, ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos) { unsigned NumArgs, void *&InsertPos) {
@ -263,20 +270,6 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
return CommonPtr->InjectedClassNameType; 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 // TemplateTypeParm Allocation/Deallocation Method Implementations
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -78,6 +78,7 @@ namespace clang {
void VisitParmVarDecl(ParmVarDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D); void VisitTemplateDecl(TemplateDecl *D);
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@ -895,14 +896,32 @@ void PCHDeclReader::VisitTemplateDecl(TemplateDecl *D) {
D->init(TemplatedDecl, TemplateParams); D->init(TemplatedDecl, TemplateParams);
} }
void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { void PCHDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitTemplateDecl(D); VisitTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++]; D->IdentifierNamespace = Record[Idx++];
ClassTemplateDecl *PrevDecl = RedeclarableTemplateDecl *PrevDecl =
cast_or_null<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++])); cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(Record[Idx++]));
D->setPreviousDeclaration(PrevDecl); assert((PrevDecl == 0 || PrevDecl->getKind() == D->getKind()) &&
"PrevDecl kind mismatch");
if (PrevDecl)
D->CommonOrPrev = PrevDecl;
if (PrevDecl == 0) { 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. // This ClassTemplateDecl owns a CommonPtr; read it.
// FoldingSets are filled in VisitClassTemplateSpecializationDecl. // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
@ -916,13 +935,6 @@ void PCHDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Reader.GetDecl(Record[Idx++])); Reader.GetDecl(Record[Idx++]));
// InjectedClassNameType is computed. // 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) { void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitTemplateDecl(D); VisitRedeclarableTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++]; if (D->getPreviousDeclaration() == 0) {
FunctionTemplateDecl *PrevDecl =
cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]));
D->setPreviousDeclaration(PrevDecl);
if (PrevDecl == 0) {
// This FunctionTemplateDecl owns a CommonPtr; read it. // This FunctionTemplateDecl owns a CommonPtr; read it.
// Read the function specialization declarations. // Read the function specialization declarations.
@ -1008,13 +1016,6 @@ void PCHDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
unsigned NumSpecs = Record[Idx++]; unsigned NumSpecs = Record[Idx++];
while (NumSpecs--) while (NumSpecs--)
Reader.GetDecl(Record[Idx++]); Reader.GetDecl(Record[Idx++]);
if (FunctionTemplateDecl *CTD
= cast_or_null<FunctionTemplateDecl>(Reader.GetDecl(Record[Idx++]))) {
D->setInstantiatedFromMemberTemplate(CTD);
if (Record[Idx++])
D->setMemberSpecialization();
}
} }
} }

View File

@ -76,6 +76,7 @@ namespace clang {
void VisitParmVarDecl(ParmVarDecl *D); void VisitParmVarDecl(ParmVarDecl *D);
void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D);
void VisitTemplateDecl(TemplateDecl *D); void VisitTemplateDecl(TemplateDecl *D);
void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D);
void VisitClassTemplateDecl(ClassTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D);
void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); void VisitFunctionTemplateDecl(FunctionTemplateDecl *D);
void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D);
@ -839,15 +840,25 @@ void PCHDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
Writer.AddTemplateParameterList(D->getTemplateParameters(), Record); Writer.AddTemplateParameterList(D->getTemplateParameters(), Record);
} }
void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { void PCHDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitTemplateDecl(D); VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace()); Record.push_back(D->getIdentifierNamespace());
Writer.AddDeclRef(D->getPreviousDeclaration(), Record); Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
if (D->getPreviousDeclaration() == 0) { if (D->getPreviousDeclaration() == 0) {
// This ClassTemplateDecl owns the CommonPtr; write it. // This TemplateDecl owns the CommonPtr; write it.
assert(D->isCanonicalDecl()); 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; typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
CTSDSetTy &CTSDSet = D->getSpecializations(); CTSDSetTy &CTSDSet = D->getSpecializations();
Record.push_back(CTSDSet.size()); Record.push_back(CTSDSet.size());
@ -865,10 +876,6 @@ void PCHDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
} }
// InjectedClassNameType is computed, no need to write it. // 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; Code = pch::DECL_CLASS_TEMPLATE;
} }
@ -929,10 +936,8 @@ void PCHDeclWriter::VisitClassTemplatePartialSpecializationDecl(
} }
void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitTemplateDecl(D); VisitRedeclarableTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace());
Writer.AddDeclRef(D->getPreviousDeclaration(), Record);
if (D->getPreviousDeclaration() == 0) { if (D->getPreviousDeclaration() == 0) {
// This FunctionTemplateDecl owns the CommonPtr; write it. // This FunctionTemplateDecl owns the CommonPtr; write it.
@ -945,10 +950,6 @@ void PCHDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
"Expected only canonical decls in set"); "Expected only canonical decls in set");
Writer.AddDeclRef(I->Function, Record); Writer.AddDeclRef(I->Function, Record);
} }
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization());
} }
Code = pch::DECL_FUNCTION_TEMPLATE; Code = pch::DECL_FUNCTION_TEMPLATE;
} }