From abc088aad79d47b40da8a26e87815db09ab2d6eb Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Sat, 19 Nov 2005 02:25:55 +0000 Subject: [PATCH] re PR c++/8355 (befriending a template specialization in another namespace) 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 | 7 ++ gcc/cp/decl.c | 129 +++++++++++++++---------------- gcc/cp/name-lookup.c | 4 + gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/g++.dg/template/friend39.C | 7 ++ 5 files changed, 87 insertions(+), 68 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/friend39.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 42e44da..bd711f3 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2005-11-18 Mark Mitchell + + 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 * cp-objcp-common.h (LANG_HOOKS_LOOKUP_NAME): Add. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 30d81a7..55e26b9 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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 friend void f()'. */ + 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 ("% 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 friend void f()'. */ - 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 ("% 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. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index 4302ca6..382a8a3a 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 570041e..9ca78fe 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,7 +1,15 @@ +<<<<<<< .mine +2005-11-18 Mark Mitchell + + PR c++/8355 + * g++.dg/template/friend39.C: New test. + +======= 2005-11-18 James E Wilson * gcc.dg/builtin-strstr.c: New. +>>>>>>> .r107206 2005-11-18 Richard Henderson * 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 index 0000000..9ebe226 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend39.C @@ -0,0 +1,7 @@ +// PR c++/8355 + +namespace Foo { template void foo();} +struct Bar +{ + friend void Foo::foo(); +}; -- 2.7.4