]> granicus.if.org Git - clang/commitdiff
Don't complain about out-of-line explicit specializations of member
authorDouglas Gregor <dgregor@apple.com>
Thu, 8 Oct 2009 15:54:21 +0000 (15:54 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 8 Oct 2009 15:54:21 +0000 (15:54 +0000)
function and member function templates that are not definitions. Add
more tests to ensure that explicit specializations of member function
templates prevent instantiation.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83550 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaDecl.cpp
test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp

index 267eea8a1bca5df05420a356d76a5e5aee9d163a..9163aba9f5bcf7f58b3ad2fab77181ca09695982 100644 (file)
@@ -2852,9 +2852,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC,
   if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
     // An out-of-line member function declaration must also be a
     // definition (C++ [dcl.meaning]p1).
-    // FIXME: Find a better way to recognize out-of-line specializations!
+    // Note that this is not the case for explicit specializations of
+    // function templates or member functions of class templates, per
+    // C++ [temp.expl.spec]p2.
     if (!IsFunctionDefinition && !isFriend &&
-        !(TemplateParamLists.size() && !FunctionTemplate)) {
+        NewFD->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) {
       Diag(NewFD->getLocation(), diag::err_out_of_line_declaration)
         << D.getCXXScopeSpec().getRange();
       NewFD->setInvalidDecl();
index 9c6c5edc504d35e8174e453d6279620a34ca9b86..64856605a0a757de43f2f4a434df797bce133ad9 100644 (file)
@@ -62,7 +62,7 @@ struct X0 { // expected-note 2{{here}}
    // expected-error{{base specifier}}
   
   template<typename U>
-  void ft1(T t, U u);
+  void ft1(T t, U u); // expected-note{{explicitly specialized}}
 };
 
 }
@@ -203,14 +203,37 @@ N0::X0<int>::InnerTemplate<int> inner_template1; // expected-error{{incomplete}}
 N0::X0<int>::InnerTemplate<long> inner_template2;
 N0::X0<int>::InnerTemplate<unsigned long> inner_template3; // expected-note{{instantiation}}
 
-#if 0
-// FIXME: update the remainder of this test to check for scopes properly.
 //    -- member function template of a class template
-template<>
-template<>
-void X0<void*>::ft1(void*, const void*) { }
+namespace N0 {
+  template<>
+  template<>
+  void X0<void*>::ft1(void*, const void*) { }
+  
+  template<> template<>
+  void X0<void*>::ft1(void *, int);
+
+  template<> template<>
+  void X0<void*>::ft1(void *, unsigned);
+
+  template<> template<>
+  void X0<void*>::ft1(void *, long);
+}
+
+template<> template<>
+void N0::X0<void*>::ft1(void *, unsigned) { } // okay
+
+template<> template<>
+void N0::X0<void*>::ft1(void *, float) { } // expected-error{{function template specialization}}
+
+namespace N1 {
+  template<> template<>
+  void N0::X0<void*>::ft1(void *, long) { } // expected-error{{enclosing}}
+}
+
 
-void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
+void test_func_template(N0::X0<void *> xvp, void *vp, const void *cvp,
+                        int i, unsigned u) {
   xvp.ft1(vp, cvp);
+  xvp.ft1(vp, i);
+  xvp.ft1(vp, u);
 }
-#endif