* [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
@ 2014-11-02 12:58 Markus Trippelsdorf
2014-11-02 13:29 ` Markus Trippelsdorf
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-02 12:58 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
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 <markus@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 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..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::S<char>::f() {} // { dg-error "different namespace" }
+ template <> void N::S<char>::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
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 } } }
}
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-02 12:58 [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace Markus Trippelsdorf
@ 2014-11-02 13:29 ` Markus Trippelsdorf
2014-11-02 14:15 ` [PATCH v2] " Markus Trippelsdorf
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-02 13:29 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
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::S<char>::f() {} // { dg-error "different namespace" }
> + template <> void N::S<char>::f() {} // { dg-error "different namespace" "" { target { ! c++11 } } }
> }
Hmm, I think this testcase should actually be rejected even with C++11.
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v2] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-02 13:29 ` Markus Trippelsdorf
@ 2014-11-02 14:15 ` Markus Trippelsdorf
2014-11-03 2:13 ` Jason Merrill
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-02 14:15 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
(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 <markus@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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v2] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-02 14:15 ` [PATCH v2] " Markus Trippelsdorf
@ 2014-11-03 2:13 ` Jason Merrill
2014-11-03 11:27 ` [PATCH v3] " Markus Trippelsdorf
0 siblings, 1 reply; 17+ messages in thread
From: Jason Merrill @ 2014-11-03 2:13 UTC (permalink / raw)
To: Markus Trippelsdorf, gcc-patches
On 11/02/2014 09:15 AM, Markus Trippelsdorf wrote:
> + 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);
In most cases I think DRs should apply to C++98 as well. In this case I
think a pedwarn only with -pedantic in C++98 is appropriate. Let's put
all the logic in check_.... And add a flag to distinguish between
instantiation and specialization.
Jason
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v3] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-03 2:13 ` Jason Merrill
@ 2014-11-03 11:27 ` Markus Trippelsdorf
2014-11-03 14:48 ` Jason Merrill
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-03 11:27 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 2014.11.02 at 21:12 -0500, Jason Merrill wrote:
> On 11/02/2014 09:15 AM, Markus Trippelsdorf wrote:
> > + 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);
>
> In most cases I think DRs should apply to C++98 as well. In this case I
> think a pedwarn only with -pedantic in C++98 is appropriate. Let's put
> all the logic in check_.... And add a flag to distinguish between
> instantiation and specialization.
Thanks for the suggestions. I've implemented them below.
(If someone comes up with a better name than:
check_instant_or_special_namespace I would change it)
BTW both EDG and clang reject g++.dg/template/spec17.C:
namespace io {
template <typename> int foo();
}
using namespace io;
template<> int foo<int>();
But I think it is a reasonable extension to accept it.
Patch tested on powerpc64-unknown-linux-gnu.
2014-11-03 Markus Trippelsdorf <markus@trippelsdorf.de>
DR 374
PR c++/56480
* pt.c (check_explicit_instantiation_namespace)
(check_specialization_namespace): Consolidate into
check_instant_or_special_namespace.
(check_instant_or_special_namespace): pedwarn only with
-pedantic in C++98.
(maybe_process_partial_specialization): Call consolidated
function.
(register_specialization): Likewise.
(do_decl_instantiation): Likewise.
(do_type_instantiation): Likewise.
DR 374
PR c++/56480
* g++.dg/template/spec17.C: Add -pedantic and -pedantic-errors
to dg-options. Don't dg-error for C++11 and up.
* g++.dg/template/spec25.C: Likewise. Adjust regex.
* 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..0eaa6a22f39d 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 ())
+ if (specialization)
{
- 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
- {
- permerror (input_location, "specialization of %qD in different namespace", tmpl);
- permerror (input_location, " from definition of %q+#D", tmpl);
- return false;
- }
-}
-
-/* SPEC is an explicit instantiation. Check that it is valid to
- perform this explicit instantiation in the current namespace. */
+ /* [tmpl.expl.spec]
-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 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;
+ /* DR374: explicit specializations of templates in an enclosing
+ namespace are allowed. */
+ else if (cxx_dialect < cxx11)
+ {
+ pedwarn (input_location, OPT_Wpedantic,
+ "specialization of %qD in different namespace", tmpl);
+ pedwarn (input_location, OPT_Wpedantic,
+ " from definition of %q+#D", tmpl);
+ }
+ }
/* 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);
+ if (!is_ancestor (current_namespace, tpl_ns))
+ permerror (input_location,
+ "explicit instantiation of %qD in namespace %qD "
+ "(which does not enclose namespace %qD)",
+ tmpl, current_namespace, tpl_ns);
+
+ return false;
}
/* The TYPE is being declared. If it is a template type, that means it
@@ -859,7 +860,8 @@ maybe_process_partial_specialization (tree type)
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
- if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type))
+ if (!check_instant_or_special_namespace (
+ CLASSTYPE_TI_TEMPLATE (type), true)
&& !at_namespace_scope_p ())
return error_mark_node;
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
@@ -1454,7 +1456,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
DECL_DELETED_FN (clone)
= DECL_DELETED_FN (fn);
}
- check_specialization_namespace (tmpl);
+ check_instant_or_special_namespace (tmpl, true);
return fn;
}
@@ -1476,7 +1478,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
- && !check_specialization_namespace (tmpl))
+ && !check_instant_or_special_namespace (tmpl, true))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
@@ -19406,7 +19408,7 @@ do_decl_instantiation (tree decl, tree storage)
else
error ("storage class %qD applied to template instantiation", storage);
- check_explicit_instantiation_namespace (result);
+ check_instant_or_special_namespace (result, false);
mark_decl_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result, /*defer_ok=*/1,
@@ -19554,7 +19556,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
return;
}
- check_explicit_instantiation_namespace (TYPE_NAME (t));
+ check_instant_or_special_namespace (TYPE_NAME (t), false);
mark_class_instantiated (t, extern_p);
if (nomem_p)
diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C
index 237557684238..0b2e02bf450c 100644
--- a/gcc/testsuite/g++.dg/template/spec17.C
+++ b/gcc/testsuite/g++.dg/template/spec17.C
@@ -1,11 +1,12 @@
// PR c++/16224
+// { dg-options "-pedantic -pedantic-errors" }
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..c7b51a4beca7 100644
--- a/gcc/testsuite/g++.dg/template/spec25.C
+++ b/gcc/testsuite/g++.dg/template/spec25.C
@@ -1,10 +1,11 @@
+// { dg-options "-pedantic -pedantic-errors" }
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..277a7f6243d5 100644
--- a/gcc/testsuite/g++.dg/template/spec36.C
+++ b/gcc/testsuite/g++.dg/template/spec36.C
@@ -1,5 +1,6 @@
/* PR c++/38089 */
/* { dg-do compile } */
+/* { dg-options "-pedantic -pedantic-errors" } */
struct basic_string
{
@@ -8,9 +9,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..805811fd8b54 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C
@@ -1,10 +1,11 @@
// { dg-do compile }
+// { dg-options "-pedantic -pedantic-errors" }
// Templates defined outside must be declared inside
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" }
}
@@ -15,7 +16,7 @@ bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in b
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..1f5e1e9d8d7b 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/explicit73.C
@@ -1,4 +1,5 @@
// { dg-do assemble }
+// { dg-options "-pedantic -pedantic-errors" }
// by Alexandre Oliva <oliva@dcc.unicamp.br>
@@ -7,9 +8,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..02b21d94cc9b 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup10.C
@@ -1,4 +1,5 @@
// { dg-do assemble }
+// { dg-options "-pedantic -pedantic-errors" }
// Copyright (C) 2000 Free Software Foundation
// Contributed by Nathan Sidwell 3 July 2000 <nathan@codesourcery.com>
@@ -13,8 +14,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 } } }
}
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-03 11:27 ` [PATCH v3] " Markus Trippelsdorf
@ 2014-11-03 14:48 ` Jason Merrill
2014-11-03 18:29 ` Markus Trippelsdorf
2014-11-04 17:10 ` [RFC PATCH v4] " Markus Trippelsdorf
0 siblings, 2 replies; 17+ messages in thread
From: Jason Merrill @ 2014-11-03 14:48 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: gcc-patches
On 11/03/2014 05:27 AM, Markus Trippelsdorf wrote:
> BTW both EDG and clang reject g++.dg/template/spec17.C:
>
> namespace io {
> template <typename> int foo();
> }
> using namespace io;
> template<> int foo<int>();
>
> But I think it is a reasonable extension to accept it.
We should reject it, too. We can only leave out the namespace
qualification with inline namespaces.
> +// { dg-options "-pedantic -pedantic-errors" }
You shouldn't need these dg-options lines; if a testcase has no
dg-options line, -pedantic-errors is the default.
Jason
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH v3] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-03 14:48 ` Jason Merrill
@ 2014-11-03 18:29 ` Markus Trippelsdorf
2014-11-04 17:10 ` [RFC PATCH v4] " Markus Trippelsdorf
1 sibling, 0 replies; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-03 18:29 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 2014.11.03 at 08:47 -0600, Jason Merrill wrote:
> On 11/03/2014 05:27 AM, Markus Trippelsdorf wrote:
> > BTW both EDG and clang reject g++.dg/template/spec17.C:
> >
> > namespace io {
> > template <typename> int foo();
> > }
> > using namespace io;
> > template<> int foo<int>();
> >
> > But I think it is a reasonable extension to accept it.
>
> We should reject it, too. We can only leave out the namespace
> qualification with inline namespaces.
Where would be the best place to check for this issue?
> > +// { dg-options "-pedantic -pedantic-errors" }
>
> You shouldn't need these dg-options lines; if a testcase has no
> dg-options line, -pedantic-errors is the default.
OK. Fixed.
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* [RFC PATCH v4] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-03 14:48 ` Jason Merrill
2014-11-03 18:29 ` Markus Trippelsdorf
@ 2014-11-04 17:10 ` Markus Trippelsdorf
1 sibling, 0 replies; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-04 17:10 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 2014.11.03 at 08:47 -0600, Jason Merrill wrote:
> On 11/03/2014 05:27 AM, Markus Trippelsdorf wrote:
> > BTW both EDG and clang reject g++.dg/template/spec17.C:
> >
> > namespace io {
> > template <typename> int foo();
> > }
> > using namespace io;
> > template<> int foo<int>();
> >
> > But I think it is a reasonable extension to accept it.
>
> We should reject it, too. We can only leave out the namespace
> qualification with inline namespaces.
>
> > +// { dg-options "-pedantic -pedantic-errors" }
>
> You shouldn't need these dg-options lines; if a testcase has no
> dg-options line, -pedantic-errors is the default.
The following patch passes testing and fixes both issues.
Please let me know if you're OK with the general direction, before I
write a full Changelog.
Thanks.
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 320c39f636a2..ddfa5ebfd968 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 2cf10f442f68..5cc320ed2fcf 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 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;
+ /* DR374: explicit specializations of templates in an enclosing
+ namespace are allowed. */
+ else if (cxx_dialect < cxx11)
+ {
+ pedwarn (input_location, OPT_Wpedantic,
+ "specialization of %qD in different namespace", tmpl);
+ pedwarn (input_location, OPT_Wpedantic, " from definition of %q+#D",
+ tmpl);
+ }
+ }
/* 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 "
+ if (!is_ancestor (current_namespace, tpl_ns))
+ permerror (input_location,
+ "explicit instantiation of %qD in namespace %qD "
"(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ tmpl, current_namespace, tpl_ns);
+
+ return false;
}
/* The TYPE is being declared. If it is a template type, that means it
@@ -859,7 +860,8 @@ maybe_process_partial_specialization (tree type)
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
- if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type))
+ if (!check_instant_or_special_namespace (
+ CLASSTYPE_TI_TEMPLATE (type), true)
&& !at_namespace_scope_p ())
return error_mark_node;
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
@@ -1338,14 +1340,22 @@ is_specialization_of_friend (tree decl, tree friend_decl)
is actually just a friend declaration. Returns SPEC, or an
equivalent prior declaration, if available.
+ FLAGS is a bitmask consisting of the following flags:
+
+ 2: The function has a definition.
+ 4: The function is a friend.
+ 8: The function has explicit namespace qualification.
+
We also store instantiations of field packs in the hash table, even
though they are not themselves templates, to make lookup easier. */
static tree
register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
- hashval_t hash)
+ hashval_t hash, int flags)
{
tree fn;
+ int have_def = flags & 2;
+ int in_namespace = flags & 8;
spec_entry **slot = NULL;
spec_entry elt;
@@ -1454,7 +1464,15 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
DECL_DELETED_FN (clone)
= DECL_DELETED_FN (fn);
}
- check_specialization_namespace (tmpl);
+
+
+ if (!is_associated_namespace (current_namespace,
+ decl_namespace_context (tmpl))
+ && !have_def && !in_namespace)
+ error ("no function template matches function "
+ "template specialization");
+
+ check_instant_or_special_namespace (tmpl, true);
return fn;
}
@@ -1476,7 +1494,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
- && !check_specialization_namespace (tmpl))
+ && !check_instant_or_special_namespace (tmpl, true))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
@@ -2347,6 +2365,7 @@ check_template_variable (tree decl)
2: The function has a definition.
4: The function is a friend.
+ 8: The function has explicit namespace qualification.
The TEMPLATE_COUNT is the number of references to qualifying
template classes that appeared in the name of the function. For
@@ -2741,7 +2760,7 @@ check_explicit_specialization (tree declarator,
DECL_CONTEXT (parm) = result;
}
return register_specialization (tmpl, gen_tmpl, targs,
- is_friend, 0);
+ is_friend, 0, 0);
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
@@ -2821,7 +2840,7 @@ check_explicit_specialization (tree declarator,
/* Register this specialization so that we can find it
again. */
- decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0);
+ decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0, flags);
/* A 'structor should already have clones. */
gcc_assert (decl == error_mark_node
@@ -4930,7 +4949,7 @@ push_template_decl_real (tree decl, bool is_friend)
register_specialization (new_tmpl,
most_general_template (tmpl),
args,
- is_friend, 0);
+ is_friend, 0, 0);
return decl;
}
@@ -8661,7 +8680,7 @@ tsubst_friend_function (tree decl, tree args)
DECL_TI_ARGS (spec));
register_specialization
- (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+ (spec, new_template, DECL_TI_ARGS (spec), true, 0, 0);
}
DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
@@ -10587,7 +10606,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
- false, hash);
+ false, hash, 0);
}
break;
@@ -10795,7 +10814,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
SET_DECL_IMPLICIT_INSTANTIATION (r);
tree new_r
- = register_specialization (r, gen_tmpl, argvec, false, hash);
+ = register_specialization (r, gen_tmpl, argvec, false, hash, 0);
if (new_r != r)
/* We instantiated this while substituting into
the type earlier (template/friend54.C). */
@@ -11067,7 +11086,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
SET_ARGUMENT_PACK_ARGS (pack, vec);
SET_ARGUMENT_PACK_ARGS (tpack, expanded_types);
TREE_TYPE (pack) = tpack;
- register_specialization (pack, t, args, false, 0);
+ register_specialization (pack, t, args, false, 0, 0);
}
}
break;
@@ -11293,7 +11312,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
processing here. */
DECL_EXTERNAL (r) = 1;
- register_specialization (r, gen_tmpl, argvec, false, hash);
+ register_specialization (r, gen_tmpl, argvec, false, hash, 0);
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
@@ -19406,7 +19425,7 @@ do_decl_instantiation (tree decl, tree storage)
else
error ("storage class %qD applied to template instantiation", storage);
- check_explicit_instantiation_namespace (result);
+ check_instant_or_special_namespace (result, false);
mark_decl_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result, /*defer_ok=*/1,
@@ -19554,7 +19573,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
return;
}
- check_explicit_instantiation_namespace (TYPE_NAME (t));
+ check_instant_or_special_namespace (TYPE_NAME (t), false);
mark_class_instantiated (t, extern_p);
if (nomem_p)
diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C
index 237557684238..849178920012 100644
--- a/gcc/testsuite/g++.dg/template/spec17.C
+++ b/gcc/testsuite/g++.dg/template/spec17.C
@@ -1,7 +1,7 @@
// PR c++/16224
namespace io {
- template <typename> int foo(); // { dg-error "" }
+ template <typename> int foo(); // { dg-error "" "" { target { ! c++11 } } }
}
using namespace io;
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..0c99e74dc466 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C
@@ -4,7 +4,7 @@ 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" }
}
@@ -15,7 +15,7 @@ bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in b
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 } } }
}
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-12 11:54 ` Markus Trippelsdorf
@ 2014-11-18 21:46 ` Jason Merrill
0 siblings, 0 replies; 17+ messages in thread
From: Jason Merrill @ 2014-11-18 21:46 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: gcc-patches
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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 21:01 ` Jason Merrill
@ 2014-11-12 11:54 ` Markus Trippelsdorf
2014-11-18 21:46 ` Jason Merrill
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-12 11:54 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
On 2014.11.11 at 15:39 -0500, Jason Merrill wrote:
> 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 foo<void>; // { dg-error "" } invalid specialization
> >>>>> +template <> class foo<void>; // { dg-error "" "" { target { ! c++11 } } } invalid specialization
> >>>>
> >>>> This should still get an error in C++11 mode.
>
> In any case, I think the standard is clear that this should get an
> error, and the EDG and Clang implementers agree with me.
Looking at it, I don't see how this could be easily handled (for class
templates). Possibly already in cp_parser_explicit_specialization() from
parser.c.
For function templates it's easy (and my patch only handles this case):
#0 check_explicit_specialization (declarator=<optimized out>, declarator@entry=0x7ffff73b0b18, decl=0x7ffff73bb798, template_count=template_count@entry=0,
flags=flags@entry=0) at ../../gcc/gcc/cp/pt.c:2835
#1 0x000000000053f158 in grokfndecl (ctype=0x0, type=0x7ffff7295150, declarator=<optimized out>, parms=<optimized out>, orig_declarator=<optimized out>,
virtualp=<optimized out>, flags=NO_SPECIAL, quals=<optimized out>, rqual=<optimized out>, raises=0x0, check=1, friendp=0, publicp=<optimized out>,
inlinep=<optimized out>, sfk=sfk_none, funcdef_flag=false, template_count=0, in_namespace=0x0, attrlist=0x7fffffffdcb8, location=8492) at ../../gcc/gcc/cp/decl.c:7859
#2 0x00000000005fc652 in grokdeclarator (declarator=0x1b258b0, declspecs=0x7fffffffddd0, decl_context=NORMAL, initialized=32, initialized@entry=0, attrlist=0x0,
attrlist@entry=0x7fffffffdcb8) at ../../gcc/gcc/cp/decl.c:10929
#3 0x00000000005fe3e7 in start_decl (declarator=declarator@entry=0x1b25900, declspecs=declspecs@entry=0x7fffffffddd0, initialized=initialized@entry=0,
attributes=attributes@entry=0x0, prefix_attributes=prefix_attributes@entry=0x0, pushed_scope_p=pushed_scope_p@entry=0x7fffffffdd58) at ../../gcc/gcc/cp/decl.c:4582
#4 0x00000000006faa90 in cp_parser_init_declarator (parser=0x7ffff73c9000, decl_specifiers=0x7fffffffddd0, checks=0x0, function_definition_allowed_p=<optimized out>,
member_p=<optimized out>, declares_class_or_enum=<optimized out>, function_definition_p=0x7fffffffddcb, maybe_range_for_decl=0x0) at ../../gcc/gcc/cp/parser.c:17041
#5 0x00000000006fb81a in cp_parser_single_declaration (parser=0x7ffff73c9000, checks=0x0, member_p=member_p@entry=false, explicit_specialization_p=32,
explicit_specialization_p@entry=true, friend_p=0x7ffff727c930) at ../../gcc/gcc/cp/parser.c:23679
#6 0x00000000006fc42a in cp_parser_explicit_specialization (parser=parser@entry=0x7ffff73c9000) at ../../gcc/gcc/cp/parser.c:14515
For class templates it's another path.
#0 maybe_process_partial_specialization (type=0x7ffff73d45e8) at ../../gcc/gcc/cp/pt.c:868
#1 0x00000000005fdf62 in shadow_tag (declspecs=0x7fffffffdaf0) at ../../gcc/gcc/cp/decl.c:4487
#2 0x00000000006fb6e8 in cp_parser_single_declaration (parser=0x7ffff73e2000, checks=0x0, member_p=88, member_p@entry=false,
explicit_specialization_p=explicit_specialization_p@entry=true, friend_p=0x0) at ../../gcc/gcc/cp/parser.c:23626
#3 0x00000000006fc42a in cp_parser_explicit_specialization (parser=parser@entry=0x7ffff73e2000) at ../../gcc/gcc/cp/parser.c:14515
Anyway, I will defer working on this until next stage1, because I don't
have time to implement this before stage1 closes on Saturday.
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 20:10 ` Markus Trippelsdorf
@ 2014-11-11 21:01 ` Jason Merrill
2014-11-12 11:54 ` Markus Trippelsdorf
0 siblings, 1 reply; 17+ messages in thread
From: Jason Merrill @ 2014-11-11 21:01 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: gcc-patches
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 foo<void>; // { dg-error "" } invalid specialization
>>>>> +template <> class foo<void>; // { 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 18:43 ` Jason Merrill
@ 2014-11-11 20:10 ` Markus Trippelsdorf
2014-11-11 21:01 ` Jason Merrill
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-11 20:10 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
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 foo<void>; // { dg-error "" } invalid specialization
> >>> +template <> class foo<void>; // { 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 15:41 ` Markus Trippelsdorf
2014-11-11 18:36 ` Mike Stump
@ 2014-11-11 18:43 ` Jason Merrill
2014-11-11 20:10 ` Markus Trippelsdorf
1 sibling, 1 reply; 17+ messages in thread
From: Jason Merrill @ 2014-11-11 18:43 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: gcc-patches
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 foo<void>; // { dg-error "" } invalid specialization
>>> +template <> class foo<void>; // { 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 15:41 ` Markus Trippelsdorf
@ 2014-11-11 18:36 ` Mike Stump
2014-11-11 18:43 ` Jason Merrill
1 sibling, 0 replies; 17+ messages in thread
From: Mike Stump @ 2014-11-11 18:36 UTC (permalink / raw)
To: Markus Trippelsdorf; +Cc: Jason Merrill, gcc-patches
On Nov 11, 2014, at 7:37 AM, Markus Trippelsdorf <markus@trippelsdorf.de> wrote:
> Both EGG and clang currently accept it.
EDG… I think you mean.
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-11 15:13 ` Jason Merrill
@ 2014-11-11 15:41 ` Markus Trippelsdorf
2014-11-11 18:36 ` Mike Stump
2014-11-11 18:43 ` Jason Merrill
0 siblings, 2 replies; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-11 15:41 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
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 foo<void>; // { dg-error "" } invalid specialization
> > +template <> class foo<void>; // { 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
2014-11-08 11:57 [PATCH] " Markus Trippelsdorf
@ 2014-11-11 15:13 ` Jason Merrill
2014-11-11 15:41 ` Markus Trippelsdorf
0 siblings, 1 reply; 17+ messages in thread
From: Jason Merrill @ 2014-11-11 15:13 UTC (permalink / raw)
To: Markus Trippelsdorf, gcc-patches
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 foo<void>; // { dg-error "" } invalid specialization
> +template <> class foo<void>; // { 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
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace.
@ 2014-11-08 11:57 Markus Trippelsdorf
2014-11-11 15:13 ` Jason Merrill
0 siblings, 1 reply; 17+ messages in thread
From: Markus Trippelsdorf @ 2014-11-08 11:57 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
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 <markus@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 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;
+ /* DR374: explicit specializations of templates in an enclosing
+ namespace are allowed. */
+ else if (cxx_dialect < cxx11)
+ {
+ pedwarn (input_location, OPT_Wpedantic,
+ "specialization of %qD in different namespace", tmpl);
+ pedwarn (input_location, OPT_Wpedantic, " from definition of %q+#D",
+ tmpl);
+ }
+ }
/* 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 "
+ if (!is_ancestor (current_namespace, tpl_ns))
+ permerror (input_location,
+ "explicit instantiation of %qD in namespace %qD "
"(which does not enclose namespace %qD)",
- spec, current_namespace, ns);
+ tmpl, current_namespace, tpl_ns);
+
+ return false;
}
/* The TYPE is being declared. If it is a template type, that means it
@@ -859,7 +860,8 @@ maybe_process_partial_specialization (tree type)
if (CLASSTYPE_IMPLICIT_INSTANTIATION (type)
&& !COMPLETE_TYPE_P (type))
{
- if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type))
+ if (!check_instant_or_special_namespace (
+ CLASSTYPE_TI_TEMPLATE (type), true)
&& !at_namespace_scope_p ())
return error_mark_node;
SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type);
@@ -1338,14 +1340,22 @@ is_specialization_of_friend (tree decl, tree friend_decl)
is actually just a friend declaration. Returns SPEC, or an
equivalent prior declaration, if available.
+ FLAGS is a bitmask consisting of the following flags:
+
+ 2: The function has a definition.
+ 4: The function is a friend.
+ 8: The function has explicit namespace qualification.
+
We also store instantiations of field packs in the hash table, even
though they are not themselves templates, to make lookup easier. */
static tree
register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
- hashval_t hash)
+ hashval_t hash, int flags)
{
tree fn;
+ int have_def = flags & 2;
+ int in_namespace = flags & 8;
spec_entry **slot = NULL;
spec_entry elt;
@@ -1454,7 +1464,15 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
DECL_DELETED_FN (clone)
= DECL_DELETED_FN (fn);
}
- check_specialization_namespace (tmpl);
+
+
+ if (!is_associated_namespace (current_namespace,
+ decl_namespace_context (tmpl))
+ && !have_def && !in_namespace)
+ error ("no function template matches function "
+ "template specialization");
+
+ check_instant_or_special_namespace (tmpl, true);
return fn;
}
@@ -1476,7 +1494,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
/* A specialization must be declared in the same namespace as the
template it is specializing. */
if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec)
- && !check_specialization_namespace (tmpl))
+ && !check_instant_or_special_namespace (tmpl, true))
DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */)
@@ -2347,6 +2365,7 @@ check_template_variable (tree decl)
2: The function has a definition.
4: The function is a friend.
+ 8: The function has explicit namespace qualification.
The TEMPLATE_COUNT is the number of references to qualifying
template classes that appeared in the name of the function. For
@@ -2741,7 +2760,7 @@ check_explicit_specialization (tree declarator,
DECL_CONTEXT (parm) = result;
}
return register_specialization (tmpl, gen_tmpl, targs,
- is_friend, 0);
+ is_friend, 0, 0);
}
/* Set up the DECL_TEMPLATE_INFO for DECL. */
@@ -2821,7 +2840,7 @@ check_explicit_specialization (tree declarator,
/* Register this specialization so that we can find it
again. */
- decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0);
+ decl = register_specialization (decl, gen_tmpl, targs, is_friend, 0, flags);
/* A 'structor should already have clones. */
gcc_assert (decl == error_mark_node
@@ -4930,7 +4949,7 @@ push_template_decl_real (tree decl, bool is_friend)
register_specialization (new_tmpl,
most_general_template (tmpl),
args,
- is_friend, 0);
+ is_friend, 0, 0);
return decl;
}
@@ -8688,7 +8707,7 @@ tsubst_friend_function (tree decl, tree args)
DECL_TI_ARGS (spec));
register_specialization
- (spec, new_template, DECL_TI_ARGS (spec), true, 0);
+ (spec, new_template, DECL_TI_ARGS (spec), true, 0, 0);
}
DECL_TEMPLATE_INSTANTIATIONS (old_decl) = NULL_TREE;
@@ -10614,7 +10633,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
/* Record this non-type partial instantiation. */
register_specialization (r, t,
DECL_TI_ARGS (DECL_TEMPLATE_RESULT (r)),
- false, hash);
+ false, hash, 0);
}
break;
@@ -10822,7 +10841,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
SET_DECL_IMPLICIT_INSTANTIATION (r);
tree new_r
- = register_specialization (r, gen_tmpl, argvec, false, hash);
+ = register_specialization (r, gen_tmpl, argvec, false, hash, 0);
if (new_r != r)
/* We instantiated this while substituting into
the type earlier (template/friend54.C). */
@@ -11094,7 +11113,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
SET_ARGUMENT_PACK_ARGS (pack, vec);
SET_ARGUMENT_PACK_ARGS (tpack, expanded_types);
TREE_TYPE (pack) = tpack;
- register_specialization (pack, t, args, false, 0);
+ register_specialization (pack, t, args, false, 0, 0);
}
}
break;
@@ -11320,7 +11339,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
processing here. */
DECL_EXTERNAL (r) = 1;
- register_specialization (r, gen_tmpl, argvec, false, hash);
+ register_specialization (r, gen_tmpl, argvec, false, hash, 0);
DECL_TEMPLATE_INFO (r) = build_template_info (tmpl, argvec);
SET_DECL_IMPLICIT_INSTANTIATION (r);
}
@@ -19433,7 +19452,7 @@ do_decl_instantiation (tree decl, tree storage)
else
error ("storage class %qD applied to template instantiation", storage);
- check_explicit_instantiation_namespace (result);
+ check_instant_or_special_namespace (result, false);
mark_decl_instantiated (result, extern_p);
if (! extern_p)
instantiate_decl (result, /*defer_ok=*/1,
@@ -19581,7 +19600,7 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
return;
}
- check_explicit_instantiation_namespace (TYPE_NAME (t));
+ check_instant_or_special_namespace (TYPE_NAME (t), false);
mark_class_instantiated (t, extern_p);
if (nomem_p)
diff --git a/gcc/testsuite/g++.dg/template/spec17.C b/gcc/testsuite/g++.dg/template/spec17.C
index 237557684238..849178920012 100644
--- a/gcc/testsuite/g++.dg/template/spec17.C
+++ b/gcc/testsuite/g++.dg/template/spec17.C
@@ -1,7 +1,7 @@
// PR c++/16224
namespace io {
- template <typename> int foo(); // { dg-error "" }
+ template <typename> int foo(); // { dg-error "" "" { target { ! c++11 } } }
}
using namespace io;
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..0c99e74dc466 100644
--- a/gcc/testsuite/g++.old-deja/g++.ns/template13.C
+++ b/gcc/testsuite/g++.old-deja/g++.ns/template13.C
@@ -4,7 +4,7 @@ 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" }
}
@@ -15,7 +15,7 @@ bar::foo(T const &a) // { dg-error "" "" { xfail *-*-* } } not declared in b
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 } } }
}
--
Markus
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2014-11-18 21:10 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-11-02 12:58 [PATCH] Fix PR56480 aka DR374. Allow explicit specialization in enclosing namespace Markus Trippelsdorf
2014-11-02 13:29 ` Markus Trippelsdorf
2014-11-02 14:15 ` [PATCH v2] " Markus Trippelsdorf
2014-11-03 2:13 ` Jason Merrill
2014-11-03 11:27 ` [PATCH v3] " Markus Trippelsdorf
2014-11-03 14:48 ` Jason Merrill
2014-11-03 18:29 ` Markus Trippelsdorf
2014-11-04 17:10 ` [RFC PATCH v4] " Markus Trippelsdorf
2014-11-08 11:57 [PATCH] " Markus Trippelsdorf
2014-11-11 15:13 ` Jason Merrill
2014-11-11 15:41 ` Markus Trippelsdorf
2014-11-11 18:36 ` Mike Stump
2014-11-11 18:43 ` Jason Merrill
2014-11-11 20:10 ` Markus Trippelsdorf
2014-11-11 21:01 ` Jason Merrill
2014-11-12 11:54 ` Markus Trippelsdorf
2014-11-18 21:46 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).