From: Douglas Gregor Date: Thu, 8 Oct 2009 15:54:21 +0000 (+0000) Subject: Don't complain about out-of-line explicit specializations of member X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=741fab61570f145a52b808a6824841c41e892c28;p=clang Don't complain about out-of-line explicit specializations of member 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 --- diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 267eea8a1b..9163aba9f5 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -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(); diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp index 9c6c5edc50..64856605a0 100644 --- a/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp +++ b/test/CXX/temp/temp.spec/temp.expl.spec/p2.cpp @@ -62,7 +62,7 @@ struct X0 { // expected-note 2{{here}} // expected-error{{base specifier}} template - void ft1(T t, U u); + void ft1(T t, U u); // expected-note{{explicitly specialized}} }; } @@ -203,14 +203,37 @@ N0::X0::InnerTemplate inner_template1; // expected-error{{incomplete}} N0::X0::InnerTemplate inner_template2; N0::X0::InnerTemplate 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::ft1(void*, const void*) { } +namespace N0 { + template<> + template<> + void X0::ft1(void*, const void*) { } + + template<> template<> + void X0::ft1(void *, int); + + template<> template<> + void X0::ft1(void *, unsigned); + + template<> template<> + void X0::ft1(void *, long); +} + +template<> template<> +void N0::X0::ft1(void *, unsigned) { } // okay + +template<> template<> +void N0::X0::ft1(void *, float) { } // expected-error{{function template specialization}} + +namespace N1 { + template<> template<> + void N0::X0::ft1(void *, long) { } // expected-error{{enclosing}} +} + -void test_func_template(X0 xvp, void *vp, const void *cvp) { +void test_func_template(N0::X0 xvp, void *vp, const void *cvp, + int i, unsigned u) { xvp.ft1(vp, cvp); + xvp.ft1(vp, i); + xvp.ft1(vp, u); } -#endif