Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 11/12/2014 06:53 AM, Markus Trippelsdorf wrote: Anyway, I will defer working on this until next stage1, because I don't have time to implement this before stage1 closes on Saturday. I think this should be OK for stage 3, especially given that you first sent the patch before the end of stage 1. Jason
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 11/08/2014 06:57 AM, Markus Trippelsdorf wrote: +++ 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization This should still get an error in C++11 mode. I think we also need to test this: namespace A { namespace B { template class T void f(); } using namespace B; } template void A::f(); // { dg-error } I think your code won't catch this, because we need to know what the explicit namespace was, not just whether there was one. Can we handle this in check_explicit_specialization rather than all the way down in register_specialization? Jason
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 2014.11.11 at 10:11 -0500, Jason Merrill wrote: On 11/08/2014 06:57 AM, Markus Trippelsdorf wrote: +++ 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization This should still get an error in C++11 mode. Both EGG and clang currently accept it. I think we also need to test this: namespace A { namespace B { template class T void f(); } using namespace B; } template void A::f(); // { dg-error } I think your code won't catch this, because we need to know what the explicit namespace was, not just whether there was one. This is already caught: error: template-id ‘f’ for ‘void A::f()’ does not match any template declaration Can we handle this in check_explicit_specialization rather than all the way down in register_specialization? I will look into it. -- Markus
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On Nov 11, 2014, at 7:37 AM, Markus Trippelsdorf mar...@trippelsdorf.de wrote: Both EGG and clang currently accept it. EDG… I think you mean.
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 11/11/2014 10:37 AM, Markus Trippelsdorf wrote: On 2014.11.11 at 10:11 -0500, Jason Merrill wrote: On 11/08/2014 06:57 AM, Markus Trippelsdorf wrote: +++ 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization This should still get an error in C++11 mode. Both EGG and clang currently accept it. EDG rejects it in strict mode. Jason
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 2014.11.11 at 13:39 -0500, Jason Merrill wrote: On 11/11/2014 10:37 AM, Markus Trippelsdorf wrote: On 2014.11.11 at 10:11 -0500, Jason Merrill wrote: On 11/08/2014 06:57 AM, Markus Trippelsdorf wrote: +++ 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization This should still get an error in C++11 mode. Both EGG and clang currently accept it. EDG rejects it in strict mode. They also reject g++.dg/template/spec36.C and g++.old-deja/g++.pt/lookup10.C with -strict-ansi -std=c++11. Which is kind of ironical given that two of their employees worked on the issue: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2010/n3064.pdf -- Markus
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 11/11/2014 03:06 PM, Markus Trippelsdorf wrote: On 2014.11.11 at 13:39 -0500, Jason Merrill wrote: On 11/11/2014 10:37 AM, Markus Trippelsdorf wrote: On 2014.11.11 at 10:11 -0500, Jason Merrill wrote: On 11/08/2014 06:57 AM, Markus Trippelsdorf wrote: +++ 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization This should still get an error in C++11 mode. Both EGG and clang currently accept it. EDG rejects it in strict mode. They also reject g++.dg/template/spec36.C and g++.old-deja/g++.pt/lookup10.C with -strict-ansi -std=c++11. Which is kind of ironical given that two of their employees worked on the issue: Yeah, sometimes implementation lags behind drafting... :) In any case, I think the standard is clear that this should get an error, and the EDG and Clang implementers agree with me. Jason
[PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
DR374: http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#374 allows explicit specialization of templates in the enclosing namespace. This is implemented by consolidating check_specialization_namespace and check_explicit_instantiation_namespace into a new function and pedwarning only for C++98. Only explicit namespace qualifications are accepted, so g++.dg/template/spec17.C is rejected. To check for this condition have_def and in_namespace are passed through to register_specialization() by using a bitmask. Tested on powerpc64-unknown-linux-gnu. (Also tested by running the Boost testsuite and building Firefox.) OK for trunk? Thanks again. 2014-11-08 Markus Trippelsdorf mar...@trippelsdorf.de gcc/cp/ChangeLog: * decl.c (grokfndecl): Also pass through in_namespace. * pt.c (check_instant_or_special_namespace): Consolidate check_specialization_namespace and check_explicit_instantiation_namespace. pedwarn only for C++98. (maybe_process_partial_specialization): Call consolidated function. (register_specialization): Add flag. Only accept explicit namespace qualification. (check_template_variable): Call consolidated function. (check_explicit_specialization): Likewise (push_template_decl_real): Likewise (tsubst_friend_function): Likewise. (tsubst_decl): Likewise. (do_decl_instantiation): Likewise. (do_type_instantiation): Likewise. gcc/testsuite/ChangeLog: * 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. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4abc1011e61e..931bf2c2aafc 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7855,7 +7855,8 @@ grokfndecl (tree ctype, decl = check_explicit_specialization (orig_declarator, decl, template_count, 2 * funcdef_flag + - 4 * (friendp != 0)); + 4 * (friendp != 0) + + 8 * (in_namespace != 0)); if (decl == error_mark_node) return NULL_TREE; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index fa9652f748c2..64f72e50880d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -755,57 +755,58 @@ end_explicit_instantiation (void) processing_explicit_instantiation = false; } -/* 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 - specialize TMPL in the current namespace. */ +/* If specialization is true, 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 specialize TMPL in the current namespace. + If specialization is false, TMPL is an explicit instantiation. + Check that it is valid to perform this explicit instantiation in + the current namespace. */ static bool -check_specialization_namespace (tree tmpl) +check_instant_or_special_namespace (tree tmpl, bool specialization) { tree tpl_ns = decl_namespace_context (tmpl); - /* [tmpl.expl.spec] - - An explicit specialization shall be declared in the namespace of - which the template is a member, or, for member templates, in the - namespace of which the enclosing class or enclosing class - template is a member. An explicit specialization of a member - function, member class or static data member of a class template - shall be declared in the namespace of which the class template is - a member. */ - if (current_scope() != DECL_CONTEXT (tmpl) - !at_namespace_scope_p ()) -{ - error (specialization of %qD must appear at namespace scope, tmpl); - return false; -} - if (is_associated_namespace (current_namespace, tpl_ns)) -/* Same or super-using namespace. */ -return true; - else + if (specialization) { - permerror (input_location, specialization of %qD in different namespace, tmpl); - permerror (input_location, from definition of %q+#D, tmpl); - return false; -} -} + /* [tmpl.expl.spec] -/* 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; +An explicit specialization shall be declared in the namespace of +which the template is a member, or, for member templates, in the +namespace of
[PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
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() for C++11 and up. Tested on powerpc64-unknown-linux-gnu. OK for trunk? Thanks. 2014-11-02 Markus Trippelsdorf mar...@trippelsdorf.de DR 374 PR c++/56480 * pt.c (check_specialization_namespace): Skip permerror() for C++11 and up. 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. * g++.dg/template/spec36.C: Likewise. * g++.old-deja/g++.ns/template13.C: Likewise. * g++.old-deja/g++.pt/explicit73.C: Likewise. * g++.old-deja/g++.pt/lookup10.C: Likewise. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 2cf10f442f68..09a545496fa8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -785,8 +785,12 @@ 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); + } return false; } } 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 fooint(); // { dg-error } +template int fooint(); // { dg-error { target { ! c++11 } } } int a = fooint(); diff --git a/gcc/testsuite/g++.dg/template/spec25.C b/gcc/testsuite/g++.dg/template/spec25.C index 385d19ada0c4..d41c5fce1297 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::Schar::f() {} // { dg-error different namespace } + template void N::Schar::f() {} // { dg-error different namespace { target { ! c++11 } } } } 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 templateclass T - void foo(); // { dg-error definition } + void foo(); // { dg-error definition { target { ! c++11 } } } templateclass Tclass 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::fooint() // { dg-error different namespace } +template void bar::fooint() // { 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 foovoid; // { dg-error } invalid specialization +template class foovoid; // { dg-error { target { ! c++11 } } } invalid specialization diff --git
Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
On 2014.11.02 at 13:58 +0100, Markus Trippelsdorf wrote: diff --git a/gcc/testsuite/g++.dg/template/spec25.C b/gcc/testsuite/g++.dg/template/spec25.C index 385d19ada0c4..d41c5fce1297 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::Schar::f() {} // { dg-error different namespace } + template void N::Schar::f() {} // { dg-error different namespace { target { ! c++11 } } } } Hmm, I think this testcase should actually be rejected even with C++11. -- Markus