Reimplement RedeclarableTemplateDecl in terms of

Redeclarable<RedeclarableTemplateDecl>, eliminating a bunch of
redeclaration-chain logic both in RedeclarableTemplateDecl and
especially in its (de-)serialization.

As part of this, eliminate the RedeclarableTemplate<> class template,
which was an abstraction that didn't actually save anything.

llvm-svn: 148181
This commit is contained in:
Douglas Gregor 2012-01-14 15:13:49 +00:00
parent f55694af01
commit 68444de354
5 changed files with 131 additions and 286 deletions

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_AST_DECLTEMPLATE_H #define LLVM_CLANG_AST_DECLTEMPLATE_H
#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclCXX.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateBase.h"
#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/PointerUnion.h"
#include <limits> #include <limits>
@ -478,23 +479,12 @@ public:
}; };
/// Declaration of a redeclarable template. /// Declaration of a redeclarable template.
class RedeclarableTemplateDecl : public TemplateDecl { class RedeclarableTemplateDecl : public TemplateDecl,
public Redeclarable<RedeclarableTemplateDecl>
RedeclarableTemplateDecl *getPreviousDeclarationImpl() { {
return CommonOrPrev.dyn_cast<RedeclarableTemplateDecl*>(); typedef Redeclarable<RedeclarableTemplateDecl> redeclarable_base;
} virtual RedeclarableTemplateDecl *getNextRedeclaration() {
return RedeclLink.getNext();
RedeclarableTemplateDecl *getCanonicalDeclImpl();
void setPreviousDeclarationImpl(RedeclarableTemplateDecl *Prev);
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplateImpl() {
return getCommonPtr()->InstantiatedFromMember.getPointer();
}
void setInstantiatedFromMemberTemplateImpl(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
} }
protected: protected:
@ -564,15 +554,12 @@ protected:
/// was explicitly specialized. /// was explicitly specialized.
llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool>
InstantiatedFromMember; InstantiatedFromMember;
/// \brief The latest declaration of this template.
RedeclarableTemplateDecl *Latest;
}; };
/// \brief A pointer to the previous declaration (if this is a redeclaration) /// \brief Pointer to the common data shared by all declarations of this
/// or to the data that is common to all declarations of this template. /// template.
llvm::PointerUnion<CommonBase*, RedeclarableTemplateDecl*> CommonOrPrev; CommonBase *Common;
/// \brief Retrieves the "common" pointer shared by all (re-)declarations of /// \brief Retrieves the "common" pointer shared by all (re-)declarations of
/// the same template. Calling this routine may implicitly allocate memory /// the same template. Calling this routine may implicitly allocate memory
/// for the common pointer. /// for the common pointer.
@ -584,53 +571,15 @@ protected:
RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, RedeclarableTemplateDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName Name, TemplateParameterList *Params, DeclarationName Name, TemplateParameterList *Params,
NamedDecl *Decl) NamedDecl *Decl)
: TemplateDecl(DK, DC, L, Name, Params, Decl), : TemplateDecl(DK, DC, L, Name, Params, Decl), Common() { }
CommonOrPrev((CommonBase*)0) { }
public: public:
template <class decl_type> friend class RedeclarableTemplate; template <class decl_type> friend class RedeclarableTemplate;
RedeclarableTemplateDecl *getCanonicalDecl() { /// Retrieves the canonical declaration of this template.
return getCanonicalDeclImpl(); RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); }
} const RedeclarableTemplateDecl *getCanonicalDecl() const {
return getFirstDeclaration();
/// \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 Retrieve the first declaration of this template, or itself
/// if this the first one.
RedeclarableTemplateDecl *getFirstDeclaration() {
return getCanonicalDecl();
}
/// \brief Retrieve the first declaration of this template, or itself
/// if this the first one.
const RedeclarableTemplateDecl *getFirstDeclaration() const {
return
const_cast<RedeclarableTemplateDecl*>(this)->getFirstDeclaration();
}
/// \brief Retrieve the most recent declaration of this template, or itself
/// if this the most recent one.
RedeclarableTemplateDecl *getMostRecentDeclaration() {
return getCommonPtr()->Latest;
}
/// \brief Retrieve the most recent declaration of this template, or itself
/// if this the most recent one.
const RedeclarableTemplateDecl *getMostRecentDeclaration() const {
return
const_cast<RedeclarableTemplateDecl*>(this)->getMostRecentDeclaration();
} }
/// \brief Determines whether this template was a specialization of a /// \brief Determines whether this template was a specialization of a
@ -665,10 +614,21 @@ public:
/// \brief Retrieve the previous declaration of this template, or /// \brief Retrieve the previous declaration of this template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() { RedeclarableTemplateDecl *getInstantiatedFromMemberTemplate() {
return getInstantiatedFromMemberTemplateImpl(); return getCommonPtr()->InstantiatedFromMember.getPointer();
} }
virtual RedeclarableTemplateDecl *getNextRedeclaration(); void setInstantiatedFromMemberTemplate(RedeclarableTemplateDecl *TD) {
assert(!getCommonPtr()->InstantiatedFromMember.getPointer());
getCommonPtr()->InstantiatedFromMember.setPointer(TD);
}
typedef redeclarable_base::redecl_iterator redecl_iterator;
redecl_iterator redecls_begin() const {
return redeclarable_base::redecls_begin();
}
redecl_iterator redecls_end() const {
return redeclarable_base::redecls_end();
}
// 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()); }
@ -680,80 +640,11 @@ public:
return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate;
} }
friend class ASTReader;
friend class ASTDeclReader; friend class ASTDeclReader;
friend class ASTDeclWriter; friend class ASTDeclWriter;
}; };
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);
}
};
template <> struct RedeclarableTemplateDecl:: template <> struct RedeclarableTemplateDecl::
SpecEntryTraits<FunctionTemplateSpecializationInfo> { SpecEntryTraits<FunctionTemplateSpecializationInfo> {
typedef FunctionDecl DeclType; typedef FunctionDecl DeclType;
@ -765,13 +656,10 @@ SpecEntryTraits<FunctionTemplateSpecializationInfo> {
}; };
/// Declaration of a template function. /// Declaration of a template function.
class FunctionTemplateDecl : public RedeclarableTemplateDecl, class FunctionTemplateDecl : public RedeclarableTemplateDecl {
public RedeclarableTemplate<FunctionTemplateDecl> {
static void DeallocateCommon(void *Ptr); static void DeallocateCommon(void *Ptr);
protected: protected:
typedef RedeclarableTemplate<FunctionTemplateDecl> 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
/// function template. /// function template.
struct Common : CommonBase { struct Common : CommonBase {
@ -834,26 +722,31 @@ public:
unsigned NumArgs, void *&InsertPos); unsigned NumArgs, void *&InsertPos);
FunctionTemplateDecl *getCanonicalDecl() { FunctionTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl(); return cast<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
const FunctionTemplateDecl *getCanonicalDecl() const { const FunctionTemplateDecl *getCanonicalDecl() const {
return redeclarable_base::getCanonicalDecl(); return cast<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
/// \brief Retrieve the previous declaration of this function template, or /// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
FunctionTemplateDecl *getPreviousDeclaration() { FunctionTemplateDecl *getPreviousDeclaration() {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
/// \brief Retrieve the previous declaration of this function template, or /// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
const FunctionTemplateDecl *getPreviousDeclaration() const { const FunctionTemplateDecl *getPreviousDeclaration() const {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { FunctionTemplateDecl *getInstantiatedFromMemberTemplate() {
return redeclarable_base::getInstantiatedFromMemberTemplate(); return cast_or_null<FunctionTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
} }
typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator; typedef SpecIterator<FunctionTemplateSpecializationInfo> spec_iterator;
@ -1745,13 +1638,10 @@ public:
}; };
/// Declaration of a class template. /// Declaration of a class template.
class ClassTemplateDecl : public RedeclarableTemplateDecl, 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 : CommonBase { struct Common : CommonBase {
@ -1836,26 +1726,31 @@ public:
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos);
ClassTemplateDecl *getCanonicalDecl() { ClassTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl(); return cast<ClassTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
const ClassTemplateDecl *getCanonicalDecl() const { const ClassTemplateDecl *getCanonicalDecl() const {
return redeclarable_base::getCanonicalDecl(); return cast<ClassTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
/// \brief Retrieve the previous declaration of this class template, or /// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
ClassTemplateDecl *getPreviousDeclaration() { ClassTemplateDecl *getPreviousDeclaration() {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<ClassTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
/// \brief Retrieve the previous declaration of this class template, or /// \brief Retrieve the previous declaration of this class template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
const ClassTemplateDecl *getPreviousDeclaration() const { const ClassTemplateDecl *getPreviousDeclaration() const {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<ClassTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
ClassTemplateDecl *getInstantiatedFromMemberTemplate() { ClassTemplateDecl *getInstantiatedFromMemberTemplate() {
return redeclarable_base::getInstantiatedFromMemberTemplate(); return cast_or_null<ClassTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
} }
/// \brief Return the partial specialization with the provided arguments if it /// \brief Return the partial specialization with the provided arguments if it
@ -2041,13 +1936,10 @@ public:
/// Declaration of an alias template. For example: /// Declaration of an alias template. For example:
/// ///
/// template <typename T> using V = std::map<T*, int, MyCompare<T>>; /// template <typename T> using V = std::map<T*, int, MyCompare<T>>;
class TypeAliasTemplateDecl : public RedeclarableTemplateDecl, class TypeAliasTemplateDecl : public RedeclarableTemplateDecl {
public RedeclarableTemplate<TypeAliasTemplateDecl> {
static void DeallocateCommon(void *Ptr); static void DeallocateCommon(void *Ptr);
protected: protected:
typedef RedeclarableTemplate<TypeAliasTemplateDecl> redeclarable_base;
typedef CommonBase Common; typedef CommonBase Common;
TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
@ -2068,26 +1960,31 @@ public:
TypeAliasTemplateDecl *getCanonicalDecl() { TypeAliasTemplateDecl *getCanonicalDecl() {
return redeclarable_base::getCanonicalDecl(); return cast<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
const TypeAliasTemplateDecl *getCanonicalDecl() const { const TypeAliasTemplateDecl *getCanonicalDecl() const {
return redeclarable_base::getCanonicalDecl(); return cast<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getCanonicalDecl());
} }
/// \brief Retrieve the previous declaration of this function template, or /// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
TypeAliasTemplateDecl *getPreviousDeclaration() { TypeAliasTemplateDecl *getPreviousDeclaration() {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
/// \brief Retrieve the previous declaration of this function template, or /// \brief Retrieve the previous declaration of this function template, or
/// NULL if no such declaration exists. /// NULL if no such declaration exists.
const TypeAliasTemplateDecl *getPreviousDeclaration() const { const TypeAliasTemplateDecl *getPreviousDeclaration() const {
return redeclarable_base::getPreviousDeclaration(); return cast_or_null<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getPreviousDeclaration());
} }
TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() { TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() {
return redeclarable_base::getInstantiatedFromMemberTemplate(); return cast_or_null<TypeAliasTemplateDecl>(
RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate());
} }

View File

@ -112,42 +112,30 @@ static void AdoptTemplateParameterList(TemplateParameterList *Params,
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() { RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() {
// Find the first declaration of this function template. if (!Common) {
RedeclarableTemplateDecl *First = getCanonicalDecl(); // Walk the previous-declaration chain until we either find a declaration
// with a common pointer or we run out of previous declarations.
llvm::SmallVector<RedeclarableTemplateDecl *, 2> PrevDecls;
for (RedeclarableTemplateDecl *Prev = getPreviousDeclaration(); Prev;
Prev = Prev->getPreviousDeclaration()) {
if (Prev->Common) {
Common = Prev->Common;
break;
}
PrevDecls.push_back(Prev);
}
if (First->CommonOrPrev.isNull()) { // If we never found a common pointer, allocate one now.
CommonBase *CommonPtr = First->newCommon(getASTContext()); if (!Common)
First->CommonOrPrev = CommonPtr; Common = newCommon(getASTContext());
CommonPtr->Latest = First;
// Update any previous declarations we saw with the common pointer.
for (unsigned I = 0, N = PrevDecls.size(); I != N; ++I)
PrevDecls[I]->Common = Common;
} }
return First->CommonOrPrev.get<CommonBase*>();
}
return Common;
RedeclarableTemplateDecl *RedeclarableTemplateDecl::getCanonicalDeclImpl() {
RedeclarableTemplateDecl *Tmpl = this;
while (Tmpl->getPreviousDeclaration())
Tmpl = Tmpl->getPreviousDeclaration();
return Tmpl;
}
void RedeclarableTemplateDecl::setPreviousDeclarationImpl(
RedeclarableTemplateDecl *Prev) {
if (Prev) {
CommonBase *Common = Prev->getCommonPtr();
Prev = Common->Latest;
Common->Latest = this;
CommonOrPrev = Prev;
} else {
assert(CommonOrPrev.is<CommonBase*>() && "Cannot reset TemplateDecl Prev");
}
}
RedeclarableTemplateDecl *RedeclarableTemplateDecl::getNextRedeclaration() {
if (CommonOrPrev.is<RedeclarableTemplateDecl*>())
return CommonOrPrev.get<RedeclarableTemplateDecl*>();
CommonBase *Common = CommonOrPrev.get<CommonBase*>();
return Common ? Common->Latest : this;
} }
template <class EntryType> template <class EntryType>

View File

@ -6152,10 +6152,10 @@ void ASTReader::finishPendingActions() {
PendingChainedObjCCategories.clear(); PendingChainedObjCCategories.clear();
} }
// If we deserialized any C++ or Objective-C class definitions or any // If we deserialized any C++ or Objective-C class definitions, any
// Objective-C protocol definitions, make sure that all redeclarations point // Objective-C protocol definitions, or any redeclarable templates, make sure
// to the definitions. Note that this can only happen now, after the // that all redeclarations point to the definitions. Note that this can only
// redeclaration chains have been fully wired. // happen now, after the redeclaration chains have been fully wired.
for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(), for (llvm::SmallPtrSet<Decl *, 4>::iterator D = PendingDefinitions.begin(),
DEnd = PendingDefinitions.end(); DEnd = PendingDefinitions.end();
D != DEnd; ++D) { D != DEnd; ++D) {
@ -6177,11 +6177,21 @@ void ASTReader::finishPendingActions() {
continue; continue;
} }
ObjCProtocolDecl *PD = cast<ObjCProtocolDecl>(*D); if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(*D)) {
for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(), for (ObjCProtocolDecl::redecl_iterator R = PD->redecls_begin(),
REnd = PD->redecls_end(); REnd = PD->redecls_end();
R != REnd; ++R)
R->Data = PD->Data;
continue;
}
RedeclarableTemplateDecl *RTD
= cast<RedeclarableTemplateDecl>(*D)->getCanonicalDecl();
for (RedeclarableTemplateDecl::redecl_iterator R = RTD->redecls_begin(),
REnd = RTD->redecls_end();
R != REnd; ++R) R != REnd; ++R)
R->Data = PD->Data; R->Common = RTD->Common;
} }
PendingDefinitions.clear(); PendingDefinitions.clear();
} }

View File

@ -1234,72 +1234,40 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
ASTDeclReader::RedeclarableResult ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr() RedeclarableResult Redecl = VisitRedeclarable(D);
// can be used while this is still initializing.
enum RedeclKind { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclKind Kind = (RedeclKind)Record[Idx++];
// Determine the first declaration ID.
DeclID FirstDeclID = 0;
switch (Kind) {
case FirstDeclaration: {
FirstDeclID = ThisDeclID;
// Since this is the first declaration of the template, fill in the // Make sure we've allocated the Common pointer first. We do this before
// information for the 'common' pointer. // VisitTemplateDecl so that getCommonPtr() can be used during initialization.
if (D->CommonOrPrev.isNull()) { RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
RedeclarableTemplateDecl::CommonBase *Common if (!CanonD->Common) {
= D->newCommon(Reader.getContext()); CanonD->Common = CanonD->newCommon(Reader.getContext());
Common->Latest = D; Reader.PendingDefinitions.insert(CanonD);
D->CommonOrPrev = Common; }
} D->Common = CanonD->Common;
// If this is the first declaration of the template, fill in the information
// for the 'common' pointer.
if (ThisDeclID == Redecl.getFirstID()) {
if (RedeclarableTemplateDecl *RTD if (RedeclarableTemplateDecl *RTD
= ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) { = ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
assert(RTD->getKind() == D->getKind() && assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch"); "InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplateImpl(RTD); D->setInstantiatedFromMemberTemplate(RTD);
if (Record[Idx++]) if (Record[Idx++])
D->setMemberSpecialization(); D->setMemberSpecialization();
} }
break;
} }
case FirstInFile:
case PointsToPrevious: {
FirstDeclID = ReadDeclID(Record, Idx);
DeclID PrevDeclID = ReadDeclID(Record, Idx);
RedeclarableTemplateDecl *FirstDecl
= cast_or_null<RedeclarableTemplateDecl>(Reader.GetDecl(FirstDeclID));
// We delay loading of the redeclaration chain to avoid deeply nested calls.
// We temporarily set the first (canonical) declaration as the previous one
// which is the one that matters and mark the real previous DeclID to be
// loaded and attached later on.
D->CommonOrPrev = FirstDecl;
if (Kind == PointsToPrevious) {
// Make a note that we need to wire up this declaration to its
// previous declaration, later. We don't need to do this for the first
// declaration in any given module file, because those will be wired
// together later.
Reader.PendingPreviousDecls.push_back(std::make_pair(D, PrevDeclID));
}
break;
}
}
VisitTemplateDecl(D); VisitTemplateDecl(D);
D->IdentifierNamespace = Record[Idx++]; D->IdentifierNamespace = Record[Idx++];
return RedeclarableResult(Reader, FirstDeclID); return Redecl;
} }
void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D); RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) { if (ThisDeclID == Redecl.getFirstID()) {
// This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
// the specializations. // the specializations.
SmallVector<serialization::DeclID, 2> SpecIDs; SmallVector<serialization::DeclID, 2> SpecIDs;
@ -1321,6 +1289,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
typedef serialization::DeclID DeclID; typedef serialization::DeclID DeclID;
ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr(); ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
// FIXME: Append specializations!
CommonPtr->LazySpecializations CommonPtr->LazySpecializations
= new (Reader.getContext()) DeclID [SpecIDs.size()]; = new (Reader.getContext()) DeclID [SpecIDs.size()];
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(), memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
@ -1415,9 +1384,9 @@ void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
} }
void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D); RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) { if (ThisDeclID == Redecl.getFirstID()) {
// This FunctionTemplateDecl owns a CommonPtr; read it. // This FunctionTemplateDecl owns a CommonPtr; read it.
// Read the function specialization declarations. // Read the function specialization declarations.
@ -1808,7 +1777,7 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous)); ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
} else { } else {
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
TD->CommonOrPrev = cast<RedeclarableTemplateDecl>(previous); TD->RedeclLink.setPointer(cast<RedeclarableTemplateDecl>(previous));
} }
} }
@ -1841,7 +1810,9 @@ void ASTDeclReader::attachLatestDecl(Decl *D, Decl *Latest) {
cast<NamespaceDecl>(Latest)); cast<NamespaceDecl>(Latest));
} else { } else {
RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D); RedeclarableTemplateDecl *TD = cast<RedeclarableTemplateDecl>(D);
TD->getCommonPtr()->Latest = cast<RedeclarableTemplateDecl>(Latest); TD->RedeclLink
= Redeclarable<RedeclarableTemplateDecl>::LatestDeclLink(
cast<RedeclarableTemplateDecl>(Latest));
} }
} }

