From 199b7a3586061f951fa737656217206164456910 Mon Sep 17 00:00:00 2001 From: Momchil Velikov Date: Thu, 15 Jan 2015 21:02:15 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 8 +++++++ gcc/cp/decl.c | 17 +++++++++++---- gcc/cp/name-lookup.c | 23 +++++++++++---------- gcc/testsuite/g++.dg/template/friend57.C | 21 +++++++++++++++++++ gcc/testsuite/g++.old-deja/g++.pt/friend5.C | 2 +- 5 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/friend57.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2e74c0a4068..9120e07eaf9 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2015-01-15 Momchil Velikov + + 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 PR c++/64356 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 9d9a04eeee6..35f483363d8 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -1871,6 +1871,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; @@ -2153,10 +2166,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 cf612407e9e..ba16befa74d 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -933,7 +933,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; @@ -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. 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 00000000000..7077d5e53cb --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend57.C @@ -0,0 +1,21 @@ +// PR c++/59366 +// { dg-do compile } +template void f(T); + +struct S +{ + template friend void f(T) {} + template friend void g(T) {} + template friend void h(T) {} +}; + +template 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 3feeb684e36..edb9d623359 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()); } -- 2.30.2