If a partial specialization of a member template is declared within a class

template and defined outside it, don't instantiate it twice when instantiating
the surrounding class template specialization. That would cause us to reject
the code because we think two partial specializations instantiated to produce
the same signature.

llvm-svn: 191418
This commit is contained in:
Richard Smith 2013-09-26 03:49:48 +00:00
parent fde9485297
commit 10b55fc85e
3 changed files with 40 additions and 5 deletions

View File

@ -2142,13 +2142,25 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
// Instantiate any out-of-line class template partial
// specializations now.
for (TemplateDeclInstantiator::delayed_partial_spec_iterator
for (TemplateDeclInstantiator::delayed_partial_spec_iterator
P = Instantiator.delayed_partial_spec_begin(),
PEnd = Instantiator.delayed_partial_spec_end();
P != PEnd; ++P) {
if (!Instantiator.InstantiateClassTemplatePartialSpecialization(
P->first,
P->second)) {
P->first, P->second)) {
Instantiation->setInvalidDecl();
break;
}
}
// Instantiate any out-of-line variable template partial
// specializations now.
for (TemplateDeclInstantiator::delayed_var_partial_spec_iterator
P = Instantiator.delayed_var_partial_spec_begin(),
PEnd = Instantiator.delayed_var_partial_spec_end();
P != PEnd; ++P) {
if (!Instantiator.InstantiateVarTemplatePartialSpecialization(
P->first, P->second)) {
Instantiation->setInvalidDecl();
break;
}

View File

@ -923,7 +923,7 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
SmallVector<ClassTemplatePartialSpecializationDecl *, 4> PartialSpecs;
D->getPartialSpecializations(PartialSpecs);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
if (PartialSpecs[I]->isOutOfLine())
if (PartialSpecs[I]->getFirstDeclaration()->isOutOfLine())
OutOfLinePartialSpecs.push_back(std::make_pair(Inst, PartialSpecs[I]));
}
@ -1004,7 +1004,7 @@ Decl *TemplateDeclInstantiator::VisitVarTemplateDecl(VarTemplateDecl *D) {
SmallVector<VarTemplatePartialSpecializationDecl *, 4> PartialSpecs;
D->getPartialSpecializations(PartialSpecs);
for (unsigned I = 0, N = PartialSpecs.size(); I != N; ++I)
if (PartialSpecs[I]->isOutOfLine())
if (PartialSpecs[I]->getFirstDeclaration()->isOutOfLine())
OutOfLineVarPartialSpecs.push_back(
std::make_pair(Inst, PartialSpecs[I]));
}

View File

@ -0,0 +1,23 @@
// RUN: %clang_cc1 -std=c++1y -verify %s
// expected-no-diagnostics
template<typename T> struct A {
template<typename U> struct B;
template<typename U> struct B<U*>;
};
template<typename T> template<typename U> struct A<T>::B<U*> {};
template struct A<int>;
A<int>::B<int*> b;
template<typename T> struct B {
template<typename U> static const int var1;
template<typename U> static const int var1<U*>;
template<typename U> static const int var2;
};
template<typename T> template<typename U> const int B<T>::var1<U*> = 1;
template<typename T> template<typename U> const int B<T>::var2<U*> = 1;
template struct B<int>;
int b_test1[B<int>::var1<int*>];
int b_test2[B<int>::var2<int*>];