Hide the specializations folding sets of ClassTemplateDecl as an implementation detail (InsertPos

leaks though) and add methods to its interface for adding/finding specializations.

Simplifies its users a bit and we no longer need to replace specializations in the folding set with
their redeclarations. We just return the most recent redeclarations.

As a bonus, it fixes http://llvm.org/PR7670.

llvm-svn: 108832
This commit is contained in:
Argyrios Kyrtzidis 2010-07-20 13:59:28 +00:00
parent 38360b3ff7
commit 47470f2f3f
5 changed files with 135 additions and 82 deletions

View File

@ -997,6 +997,17 @@ public:
const PrintingPolicy &Policy,
bool Qualified) const;
ClassTemplateSpecializationDecl *getMostRecentDeclaration() {
CXXRecordDecl *Recent
= cast<CXXRecordDecl>(CXXRecordDecl::getMostRecentDeclaration());
if (!isa<ClassTemplateSpecializationDecl>(Recent)) {
// FIXME: Does injected class name need to be in the redeclarations chain?
assert(Recent->isInjectedClassName() && Recent->getPreviousDeclaration());
Recent = Recent->getPreviousDeclaration();
}
return cast<ClassTemplateSpecializationDecl>(Recent);
}
/// \brief Retrieve the template that this specialization specializes.
ClassTemplateDecl *getSpecializedTemplate() const;
@ -1242,6 +1253,11 @@ public:
static ClassTemplatePartialSpecializationDecl *
Create(ASTContext &Context, EmptyShell Empty);
ClassTemplatePartialSpecializationDecl *getMostRecentDeclaration() {
return cast<ClassTemplatePartialSpecializationDecl>(
ClassTemplateSpecializationDecl::getMostRecentDeclaration());
}
/// Get the list of template parameters
TemplateParameterList *getTemplateParameters() const {
return TemplateParams;
@ -1393,6 +1409,18 @@ protected:
/// 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;
}
/// \brief Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations() {
return getCommonPtr()->PartialSpecializations;
}
ClassTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
TemplateParameterList *Params, NamedDecl *Decl)
: TemplateDecl(ClassTemplate, DC, L, Name, Params, Decl),
@ -1436,16 +1464,34 @@ public:
NamedDecl *Decl,
ClassTemplateDecl *PrevDecl);
/// \brief Retrieve the set of specializations of this class template.
llvm::FoldingSet<ClassTemplateSpecializationDecl> &getSpecializations() {
return getCommonPtr()->Specializations;
/// \brief Return the specialization with the provided arguments if it exists,
/// otherwise return the insertion point.
ClassTemplateSpecializationDecl *
findSpecialization(const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
/// \brief Insert the specified specialization knowing that it is not already
/// in. InsertPos must be obtained from findSpecialization.
void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos) {
getSpecializations().InsertNode(D, InsertPos);
}
/// \brief Retrieve the set of partial specializations of this class
/// template.
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
getPartialSpecializations() {
return getCommonPtr()->PartialSpecializations;
/// \brief Return the partial specialization with the provided arguments if it
/// exists, otherwise return the insertion point.
ClassTemplatePartialSpecializationDecl *
findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs,
void *&InsertPos);
/// \brief Insert the specified partial specialization knowing that it is not
/// already in. InsertPos must be obtained from findPartialSpecialization.
void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D,
void *InsertPos) {
getPartialSpecializations().InsertNode(D, InsertPos);
}
/// \brief Return the next partial specialization sequence number.
unsigned getNextPartialSpecSequenceNumber() {
return getPartialSpecializations().size();
}
/// \brief Retrieve the partial specializations as an ordered list.
@ -1455,12 +1501,24 @@ public:
/// \brief Find a class template partial specialization with the given
/// type T.
///
/// \brief A dependent type that names a specialization of this class
/// \param T a dependent type that names a specialization of this class
/// template.
///
/// \returns the class template partial specialization that exactly matches
/// the type \p T, or NULL if no such partial specialization exists.
ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T);
/// \brief Find a class template partial specialization which was instantiated
/// from the given member partial specialization.
///
/// \param D a member class template partial specialization.
///
/// \returns the class template partial specialization which was instantiated
/// from the given member partial specialization, or NULL if no such partial
/// specialization exists.
ClassTemplatePartialSpecializationDecl *
findPartialSpecInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *D);
/// \brief Retrieve the template specialization type of the
/// injected-class-name for this class template.

