[modules] If a referenced-but-not-instantiated class template specialization

gets explicitly specialized, don't reuse the previous class template
specialization declaration as a new declaration. The benefit here is fairly
marginal, it harms source fidelity, and this is horrible to model if the
specialization was imported from another module (without this change, it
asserts or worse).

llvm-svn: 209552
This commit is contained in:
Richard Smith 2014-05-23 21:00:28 +00:00
parent b429083aff
commit 871cd4c131
4 changed files with 12 additions and 18 deletions

View File

@ -6066,24 +6066,7 @@ Sema::ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec,
// The canonical type
QualType CanonType;
if (PrevDecl &&
(PrevDecl->getSpecializationKind() == TSK_Undeclared ||
TUK == TUK_Friend)) {
// Since the only prior class template specialization with these
// arguments was referenced but not declared, or we're only
// referencing this specialization as a friend, reuse that
// declaration node as our own, updating its source location and
// the list of outer template parameters to reflect our new declaration.
Specialization = PrevDecl;
Specialization->setLocation(TemplateNameLoc);
if (TemplateParameterLists.size() > 0) {
Specialization->setTemplateParameterListsInfo(Context,
TemplateParameterLists.size(),
TemplateParameterLists.data());
}
PrevDecl = 0;
CanonType = Context.getTypeDeclType(Specialization);
} else if (isPartialSpecialization) {
if (isPartialSpecialization) {
// Build the canonical type that describes the converted template
// arguments of the class template partial specialization.
TemplateName CanonTemplate = Context.getCanonicalTemplateName(Name);

View File

@ -56,3 +56,10 @@ template<typename T> struct WithPartialSpecialization<T*> {
T &f() { static T t; return t; }
};
typedef WithPartialSpecializationUse::type WithPartialSpecializationInstantiate;
template<> struct WithExplicitSpecialization<int> {
int n;
template<typename T> T &inner_template() {
return n;
}
};

View File

@ -33,3 +33,6 @@ template<typename T> struct Outer {
template<typename T> struct WithPartialSpecialization {};
typedef WithPartialSpecialization<int*> WithPartialSpecializationUse;
template<typename T> struct WithExplicitSpecialization;
typedef WithExplicitSpecialization<int> WithExplicitSpecializationUse;

View File

@ -104,6 +104,7 @@ void g() {
TemplateInstantiationVisibility<char[4]> tiv4;
int &p = WithPartialSpecializationUse().f();
int &q = WithExplicitSpecializationUse().inner_template<int>();
}
RedeclaredAsFriend<int> raf1;