forked from OSchip/llvm-project
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:
parent
38360b3ff7
commit
47470f2f3f
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>;
|
||||
|
|
Loading…
Reference in New Issue