Commit 199b7a35 by Momchil Velikov Committed by Jason Merrill

re PR c++/59366 (A friend function template defined in a class is found without ADL)

	PR c++/59366
	* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
	and function templates, declared only in the class.
	* decl.c (duplicate_decls): Reveal hidden friend functions or
	function templates, if they are redeclared outside the class.

From-SVN: r219689
parent 58b59d5e
2015-01-15 Momchil Velikov <momchil.velikov@gmail.com>
PR c++/59366
* name-lookup.c (pushdecl_maybe_friend_1): Hide friend functions
and function templates, declared only in the class.
* decl.c (duplicate_decls): Reveal hidden friend functions or
function templates, if they are redeclared outside the class.
2015-01-15 Jason Merrill <jason@redhat.com> 2015-01-15 Jason Merrill <jason@redhat.com>
PR c++/64356 PR c++/64356
......
...@@ -1871,6 +1871,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -1871,6 +1871,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_ATTRIBUTES (newdecl) DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl); = (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (DECL_DECLARES_FUNCTION_P (olddecl) && DECL_DECLARES_FUNCTION_P (newdecl))
{
olddecl_friend = DECL_FRIEND_P (olddecl);
hidden_friend = (DECL_ANTICIPATED (olddecl)
&& DECL_HIDDEN_FRIEND_P (olddecl)
&& newdecl_is_friend);
if (!hidden_friend)
{
DECL_ANTICIPATED (olddecl) = 0;
DECL_HIDDEN_FRIEND_P (olddecl) = 0;
}
}
if (TREE_CODE (newdecl) == TEMPLATE_DECL) if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{ {
tree old_result; tree old_result;
...@@ -2153,10 +2166,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) ...@@ -2153,10 +2166,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (DECL_DECLARES_FUNCTION_P (newdecl)) if (DECL_DECLARES_FUNCTION_P (newdecl))
{ {
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl); DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
hidden_friend = (DECL_ANTICIPATED (olddecl)
&& DECL_HIDDEN_FRIEND_P (olddecl)
&& newdecl_is_friend);
DECL_BEFRIENDING_CLASSES (newdecl) DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl), = chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl)); DECL_BEFRIENDING_CLASSES (olddecl));
......
...@@ -933,7 +933,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) ...@@ -933,7 +933,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
} }
if (DECL_DECLARES_FUNCTION_P (t)) if (DECL_DECLARES_FUNCTION_P (t))
check_default_args (t); {
check_default_args (t);
if (is_friend && t == x && !flag_friend_injection)
{
/* This is a new friend declaration of a function or a
function template, so hide it from ordinary function
lookup. */
DECL_ANTICIPATED (t) = 1;
DECL_HIDDEN_FRIEND_P (t) = 1;
}
}
if (t != x || DECL_FUNCTION_TEMPLATE_P (t)) if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
return t; return t;
...@@ -995,16 +1006,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend) ...@@ -995,16 +1006,6 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
} }
} }
if (TREE_CODE (x) == FUNCTION_DECL
&& is_friend
&& !flag_friend_injection)
{
/* This is a new declaration of a friend function, so hide
it from ordinary function lookup. */
DECL_ANTICIPATED (x) = 1;
DECL_HIDDEN_FRIEND_P (x) = 1;
}
/* This name is new in its binding level. /* This name is new in its binding level.
Install the new declaration and return it. */ Install the new declaration and return it. */
if (namespace_bindings_p ()) if (namespace_bindings_p ())
......
// PR c++/59366
// { dg-do compile }
template<typename T> void f(T);
struct S
{
template<typename T> friend void f(T) {}
template<typename T> friend void g(T) {}
template<typename T> friend void h(T) {}
};
template<typename T> void h(T);
int
main ()
{
f(1);
g(1); // { dg-error "'g' was not declared in this scope" }
g(S());
h(1);
}
...@@ -14,5 +14,5 @@ class C ...@@ -14,5 +14,5 @@ class C
int main() int main()
{ {
f(7); f(C());
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment