* [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
@ 2014-05-05 10:07 Momchil Velikov
2014-05-05 10:13 ` Momchil Velikov
2014-12-27 22:25 ` Momchil Velikov
0 siblings, 2 replies; 10+ messages in thread
From: Momchil Velikov @ 2014-05-05 10:07 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 547 bytes --]
Hello,
A friend function, defined in a class and not declared outside should
be hidden from ordinary name lookup and only found by argument-dependent
lookup, like:
struct S
{
friend void f() {}
friend void g(const S &) {}
};
int
main()
{
f(); // error
g(S()); // correct, found by ADL
}
GCC correctly handles this case, but fails for function templates like:
struct S
{
template<typename T> friend void f(T) {}
};
int
main()
{
f(1); // should be an error, GCC succeeds
f(S()); // correct, found by ADL
}
~chill
[-- Attachment #2: hidden-friend-template.diff --]
[-- Type: text/x-patch, Size: 3258 bytes --]
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 374cd0f..b374181 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2014-05-05 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.
+
2014-05-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58582
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index d900560..8441047 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -924,6 +924,29 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
if (DECL_DECLARES_FUNCTION_P (t))
check_default_args (t);
+ if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+ {
+ if (is_friend)
+ {
+ if (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;
+ }
+ }
+ 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;
+ }
+ }
+
if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
return t;
@@ -983,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.
Install the new declaration and return it. */
if (namespace_bindings_p ())
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3b613d9..dbd63bd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2014-05-05 Momchil Velikov <momchil.velikov@gmail.com>
+
+ PR c++/59366
+ * g++.dg/template/friend56.C: New
+ * g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
+ functions `f` should be found only by ADL.
+
2014-05-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/58582
diff --git a/gcc/testsuite/g++.dg/template/friend56.C b/gcc/testsuite/g++.dg/template/friend56.C
new file mode 100644
index 0000000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend56.C
@@ -0,0 +1,21 @@
+// 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);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
int main()
{
- f(7);
+ f(C());
}
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-05-05 10:07 [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL Momchil Velikov
@ 2014-05-05 10:13 ` Momchil Velikov
2014-12-27 22:25 ` Momchil Velikov
1 sibling, 0 replies; 10+ messages in thread
From: Momchil Velikov @ 2014-05-05 10:13 UTC (permalink / raw)
To: gcc-patches
Bootstrapped/regtested on x86_64-linux-gnu.
One test, gcc/testsuite/g++.old-deja/g++.pt/friend5.C, breaks, as it should,
and was fixed.
~chill
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-05-05 10:07 [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL Momchil Velikov
2014-05-05 10:13 ` Momchil Velikov
@ 2014-12-27 22:25 ` Momchil Velikov
2014-12-27 23:47 ` Jason Merrill
1 sibling, 1 reply; 10+ messages in thread
From: Momchil Velikov @ 2014-12-27 22:25 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 948 bytes --]
Ping
On 5.05.2014 13:06, Momchil Velikov wrote:
> Hello,
>
> A friend function, defined in a class and not declared outside should
> be hidden from ordinary name lookup and only found by argument-dependent
> lookup, like:
>
> struct S
> {
> friend void f() {}
> friend void g(const S &) {}
> };
>
> int
> main()
> {
> f(); // error
> g(S()); // correct, found by ADL
> }
>
> GCC correctly handles this case, but fails for function templates like:
>
> struct S
> {
> template<typename T> friend void f(T) {}
> };
>
> int
> main()
> {
> f(1); // should be an error, GCC succeeds
> f(S()); // correct, found by ADL
> }
>
Bootstrapped and regtested again on top of:
Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-friend-define/configure
--prefix=/home/chill/opt/gcc-friend-define --enable-languages=c,c++
--disable-multilib
Thread model: posix
gcc version 5.0.0 20141227 (experimental) (GCC)
[-- Attachment #2: hidden-friend-template-59366.diff --]
[-- Type: text/x-patch, Size: 2380 bytes --]
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index b982451..5059e14 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -927,6 +927,29 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
if (DECL_DECLARES_FUNCTION_P (t))
check_default_args (t);
+ if (TREE_CODE (x) == FUNCTION_DECL || DECL_FUNCTION_TEMPLATE_P (x))
+ {
+ if (is_friend)
+ {
+ if (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;
+ }
+ }
+ 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;
+ }
+ }
+
if (t != x || DECL_FUNCTION_TEMPLATE_P (t))
return t;
@@ -987,16 +1010,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 ())
diff --git a/gcc/testsuite/g++.dg/template/friend57.C b/gcc/testsuite/g++.dg/template/friend57.C
new file mode 100644
index 0000000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend57.C
@@ -0,0 +1,21 @@
+// 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);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
int main()
{
- f(7);
+ f(C());
}
[-- Attachment #3: hidden-friend-template-59366.ChangeLog --]
[-- Type: text/plain, Size: 425 bytes --]
/cp
2014-12-27 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.
/testsuite
2014-12-27 Momchil Velikov <momchil.velikov@gmail.com>
PR c++/59366
* g++.dg/template/friend57.C: New
* g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
functions `f` should be found only by ADL.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-12-27 22:25 ` Momchil Velikov
@ 2014-12-27 23:47 ` Jason Merrill
2014-12-29 1:42 ` Momchil Velikov
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2014-12-27 23:47 UTC (permalink / raw)
To: Momchil Velikov, gcc-patches
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?
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-12-27 23:47 ` Jason Merrill
@ 2014-12-29 1:42 ` Momchil Velikov
2014-12-30 16:24 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Momchil Velikov @ 2014-12-29 1:42 UTC (permalink / raw)
To: Jason Merrill, gcc-patches
[-- Attachment #1: Type: text/plain, Size: 746 bytes --]
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)
[-- Attachment #2: hidden-friend-wip.diff --]
[-- Type: text/x-patch, Size: 2431 bytes --]
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 ())
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-12-29 1:42 ` Momchil Velikov
@ 2014-12-30 16:24 ` Jason Merrill
2014-12-30 16:25 ` Momchil Velikov
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2014-12-30 16:24 UTC (permalink / raw)
To: Momchil Velikov, gcc-patches
On 12/28/2014 01:45 PM, Momchil Velikov wrote:
> + if (!hidden_friend)
> + {
> + DECL_ANTICIPATED (olddecl) = 0;
> + DECL_HIDDEN_FRIEND_P (olddecl) = 0;
> + }
Why not add this...
> @@ -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);
...here? I don't see a reason why a function template wouldn't hit this
block.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-12-30 16:24 ` Jason Merrill
@ 2014-12-30 16:25 ` Momchil Velikov
2015-01-05 13:57 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Momchil Velikov @ 2014-12-30 16:25 UTC (permalink / raw)
To: Jason Merrill, gcc-patches
On 30.12.2014 17:54, Jason Merrill wrote:
> On 12/28/2014 01:45 PM, Momchil Velikov wrote:
>> + if (!hidden_friend)
>> + {
>> + DECL_ANTICIPATED (olddecl) = 0;
>> + DECL_HIDDEN_FRIEND_P (olddecl) = 0;
>> + }
>
> Why not add this...
>
>> @@ -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);
>
> ...here? I don't see a reason why a function template wouldn't hit this
> block.
A function template enters the body of the if statement at line 1881,
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
and exits the function at line 1951 with
return olddecl;
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2014-12-30 16:25 ` Momchil Velikov
@ 2015-01-05 13:57 ` Jason Merrill
2015-01-05 19:30 ` Momchil Velikov
0 siblings, 1 reply; 10+ messages in thread
From: Jason Merrill @ 2015-01-05 13:57 UTC (permalink / raw)
To: Momchil Velikov, gcc-patches
On 12/30/2014 11:24 AM, Momchil Velikov wrote:
> A function template enters the body of the if statement at line 1881,
>
> if (TREE_CODE (newdecl) == TEMPLATE_DECL)
>
> and exits the function at line 1951 with
>
> return olddecl;
Ah, yes. The patch is OK, then, but still needs ChangeLog and testcase.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2015-01-05 13:57 ` Jason Merrill
@ 2015-01-05 19:30 ` Momchil Velikov
2015-01-15 21:26 ` Jason Merrill
0 siblings, 1 reply; 10+ messages in thread
From: Momchil Velikov @ 2015-01-05 19:30 UTC (permalink / raw)
To: gcc-patches; +Cc: Jason Merrill
[-- Attachment #1: Type: text/plain, Size: 711 bytes --]
On 5.01.2015 15:55, Jason Merrill wrote:
> On 12/30/2014 11:24 AM, Momchil Velikov wrote:
>> A function template enters the body of the if statement at line 1881,
>>
>> if (TREE_CODE (newdecl) == TEMPLATE_DECL)
>>
>> and exits the function at line 1951 with
>>
>> return olddecl;
>
> Ah, yes. The patch is OK, then, but still needs ChangeLog and testcase.
>
> Jason
>
Bootstrapped/tested again with:
Target: x86_64-unknown-linux-gnu
Configured with: /home/chill/src/gcc-master/configure
--prefix=/home/chill/opt/gcc-master --enable-languages=c,c++
Thread model: posix
gcc version 5.0.0 20150105 (experimental) [master revision
113a5d9:4b40b3c:c1fd77316d75af1122efb4b8b2988a86599558dc] (GCC)
[-- Attachment #2: gcc-friend-59366.diff --]
[-- Type: text/x-patch, Size: 3321 bytes --]
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2fea106..82401ab 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 2dfb00d..d92a2cd 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 ())
diff --git a/gcc/testsuite/g++.dg/template/friend57.C b/gcc/testsuite/g++.dg/template/friend57.C
new file mode 100644
index 0000000..7077d5e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend57.C
@@ -0,0 +1,21 @@
+// 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);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
index 3feeb68..edb9d62 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/friend5.C
@@ -14,5 +14,5 @@ class C
int main()
{
- f(7);
+ f(C());
}
[-- Attachment #3: gcc-friend-59366.ChangeLog --]
[-- Type: text/plain, Size: 549 bytes --]
/cp
2015-01-05 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.
/testsuite
2015-01-05 Momchil Velikov <momchil.velikov@gmail.com>
PR c++/59366
* g++.dg/template/friend57.C: New
* g++.old-deja/g++.pt/friend5.C (main): Fix testcase. The friend
function `f` should be found only by ADL.
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL
2015-01-05 19:30 ` Momchil Velikov
@ 2015-01-15 21:26 ` Jason Merrill
0 siblings, 0 replies; 10+ messages in thread
From: Jason Merrill @ 2015-01-15 21:26 UTC (permalink / raw)
To: Momchil Velikov, gcc-patches
Applied, thanks.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2015-01-15 21:02 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-05-05 10:07 [PATCH] Fix PR c++/59366 A friend function template defined in a class is found without ADL Momchil Velikov
2014-05-05 10:13 ` Momchil Velikov
2014-12-27 22:25 ` Momchil Velikov
2014-12-27 23:47 ` Jason Merrill
2014-12-29 1:42 ` Momchil Velikov
2014-12-30 16:24 ` Jason Merrill
2014-12-30 16:25 ` Momchil Velikov
2015-01-05 13:57 ` Jason Merrill
2015-01-05 19:30 ` Momchil Velikov
2015-01-15 21:26 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).