View File

@ -171,6 +171,28 @@ void ClassTemplateDecl::Destroy(ASTContext& C) {
Decl::Destroy(C);
}
ClassTemplateSpecializationDecl *
ClassTemplateDecl::findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos) {
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID, Args, NumArgs, getASTContext());
ClassTemplateSpecializationDecl *D
= getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
return D ? D->getMostRecentDeclaration() : 0;
}
ClassTemplatePartialSpecializationDecl *
ClassTemplateDecl::findPartialSpecialization(const TemplateArgument *Args,
unsigned NumArgs,
void *&InsertPos) {
llvm::FoldingSetNodeID ID;
ClassTemplatePartialSpecializationDecl::Profile(ID, Args, NumArgs,
getASTContext());
ClassTemplatePartialSpecializationDecl *D
= getPartialSpecializations().FindNodeOrInsertPos(ID, InsertPos);
return D ? D->getMostRecentDeclaration() : 0;
}
void ClassTemplateDecl::getPartialSpecializations(
llvm::SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS) {
llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &PartialSpecs
@ -181,7 +203,7 @@ void ClassTemplateDecl::getPartialSpecializations(
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
P != PEnd; ++P) {
assert(!PS[P->getSequenceNumber()]);
PS[P->getSequenceNumber()] = &*P;
PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
}
}
@ -194,7 +216,22 @@ ClassTemplateDecl::findPartialSpecialization(QualType T) {
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (Context.hasSameType(P->getInjectedSpecializationType(), T))
return &*P;
return P->getMostRecentDeclaration();
}
return 0;
}
ClassTemplatePartialSpecializationDecl *
ClassTemplateDecl::findPartialSpecInstantiatedFromMember(
ClassTemplatePartialSpecializationDecl *D) {
Decl *DCanon = D->getCanonicalDecl();
for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
P = getPartialSpecializations().begin(),
PEnd = getPartialSpecializations().end();
P != PEnd; ++P) {
if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
return P->getMostRecentDeclaration();
}
return 0;

View File

