(Fixed g++.dg/template/spec25.C issue. Sorry for the churn.) DR374: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374 allows explicit specialization of templates in the enclosing namespace. Because this idiom is currently already accepted with -fpermissive, the fix is easy: Just skip the calls to permerror().
Tested on powerpc64-unknown-linux-gnu. OK for trunk? Thanks again. 2014-11-02 Markus Trippelsdorf <mar...@trippelsdorf.de> DR 374 PR c++/56480 * pt.c (check_explicit_instantiation_namespace): Move above. * pt.c (check_specialization_namespace): Skip permerror() for C++11 and up. Make sure instantiation is valid in current namespace. DR 374 PR c++/56480 * g++.dg/template/spec17.C: Don't dg-error for C++11 and up. * g++.dg/template/spec25.C: Likewise. Adjust regex. * g++.dg/template/spec36.C: Don't dg-error for C++11 and up. * g++.old-deja/g++.ns/template13.C: Likewise. * g++.old-deja/g++.pt/explicit73.C: Likewise. * g++.old-deja/g++.pt/lookup10.C: Likewise. --- gcc/cp/pt.c | 45 +++++++++++++++----------- gcc/testsuite/g++.dg/template/spec17.C | 4 +-- gcc/testsuite/g++.dg/template/spec25.C | 4 +-- gcc/testsuite/g++.dg/template/spec36.C | 4 +-- gcc/testsuite/g++.old-deja/g++.ns/template13.C | 6 ++-- gcc/testsuite/g++.old-deja/g++.pt/explicit73.C | 4 +-- gcc/testsuite/g++.old-deja/g++.pt/lookup10.C | 4 +-- 7 files changed, 39 insertions(+), 32 deletions(-) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2cf10f442f68..8672202f91e2 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -755,6 +755,23 @@ end_explicit_instantiation (void) processing_explicit_instantiation = false; } +/* SPEC is an explicit instantiation. Check that it is valid to + perform this explicit instantiation in the current namespace. */ + +static void +check_explicit_instantiation_namespace (tree spec) +{ + tree ns; + + /* DR 275: An explicit instantiation shall appear in an enclosing + namespace of its template. */ + ns = decl_namespace_context (spec); + if (!is_ancestor (current_namespace, ns)) + permerror (input_location, "explicit instantiation of %qD in namespace %qD " + "(which does not enclose namespace %qD)", + spec, current_namespace, ns); +} + /* An explicit specialization or partial specialization of TMPL is being declared. Check that the namespace in which the specialization is occurring is permissible. Returns false iff it is invalid to @@ -785,29 +802,19 @@ check_specialization_namespace (tree tmpl) return true; else { - permerror (input_location, "specialization of %qD in different namespace", tmpl); - permerror (input_location, " from definition of %q+#D", tmpl); + if (cxx_dialect < cxx11) + { + permerror (input_location, "specialization of %qD in different " + "namespace", tmpl); + permerror (input_location, " from definition of %q+#D", tmpl); + } + else + check_explicit_instantiation_namespace (tmpl); + return false; } } -/* SPEC is an explicit instantiation. Check that it is valid to - perform this explicit instantiation in the current namespace. */ - -static void -check_explicit_instantiation_namespace (tree spec) -{ - tree ns; - - /* DR 275: An explicit instantiation shall appear in an enclosing - namespace of its template. */ - ns = decl_namespace_context (spec); - if (!is_ancestor (current_namespace, ns)) - permerror (input_location, "explicit instantiation of %qD in namespace %qD " - "(which does not enclose namespace %qD)", - spec, current_namespace, ns); -} - /* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */ diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C index 237557684238..70e5be28e05a 100644 --- a/gcc/testsuite/g++.dg/template/spec17.C +++ b/gcc/testsuite/g++.dg/template/spec17.C @@ -1,11 +1,11 @@ // PR c++/16224 namespace io { - template <typename> int foo(); // { dg-error "" } + template <typename> int foo(); // { dg-error "" "" { target { ! c++11 } } } } using namespace io; -template<> int foo<int>(); // { dg-error "" } +template<> int foo<int>(); // { dg-error "" "" { target { ! c++11 } } } int a = foo<int>(); diff --git a/gcc/testsuite/g++.dg/template/spec25.C b/gcc/testsuite/g++.dg/template/spec25.C index 385d19ada0c4..c3836261f6af 100644 --- a/gcc/testsuite/g++.dg/template/spec25.C +++ b/gcc/testsuite/g++.dg/template/spec25.C @@ -1,10 +1,10 @@ namespace N { template <typename T> struct S { - void f() {} // { dg-error "definition" } + void f() {} // { dg-error "definition" "" { target { ! c++11 } } } }; } namespace K { - template <> void N::S<char>::f() {} // { dg-error "different namespace" } + template <> void N::S<char>::f() {} // { dg-error "namespace" } } diff --git a/gcc/testsuite/g++.dg/template/spec36.C b/gcc/testsuite/g++.dg/template/spec36.C index 7e8dc5241d9f..d9c57824b7e5 100644 --- a/gcc/testsuite/g++.dg/template/spec36.C +++ b/gcc/testsuite/g++.dg/template/spec36.C @@ -8,9 +8,9 @@ struct basic_string namespace MyNS { class MyClass { template <typename T> - T test() { } /* { dg-error "from definition" } */ + T test() { } /* { dg-error "from definition" "" { target { ! c++11 } } } */ }; } template <> -basic_string MyNS::MyClass::test() /* { dg-error "specialization of" } */ +basic_string MyNS::MyClass::test() /* { dg-error "specialization of" "" { target { ! c++11 } } } */ { return 1; } diff --git a/gcc/testsuite/g++.old-deja/g++.ns/template13.C b/gcc/testsuite/g++.old-deja/g++.ns/template13.C index a9559c7153b6..21ad61847b73 100644 --- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C +++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C @@ -4,18 +4,18 @@ namespace bar { // trick it to provide some prior declaration template<class T> - void foo(); // { dg-error "definition" } + void foo(); // { dg-error "definition" "" { target { ! c++11 } } } template<class T>class X; // { dg-message "note: previous declaration" } } template <typename T> T const -bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in bar - +bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in bar - { return a; } -template<> void bar::foo<int>() // { dg-error "different namespace" } +template<> void bar::foo<int>() // { dg-error "different namespace" "" { target { ! c++11 } } } { } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C b/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C index 1d83e3468289..bcf4fe7f21a5 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C @@ -7,9 +7,9 @@ // the template namespace N { - template <class T> class foo; // { dg-error "" } referenced below + template <class T> class foo; // { dg-error "" "" { target { ! c++11 } } } referenced below } using namespace N; -template <> class foo<void>; // { dg-error "" } invalid specialization +template <> class foo<void>; // { dg-error "" "" { target { ! c++11 } } } invalid specialization diff --git a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C index 1c04250fc3c0..0ed5dbe42c89 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C @@ -13,8 +13,8 @@ namespace Outer { namespace Core = Core_Real; namespace Core_Real { - template<class T> void Foo (T *) {} // { dg-error "definition" } + template<class T> void Foo (T *) {} // { dg-error "definition" "" { target { ! c++11 } } } } - template<> void Core::Foo<> (Render_Real::Type *) {} // { dg-error "" } + template<> void Core::Foo<> (Render_Real::Type *) {} // { dg-error "" "" { target { ! c++11 } } } } -- 2.1.3 -- Markus