[cfe-commits] r131207 - in /cfe/trunk: lib/Sema/SemaTemplate.cpp test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp
Douglas Gregor
dgregor at apple.com
Wed May 11 16:26:17 PDT 2011
Author: dgregor
Date: Wed May 11 18:26:17 2011
New Revision: 131207
URL: http://llvm.org/viewvc/llvm-project?rev=131207&view=rev
Log:
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>.
Added:
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp
Modified:
cfe/trunk/lib/Sema/SemaTemplate.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=131207&r1=131206&r2=131207&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Wed May 11 18:26:17 2011
@@ -1614,6 +1614,11 @@
// 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 @@
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>()) {
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp?rev=131207&r1=131206&r2=131207&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp Wed May 11 18:26:17 2011
@@ -165,3 +165,4 @@
const int X<0>::Y::Z;
template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}}
}
+
Modified: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp?rev=131207&r1=131206&r2=131207&view=diff
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp (original)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p15.cpp Wed May 11 18:26:17 2011
@@ -20,3 +20,14 @@
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
+}
Added: cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp?rev=131207&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.spec/temp.expl.spec/p5-example.cpp Wed May 11 18:26:17 2011
@@ -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<>')}}
More information about the cfe-commits
mailing list