@ -1477,14 +1477,10 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
= dyn_cast<ClassTemplateDecl>(Template)) {
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *Decl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
= ClassTemplate->findSpecialization(Converted.getFlatArguments(),
Converted.flatSize(), InsertPos);
if (!Decl) {
// This is the first time we have referenced this class template
// specialization. Create the canonical declaration and add it to
@ -1495,7 +1491,7 @@ QualType Sema::CheckTemplateIdType(TemplateName Name,
ClassTemplate->getLocation(),
ClassTemplate,
Converted, 0);
ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
ClassTemplate->AddSpecialization(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
}
@ -3727,7 +3723,6 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
if (isPartialSpecialization) {
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
@ -3760,30 +3755,22 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
Diag(TemplateNameLoc, diag::err_partial_spec_fully_specialized)
<< ClassTemplate->getDeclName();
isPartialSpecialization = false;
} else {
// FIXME: Template parameter list matters, too
ClassTemplatePartialSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
Context);
}
}
if (!isPartialSpecialization)
ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl = 0;
if (isPartialSpecialization)
// FIXME: Template parameter list matters, too
PrevDecl
= ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
InsertPos);
= ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(),
Converted.flatSize(),
InsertPos);
else
PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
= ClassTemplate->findSpecialization(Converted.getFlatArguments(),
Converted.flatSize(), InsertPos);
ClassTemplateSpecializationDecl *Specialization = 0;
@ -3821,7 +3808,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
ClassTemplatePartialSpecializationDecl *PrevPartial
= cast_or_null<ClassTemplatePartialSpecializationDecl>(PrevDecl);
unsigned SequenceNumber = PrevPartial? PrevPartial->getSequenceNumber()
: ClassTemplate->getPartialSpecializations().size();
: ClassTemplate->getNextPartialSpecSequenceNumber();
ClassTemplatePartialSpecializationDecl *Partial
= ClassTemplatePartialSpecializationDecl::Create(Context, Kind,
ClassTemplate->getDeclContext(),
@ -3840,12 +3827,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
(TemplateParameterList**) TemplateParameterLists.release());
}
if (PrevPartial) {
ClassTemplate->getPartialSpecializations().RemoveNode(PrevPartial);
ClassTemplate->getPartialSpecializations().GetOrInsertNode(Partial);
} else {
ClassTemplate->getPartialSpecializations().InsertNode(Partial, InsertPos);
}
if (!PrevPartial)
ClassTemplate->AddPartialSpecialization(Partial, InsertPos);
Specialization = Partial;
// If we are providing an explicit specialization of a member class
@ -3902,13 +3885,8 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
(TemplateParameterList**) TemplateParameterLists.release());
}
if (PrevDecl) {
ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
ClassTemplate->getSpecializations().GetOrInsertNode(Specialization);
} else {
ClassTemplate->getSpecializations().InsertNode(Specialization,
InsertPos);
}
if (!PrevDecl)
ClassTemplate->AddSpecialization(Specialization, InsertPos);
CanonType = Context.getTypeDeclType(Specialization);
}
@ -4701,14 +4679,10 @@ Sema::ActOnExplicitInstantiation(Scope *S,
// Find the class template specialization declaration that
// corresponds to these arguments.
llvm::FoldingSetNodeID ID;
ClassTemplateSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
= ClassTemplate->findSpecialization(Converted.getFlatArguments(),
Converted.flatSize(), InsertPos);
TemplateSpecializationKind PrevDecl_TSK
= PrevDecl ? PrevDecl->getTemplateSpecializationKind() : TSK_Undeclared;
@ -4761,15 +4735,9 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Converted, PrevDecl);
SetNestedNameSpecifier(Specialization, SS);
if (!HasNoEffect) {
if (PrevDecl) {
// Remove the previous declaration from the folding set, since we want
// to introduce a new declaration.
ClassTemplate->getSpecializations().RemoveNode(PrevDecl);
ClassTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
}
if (!HasNoEffect && !PrevDecl) {
// Insert the new specialization.
ClassTemplate->getSpecializations().InsertNode(Specialization, InsertPos);
ClassTemplate->AddSpecialization(Specialization, InsertPos);
}
}

View File

@ -857,16 +857,7 @@ TemplateDeclInstantiator::VisitClassTemplatePartialSpecializationDecl(
if (!InstClassTemplate)
return 0;
Decl *DCanon = D->getCanonicalDecl();
for (llvm::FoldingSet<ClassTemplatePartialSpecializationDecl>::iterator
P = InstClassTemplate->getPartialSpecializations().begin(),
PEnd = InstClassTemplate->getPartialSpecializations().end();
P != PEnd; ++P) {
if (P->getInstantiatedFromMember()->getCanonicalDecl() == DCanon)
return &*P;
}
return 0;
return InstClassTemplate->findPartialSpecInstantiatedFromMember(D);
}
Decl *
@ -1804,15 +1795,10 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Figure out where to insert this class template partial specialization
// in the member template's set of class template partial specializations.
llvm::FoldingSetNodeID ID;
ClassTemplatePartialSpecializationDecl::Profile(ID,
Converted.getFlatArguments(),
Converted.flatSize(),
SemaRef.Context);
void *InsertPos = 0;
ClassTemplateSpecializationDecl *PrevDecl
= ClassTemplate->getPartialSpecializations().FindNodeOrInsertPos(ID,
InsertPos);
= ClassTemplate->findPartialSpecialization(Converted.getFlatArguments(),
Converted.flatSize(), InsertPos);
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
@ -1871,7 +1857,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
InstTemplateArgs,
CanonType,
0,
ClassTemplate->getPartialSpecializations().size());
ClassTemplate->getNextPartialSpecSequenceNumber());
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return 0;
@ -1881,8 +1867,7 @@ TemplateDeclInstantiator::InstantiateClassTemplatePartialSpecialization(
// Add this partial specialization to the set of class template partial
// specializations.
ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
InsertPos);
ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
return false;
}

View File

@ -103,3 +103,8 @@ class basic_streambuf
// PR 7660
template<typename T> struct S_PR7660 { void g(void (*)(T)); };
template<> void S_PR7660<int>::g(void(*)(int)) {}
// PR 7670
template<typename> class C_PR7670;
template<> class C_PR7670<int>;
template<> class C_PR7670<int>;