forked from OSchip/llvm-project
When checking for the necessary 'template<>' headers based on the
nested of an out-of-line declaration, only require a 'template<>' header for each enclosing class template that hasn't been previously specialized; previously, we were requiring 'template<>' for enclosing class templates and members of class templates that hadn't been previously specialized. Fixes <rdar://problem/9422013>. llvm-svn: 131207
This commit is contained in:
parent
851e18a1d4
commit
373af9bc5d
|
@ -1614,6 +1614,11 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
|
|||
// expect to see.
|
||||
TemplateParameterList *ExpectedTemplateParams = 0;
|
||||
|
||||
// C++0x [temp.expl.spec]p15:
|
||||
// A member or a member template may be nested within many enclosing
|
||||
// class templates. In an explicit specialization for such a member, the
|
||||
// member declaration shall be preceded by a template<> for each
|
||||
// enclosing class template that is explicitly specialized.
|
||||
if (CXXRecordDecl *Record = T->getAsCXXRecordDecl()) {
|
||||
if (ClassTemplatePartialSpecializationDecl *Partial
|
||||
= dyn_cast<ClassTemplatePartialSpecializationDecl>(Record)) {
|
||||
|
@ -1637,10 +1642,11 @@ Sema::MatchTemplateParametersToScopeSpecifier(SourceLocation DeclStartLoc,
|
|||
break;
|
||||
} else if (Record->getTemplateSpecializationKind()) {
|
||||
if (Record->getTemplateSpecializationKind()
|
||||
!= TSK_ExplicitSpecialization)
|
||||
NeedEmptyTemplateHeader = true;
|
||||
else
|
||||
break;
|
||||
!= TSK_ExplicitSpecialization &&
|
||||
TypeIdx == NumTypes - 1)
|
||||
IsExplicitSpecialization = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
} else if (const TemplateSpecializationType *TST
|
||||
= T->getAs<TemplateSpecializationType>()) {
|
||||
|
|
|
@ -165,3 +165,4 @@ namespace PR9877 {
|
|||
const int X<0>::Y::Z;
|
||||
template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,3 +20,14 @@ NonDefaultConstructible &test(bool b) {
|
|||
return b? X<NonDefaultConstructible, int>::member // expected-note{{instantiation}}
|
||||
: X<NonDefaultConstructible, long>::member;
|
||||
}
|
||||
|
||||
namespace rdar9422013 {
|
||||
template<int>
|
||||
struct X {
|
||||
struct Inner {
|
||||
static unsigned array[17];
|
||||
};
|
||||
};
|
||||
|
||||
template<> unsigned X<1>::Inner::array[]; // okay
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// RUN: %clang_cc1 -fsyntax-only -verify %s
|
||||
template<class T> struct A {
|
||||
struct B { };
|
||||
template<class U> struct C { };
|
||||
};
|
||||
template<> struct A<int> {
|
||||
void f(int);
|
||||
};
|
||||
void h() {
|
||||
A<int> a;
|
||||
a.f(16);
|
||||
}
|
||||
// A<int>::f must be defined somewhere
|
||||
// template<> not used for a member of an // explicitly specialized class template
|
||||
void A<int>::f(int) { /* ... */ }
|
||||
template<> struct A<char>::B {
|
||||
void f();
|
||||
};
|
||||
// template<> also not used when defining a member of // an explicitly specialized member class
|
||||
void A<char>::B::f() { /* ... */ }
|
||||
template<> template<class U> struct A<char>::C {
|
||||
void f();
|
||||
};
|
||||
|
||||
template<>
|
||||
template<class U> void A<char>::C<U>::f() { /* ... */ }
|
||||
template<> struct A<short>::B {
|
||||
void f();
|
||||
};
|
||||
template<> void A<short>::B::f() { /* ... */ } // expected-error{{no function template matches function template specialization 'f'}}
|
||||
template<> template<class U> struct A<short>::C {
|
||||
void f();
|
||||
};
|
||||
template<class U> void A<short>::C<U>::f() { /* ... */ } // expected-error{{template parameter list matching the non-templated nested type 'A<short>' should be empty ('template<>')}}
|
Loading…
Reference in New Issue