c++: Function found via ADL when it should not [PR95074]
authorMarek Polacek <polacek@redhat.com>
Tue, 12 May 2020 18:56:13 +0000 (14:56 -0400)
committerMarek Polacek <polacek@redhat.com>
Tue, 12 May 2020 20:25:51 +0000 (16:25 -0400)
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) <case CPP_OPEN_PAREN>: 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
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/koenig15.C [new file with mode: 0644]

index db80907ef4d26525f28d08a53fc070c9c5029564..7515827d7aea15bdbe89f429d542d18730f3a04f 100644 (file)
@@ -1,3 +1,10 @@
+2020-05-12  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/95074
+       * parser.c (cp_parser_postfix_expression) <case CPP_OPEN_PAREN>: 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  <jakub@redhat.com>
 
        PR c++/95063
index 10627cb1c92dcc186ed2a86beff7ee474ef82f1b..f1ddef220fec8dc9de60a841a0b69eeeddec7d08 100644 (file)
@@ -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))
index 34f48e7f2a4fee9dfb01d5afedce3bf59746a2a6..24a42765cc225a573c2719a37a0f7753b85f8a97 100644 (file)
@@ -1,3 +1,8 @@
+2020-05-12  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/95074
+       * g++.dg/lookup/koenig15.C: New test.
+
 2020-05-12  Jakub Jelinek  <jakub@redhat.com>
 
        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 (file)
index 0000000..f317c01
--- /dev/null
@@ -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" }
+}