This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
- From: Momchil Velikov <momchil dot velikov at gmail dot com>
- To: Jason Merrill <jason at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Sun, 28 Dec 2014 20:45:30 +0200
- Subject: Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
- Authentication-results: sourceware.org; auth=none
- References: <536762C0 dot 5040504 at gmail dot com> <549F26E0 dot 3000606 at gmail dot com> <549F4270 dot 3040808 at redhat dot com>
On 28.12.2014 01:36, Jason Merrill wrote:
On 12/27/2014 04:38 PM, Momchil Velikov wrote:
+ else if (t != x && t != error_mark_node)
+ {
+ /* This is a non-friend re-declaration of a possibly
+ hidden function or a function template, so don't hide
+ it. */
+ DECL_ANTICIPATED (t) = 0;
+ DECL_HIDDEN_FRIEND_P (t) = 0;
+ }
Doesn't duplicate_decls handle clearing these?
It does, but only for functions (in somewhat obscure way, by not
setting the flags in DECL_LANG_SPECIFIC(newdecl)).
It does not for function templates. Indeed, it makes sense to do this
in duplicate_decls(). How about like in the attached patch?
(bootstrap and testing in progress)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index bbaf3d6..efd472a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1865,6 +1865,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_ATTRIBUTES (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)
{
tree old_result;
@@ -2147,10 +2160,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (DECL_DECLARES_FUNCTION_P (newdecl))
{
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)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b982451..69a0da6 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -925,7 +925,18 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
}
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))
return t;
@@ -987,16 +998,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.
Install the new declaration and return it. */
if (namespace_bindings_p ())