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

View File

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

View File

@ -1234,72 +1234,40 @@ void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) {
ASTDeclReader::RedeclarableResult
ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
// Initialize CommonOrPrev before VisitTemplateDecl so that getCommonPtr()
// 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;
RedeclarableResult Redecl = VisitRedeclarable(D);
// Since this is the first declaration of the template, fill in the
// information for the 'common' pointer.
if (D->CommonOrPrev.isNull()) {
RedeclarableTemplateDecl::CommonBase *Common
= D->newCommon(Reader.getContext());
Common->Latest = D;
D->CommonOrPrev = Common;
}
// Make sure we've allocated the Common pointer first. We do this before
// VisitTemplateDecl so that getCommonPtr() can be used during initialization.
RedeclarableTemplateDecl *CanonD = D->getCanonicalDecl();
if (!CanonD->Common) {
CanonD->Common = CanonD->newCommon(Reader.getContext());
Reader.PendingDefinitions.insert(CanonD);
}
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
= ReadDeclAs<RedeclarableTemplateDecl>(Record, Idx)) {
assert(RTD->getKind() == D->getKind() &&
"InstantiatedFromMemberTemplate kind mismatch");
D->setInstantiatedFromMemberTemplateImpl(RTD);
D->setInstantiatedFromMemberTemplate(RTD);
if (Record[Idx++])
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);
D->IdentifierNamespace = Record[Idx++];
return RedeclarableResult(Reader, FirstDeclID);
return Redecl;
}
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
// the specializations.
SmallVector<serialization::DeclID, 2> SpecIDs;
@ -1321,6 +1289,7 @@ void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) {
typedef serialization::DeclID DeclID;
ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
// FIXME: Append specializations!
CommonPtr->LazySpecializations
= new (Reader.getContext()) DeclID [SpecIDs.size()];
memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
@ -1415,9 +1384,9 @@ void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl(
}
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.
// Read the function specialization declarations.
@ -1808,7 +1777,7 @@ void ASTDeclReader::attachPreviousDecl(Decl *D, Decl *previous) {
ND->RedeclLink.setPointer(cast<NamespaceDecl>(previous));
} else {
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));
} else {
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) {
VisitRedeclarable(D);
// Emit data to initialize CommonOrPrev before VisitTemplateDecl so that
// getCommonPtr() can be used while this is still initializing.
enum { FirstDeclaration, FirstInFile, PointsToPrevious };
RedeclarableTemplateDecl *Prev = D->getPreviousDeclaration();
RedeclarableTemplateDecl *First = 0;
if (!Prev) {
Record.push_back(FirstDeclaration);
if (D->isFirstDeclaration()) {
// This declaration owns the 'common' pointer, so serialize that data now.
Writer.AddDeclRef(D->getInstantiatedFromMemberTemplate(), Record);
if (D->getInstantiatedFromMemberTemplate())
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);
Record.push_back(D->getIdentifierNamespace());
}
@ -1070,7 +1049,7 @@ void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) {
void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) {
if (D->isFirstDeclaration()) {
typedef llvm::FoldingSet<ClassTemplateSpecializationDecl> CTSDSetTy;
CTSDSetTy &CTSDSet = D->getSpecializations();
Record.push_back(CTSDSet.size());
@ -1158,7 +1137,7 @@ void ASTDeclWriter::VisitClassScopeFunctionSpecializationDecl(
void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) {
if (D->isFirstDeclaration()) {
// This FunctionTemplateDecl owns the CommonPtr; write it.
// Write the function specialization declarations.