View File

@ -1031,38 +1031,17 @@ void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) {
} }
void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
VisitRedeclarable(D);
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing. // getCommonPtr() can be used while this is still initializing.
enum { FirstDeclaration, FirstInFile, PointsToPrevious }; if (D->isFirstDeclaration()) {
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
RedeclarableTemplateDecl *First = 0;
if (!Prev) {
Record.push_back(FirstDeclaration);
// This declaration owns the 'common' pointer, so serialize that data now. // This declaration owns the 'common' pointer, so serialize that data now.
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record); Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
if (D->getInstantiatedFromMemberTemplate()) if (D->getInstantiatedFromMemberTemplate())
Record.push_back(D->isMemberSpecialization()); Record.push_back(D->isMemberSpecialization());
} else {
First = D->getFirstDeclaration();
Record.push_back(Prev->isFromASTFile()? FirstInFile : PointsToPrevious);
Writer.AddDeclRef(First, Record);
Writer.AddDeclRef(Prev, Record);
} }
if (D->getMostRecentDeclaration() != D && (!Prev || Prev->isFromASTFile())) {
if (!First)
First = D->getFirstDeclaration();
// Capture the set of redeclarations in this file.
LocalRedeclarationsInfo LocalInfo = {
Writer.GetDeclRef(First),
Writer.GetDeclRef(D),
Writer.GetDeclRef(D->getMostRecentDeclaration())
};
Writer.LocalRedeclarations.push_back(LocalInfo);
}
VisitTemplateDecl(D); VisitTemplateDecl(D);
Record.push_back(D->getIdentifierNamespace()); Record.push_back(D->getIdentifierNamespace());
} }
@ -1070,7 +1049,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D); VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) { if (D->isFirstDeclaration()) {
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());
@ -1158,7 +1137,7 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D); VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) { if (D->isFirstDeclaration()) {
// This FunctionTemplateDecl owns the CommonPtr; write it. // This FunctionTemplateDecl owns the CommonPtr; write it.
// Write the function specialization declarations. // Write the function specialization declarations.