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
This commit is contained in:
Mark Mitchell 2005-11-19 02:25:55 +00:00
parent 817f9ef2e5
commit abc088aad7
5 changed files with 87 additions and 68 deletions

View 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.

View 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. */

View 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))

View 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,

View File

@ -0,0 +1,7 @@
// PR c++/8355
namespace Foo { template <typename T> void foo();}
struct Bar
{
friend void Foo::foo<int>();
};