This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
Other format: | [Raw text] |
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-gnuConfigured 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)
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:
hidden-friend-template-59366.ChangeLog
Description: Text document
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |