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;
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;
/// 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),
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.
/// \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.
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
P = PartialSpecs.begin(), PEnd = PartialSpecs.end();
P != PEnd; ++P) {
assert(!PS[P->getSequenceNumber()]);
- PS[P->getSequenceNumber()] = &*P;
+ PS[P->getSequenceNumber()] = P->getMostRecentDeclaration();
}
}
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;
= 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
ClassTemplate->getLocation(),
ClassTemplate,
Converted, 0);
- ClassTemplate->getSpecializations().InsertNode(Decl, InsertPos);
+ ClassTemplate->AddSpecialization(Decl, InsertPos);
Decl->setLexicalDeclContext(CurContext);
}
// Find the class template (partial) specialization declaration that
// corresponds to these arguments.
- llvm::FoldingSetNodeID ID;
if (isPartialSpecialization) {
bool MirrorsPrimaryTemplate;
if (CheckClassTemplatePartialSpecializationArgs(
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;
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(),
(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
(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);
}
// 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;
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);
}
}
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 *
// 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.
InstTemplateArgs,
CanonType,
0,
- ClassTemplate->getPartialSpecializations().size());
+ ClassTemplate->getNextPartialSpecSequenceNumber());
// Substitute the nested name specifier, if any.
if (SubstQualifier(PartialSpec, InstPartialSpec))
return 0;
// Add this partial specialization to the set of class template partial
// specializations.
- ClassTemplate->getPartialSpecializations().InsertNode(InstPartialSpec,
- InsertPos);
+ ClassTemplate->AddPartialSpecialization(InstPartialSpec, InsertPos);
return false;
}
// 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>;