[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