From 90b160f8ec515f54ddc36519a6aaa60abdabdec1 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Tue, 12 May 2020 14:56:13 -0400 Subject: [PATCH] c++: Function found via ADL when it should not [PR95074] I noticed that we don't implement [basic.lookup.argdep]/3: quite correctly; it says "If X (the lookup set produced by unqualified lookup) contains -- a block-scope function declaration that is not a using-declaration [...] then Y (the lookup set produced by ADL) is empty." but we were still performing ADL in fn1 in the attached test. The problem was that we were only looking at the first function in the overload set which in this case happened to be a using-declaration, and those don't suppress ADL. We have to look through the whole set to find out if unqualified lookup found a block-scope function declaration, or a member function declaration. PR c++/95074 * parser.c (cp_parser_postfix_expression) : When looking for a block-scope function declaration, look through the whole set, not just the first function in the overload set. * g++.dg/lookup/koenig15.C: New test. --- gcc/cp/ChangeLog | 7 ++++ gcc/cp/parser.c | 26 +++++++++------ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/lookup/koenig15.C | 45 ++++++++++++++++++++++++++ 4 files changed, 73 insertions(+), 10 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/koenig15.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index db80907ef4d..7515827d7ae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2020-05-12 Marek Polacek + + PR c++/95074 + * parser.c (cp_parser_postfix_expression) : When + looking for a block-scope function declaration, look through the whole + set, not just the first function in the overload set. + 2020-05-12 Jakub Jelinek PR c++/95063 diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 10627cb1c92..f1ddef220fe 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7385,19 +7385,25 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p, else if (!args->is_empty () && is_overloaded_fn (postfix_expression)) { - /* We only need to look at the first function, - because all the fns share the attribute we're - concerned with (all member fns or all local - fns). */ - tree fn = get_first_fn (postfix_expression); - fn = STRIP_TEMPLATE (fn); - /* Do not do argument dependent lookup if regular lookup finds a member function or a block-scope function declaration. [basic.lookup.argdep]/3 */ - if (!((TREE_CODE (fn) == USING_DECL && DECL_DEPENDENT_P (fn)) - || DECL_FUNCTION_MEMBER_P (fn) - || DECL_LOCAL_FUNCTION_P (fn))) + bool do_adl_p = true; + tree fns = get_fns (postfix_expression); + for (lkp_iterator iter (fns); iter; ++iter) + { + tree fn = STRIP_TEMPLATE (*iter); + if ((TREE_CODE (fn) == USING_DECL + && DECL_DEPENDENT_P (fn)) + || DECL_FUNCTION_MEMBER_P (fn) + || DECL_LOCAL_FUNCTION_P (fn)) + { + do_adl_p = false; + break; + } + } + + if (do_adl_p) { koenig_p = true; if (!any_type_dependent_arguments_p (args)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 34f48e7f2a4..24a42765cc2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-05-12 Marek Polacek + + PR c++/95074 + * g++.dg/lookup/koenig15.C: New test. + 2020-05-12 Jakub Jelinek PR sanitizer/95051 diff --git a/gcc/testsuite/g++.dg/lookup/koenig15.C b/gcc/testsuite/g++.dg/lookup/koenig15.C new file mode 100644 index 00000000000..f317c010dde --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/koenig15.C @@ -0,0 +1,45 @@ +// PR c++/95074 - Function found via ADL when it should not. +// { dg-do compile } + +namespace N { + struct S { }; + void f(S); +} + +namespace M { + void f(int); +} + +void +fn0 () +{ + N::S s; + using M::f; + f (s); +} + +void +fn1 () +{ + N::S s; + extern void f(char); + using M::f; + f (s); // { dg-error "no matching function" } +} + +void +fn2 () +{ + N::S s; + using M::f; + extern void f(char); + f (s); // { dg-error "no matching function" } +} + +void +fn3 () +{ + N::S s; + extern void (*f)(char); + f (s); // { dg-error "cannot convert" } +} -- 2.30.2