c++/42018 try to reject specialization re-declared in wrong namespace

Submitted by Jonathan Wakely on Oct. 1, 2010, 9:18 p.m.

Details

Message ID AANLkTimZXYODVo2CHZnS=mCitoW_xrG4xia5in6tskg9@mail.gmail.com
State New
Headers show

Commit Message

Jonathan Wakely Oct. 1, 2010, 9:18 p.m.
This patch is my attempt to fix PR c++/42018, but it's wrong, because
it also rejects some valid specializations, causing:

FAIL: g++.old-deja/g++.ns/template12.C (test for excess errors)
Excess errors:
/home/redi/src/gcc/gcc-4.x/gcc/testsuite/g++.old-deja/g++.ns/template12.C:18:47:
error: specialization of 'template<class T> const T bar::foo(const
T&)' in different namespace [-fpermissive]
/home/redi/src/gcc/gcc-4.x/gcc/testsuite/g++.old-deja/g++.ns/template12.C:13:20:
error:   from definition of 'template<class T> const T bar::foo(const
T&)' [-fpermissive]

FAIL: g++.old-deja/g++.pt/memtemp96.C (test for excess errors)
Excess errors:
/home/redi/src/gcc/gcc-4.x/gcc/testsuite/g++.old-deja/g++.pt/memtemp96.C:11:17:
error: specialization of 'template<class T> template<class U> int
A::f(U)' must appear at namespace scope

Can anyone point me in the right direction so that the new test in the
patch fails, but those don't?

Thanks,

Jonathan

Comments

Jason Merrill Oct. 4, 2010, 2:31 p.m.
On 10/01/2010 05:18 PM, Jonathan Wakely wrote:
> Can anyone point me in the right direction so that the new test in the
> patch fails, but those don't?

This restriction has been clarified in the current working paper to read

"An explicit specialization shall be declared in a namespace enclosing 
the specialized template. An explicit specialization whose declarator-id 
is not qualified shall be declared in the nearest enclosing namespace of 
the template, or, if the namespace is inline (7.3.1), any namespace from 
its enclosing namespace set."

...which is what makes g++.ns/template12.C well-formed.

It seems that check_specialization_namespace doesn't have the 
information it needs; it doesn't know whether the specialization was 
declared with a qualified-id (as in template12.C).  I would guess that 
memtemp96.C is failing because we pushed into A<char> as part of parsing 
the declarator, which makes current_scope() give the wrong answer.

It seems you need to do the checking at a higher level.  Maybe in 
check_explicit_specialization.

Jason

Patch hide | download patch | download mbox

Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	(revision 164893)
+++ gcc/cp/pt.c	(working copy)
@@ -1379,6 +1379,11 @@  register_specialization (tree spec, tree
 	}
       else if (DECL_TEMPLATE_SPECIALIZATION (fn))
 	{
+	  /* A specialization must be declared in the same namespace as the
+	     template it is specializing.  */
+	  if (!check_specialization_namespace (tmpl))
+	    return error_mark_node;
+
 	  if (!duplicate_decls (spec, fn, is_friend) && DECL_INITIAL (spec))
 	    /* Dup decl failed, but this is a new definition. Set the
 	       line number so any errors match this new
Index: gcc/testsuite/g++.dg/template/pr42018.C
===================================================================
--- gcc/testsuite/g++.dg/template/pr42018.C	(revision 0)
+++ gcc/testsuite/g++.dg/template/pr42018.C	(revision 0)
@@ -0,0 +1,14 @@ 
+// PR c++/42018
+// { dg-do compile }
+
+template<typename>
+  void foo(void);             // { dg-error "from definition of" }
+
+template<>
+  void foo<int>();
+
+namespace x {
+  template<>
+    void foo<int>() { return; } // { dg-error "in different namespace" }
+}
+