This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 8355
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Fri, 18 Nov 2005 18:37:43 -0800
- Subject: C++ PATCH: PR 8355
- Reply-to: mark at codesourcery dot com
This patch fixes PR 8355, a long-standing problem with friend
declarations. We were complaining about declarations of template
instantiations from other namespaces as friends. So,
set_decl_namespace needed to be told that was OK. But, because
grokfndecl did not set up DECL_TEMPLATE_INFO until after calling
set_decl_namespace, there was no way for set_decl_namespace to know,
so grokfndecl needed a little reordering as well.
Tested on x86_64-unknown-linux-gnu, applied on the mainline. (This is
not a regression, so will not be applied to 4.0 branch.)
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
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 Mark Mitchell <mark@codesourcery.com>
PR c++/8355
* g++.dg/template/friend39.C: New test.
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c (revision 107031)
+++ gcc/cp/decl.c (working copy)
@@ -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: gcc/cp/name-lookup.c
===================================================================
--- gcc/cp/name-lookup.c (revision 107031)
+++ gcc/cp/name-lookup.c (working copy)
@@ -2880,6 +2880,10 @@ set_decl_namespace (tree decl, tree scop
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: gcc/testsuite/g++.dg/template/friend39.C
===================================================================
--- gcc/testsuite/g++.dg/template/friend39.C (revision 0)
+++ gcc/testsuite/g++.dg/template/friend39.C (revision 0)
@@ -0,0 +1,7 @@
+// PR c++/8355
+
+namespace Foo { template <typename T> void foo();}
+struct Bar
+{
+ friend void Foo::foo<int>();
+};