]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/8355 (befriending a template specialization in another namespace)
authorMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 19 Nov 2005 02:25:55 +0000 (02:25 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Sat, 19 Nov 2005 02:25:55 +0000 (02:25 +0000)
PR c++/8355
* decl.c (grokfndecl): Set up DECL_TEMPLATE_INFO before calling
set_decl_namespace.
* name-lookup.c (set_decl_namespace):
PR c++/8355
* g++.dg/template/friend39.C: New test.

From-SVN: r107207

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/name-lookup.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/friend39.C [new file with mode: 0644]

index 42e44da26ba07ef0f064735be21040d2ead76938..bd711f3aac12a875396788eadbc4beeed56d26f4 100644 (file)
@@ -1,3 +1,10 @@
+2005-11-18  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/8355
+       * decl.c (grokfndecl): Set up DECL_TEMPLATE_INFO before calling
+       set_decl_namespace.
+       * name-lookup.c (set_decl_namespace): 
+
 2005-11-18  Mike Stump  <mrs@apple.com>
 
        * cp-objcp-common.h (LANG_HOOKS_LOOKUP_NAME): Add.
index 30d81a727f5a624d8940a55b85ca18237c9c082f..55e26b97ff65c2c6cb8a0e95f460e12093462257 100644 (file)
@@ -5696,7 +5696,6 @@ grokfndecl (tree ctype,
 {
   tree decl;
   int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
-  int has_default_arg = 0;
   tree t;
 
   if (raises)
@@ -5708,6 +5707,67 @@ grokfndecl (tree ctype,
   if (TYPE_VOLATILE (type))
     TREE_THIS_VOLATILE (decl) = 1;
 
+  if (friendp
+      && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
+    {
+      if (funcdef_flag)
+       error
+         ("defining explicit specialization %qD in friend declaration",
+          orig_declarator);
+      else
+       {
+         tree fns = TREE_OPERAND (orig_declarator, 0);
+         tree args = TREE_OPERAND (orig_declarator, 1);
+
+         if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+           {
+             /* Something like `template <class T> friend void f<T>()'.  */
+             error ("invalid use of template-id %qD in declaration "
+                    "of primary template",
+                    orig_declarator);
+             return NULL_TREE;
+           }
+
+
+         /* A friend declaration of the form friend void f<>().  Record
+            the information in the TEMPLATE_ID_EXPR.  */
+         SET_DECL_IMPLICIT_INSTANTIATION (decl);
+
+         if (TREE_CODE (fns) == COMPONENT_REF)
+           {
+             /* Due to bison parser ickiness, we will have already looked
+                up an operator_name or PFUNCNAME within the current class
+                (see template_id in parse.y). If the current class contains
+                such a name, we'll get a COMPONENT_REF here. Undo that.  */
+
+             gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
+                         == current_class_type);
+             fns = TREE_OPERAND (fns, 1);
+           }
+         gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
+                     || TREE_CODE (fns) == OVERLOAD);
+         DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
+
+         for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
+           if (TREE_PURPOSE (t)
+               && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
+           {
+             error ("default arguments are not allowed in declaration "
+                    "of friend template specialization %qD",
+                    decl);
+             return NULL_TREE;
+           }
+
+         if (inlinep)
+           {
+             error ("%<inline%> is not allowed in declaration of friend "
+                    "template specialization %qD",
+                    decl);
+             return NULL_TREE;
+           }
+       }
+    }
+
   /* If this decl has namespace scope, set that up.  */
   if (in_namespace)
     set_decl_namespace (decl, in_namespace, friendp);
@@ -5828,73 +5888,6 @@ grokfndecl (tree ctype,
   if (ctype && decl_function_context (decl))
     DECL_NO_STATIC_CHAIN (decl) = 1;
 
-  for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
-    if (TREE_PURPOSE (t)
-       && TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
-      {
-       has_default_arg = 1;
-       break;
-      }
-
-  if (friendp
-      && TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
-    {
-      if (funcdef_flag)
-       error
-         ("defining explicit specialization %qD in friend declaration",
-          orig_declarator);
-      else
-       {
-         tree fns = TREE_OPERAND (orig_declarator, 0);
-         tree args = TREE_OPERAND (orig_declarator, 1);
-
-         if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-           {
-             /* Something like `template <class T> friend void f<T>()'.  */
-             error ("invalid use of template-id %qD in declaration "
-                    "of primary template",
-                    orig_declarator);
-             return NULL_TREE;
-           }
-
-
-         /* A friend declaration of the form friend void f<>().  Record
-            the information in the TEMPLATE_ID_EXPR.  */
-         SET_DECL_IMPLICIT_INSTANTIATION (decl);
-
-         if (TREE_CODE (fns) == COMPONENT_REF)
-           {
-             /* Due to bison parser ickiness, we will have already looked
-                up an operator_name or PFUNCNAME within the current class
-                (see template_id in parse.y). If the current class contains
-                such a name, we'll get a COMPONENT_REF here. Undo that.  */
-
-             gcc_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
-                         == current_class_type);
-             fns = TREE_OPERAND (fns, 1);
-           }
-         gcc_assert (TREE_CODE (fns) == IDENTIFIER_NODE
-                     || TREE_CODE (fns) == OVERLOAD);
-         DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
-
-         if (has_default_arg)
-           {
-             error ("default arguments are not allowed in declaration "
-                    "of friend template specialization %qD",
-                    decl);
-             return NULL_TREE;
-           }
-
-         if (inlinep)
-           {
-             error ("%<inline%> is not allowed in declaration of friend "
-                    "template specialization %qD",
-                    decl);
-             return NULL_TREE;
-           }
-       }
-    }
-
   if (funcdef_flag)
     /* Make the init_value nonzero so pushdecl knows this is not
        tentative.  error_mark_node is replaced later with the BLOCK.  */
index 4302ca6194ee2572496cb1f8eb276aae6696a8d7..382a8a3a3ea432510f12ccf0450df6e509b7f49a 100644 (file)
@@ -2880,6 +2880,10 @@ set_decl_namespace (tree decl, tree scope, bool friendp)
        match.  But, we'll check later, when we construct the
        template.  */
     return;
+  /* Instantiations or specializations of templates may be declared as
+     friends in any namespace.  */
+  if (friendp && DECL_USE_TEMPLATE (decl))
+    return;
   if (is_overloaded_fn (old))
     {
       for (; old; old = OVL_NEXT (old))
index 570041ea26fa47c372b3ce4b23bb8ddc5789c721..9ca78fe1036769add553158aaea793433b0df613 100644 (file)
@@ -1,7 +1,15 @@
+<<<<<<< .mine
+2005-11-18  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/8355
+       * g++.dg/template/friend39.C: New test.
+
+=======
 2005-11-18  James E Wilson  <wilson@specifix.com>
 
        * gcc.dg/builtin-strstr.c: New.
 
+>>>>>>> .r107206
 2005-11-18  Richard Henderson  <rth@redhat.com>
 
        * gcc.target/ia64/20010423-1.c, gcc.target/ia64/20020313-1.c,
diff --git a/gcc/testsuite/g++.dg/template/friend39.C b/gcc/testsuite/g++.dg/template/friend39.C
new file mode 100644 (file)
index 0000000..9ebe226
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/8355
+
+namespace Foo { template <typename T> void foo();}
+struct Bar
+{
+  friend void Foo::foo<int>();
+};