re PR c++/34691 (Default argument checking not performed after overload resolution...
authorJason Merrill <jason@redhat.com>
Wed, 8 Apr 2009 03:44:48 +0000 (23:44 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 8 Apr 2009 03:44:48 +0000 (23:44 -0400)
PR c++/34691
* name-lookup.c (merge_functions): Keep multiple extern "C" functions.
* call.c (joust): Complain about mismatched default arguments
in extern "C" functions.
* class.c (resolve_address_of_overloaded_function): Handle multiple
extern "C" functions.
* pt.c (resolve_overloaded_unification): Likewise.

From-SVN: r145709

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/overload/extern-C-1.C [new file with mode: 0644]

index 08daf462594ac6112331bb5808e88efe63e484fb..264fea46725656d8ac1828d08098daefa7281b5c 100644 (file)
@@ -1,3 +1,13 @@
+2009-04-07  Jason Merrill  <jason@redhat.com>
+
+       PR c++/34691
+       * name-lookup.c (merge_functions): Keep multiple extern "C" functions.
+       * call.c (joust): Complain about mismatched default arguments
+       in extern "C" functions.
+       * class.c (resolve_address_of_overloaded_function): Handle multiple
+       extern "C" functions.
+       * pt.c (resolve_overloaded_unification): Likewise.
+
 2009-04-07  Jason Merrill  <jason@redhat.com>
 
        PR c++/25185
index 745c31facc20bf5f77bb347180b3f448b5c6df81..c942712cbec7db8d46d6b3c2611d4cb3953dbf3a 100644 (file)
@@ -6787,11 +6787,53 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn)
        }
     }
 
-  /* If the two functions are the same (this can happen with declarations
-     in multiple scopes and arg-dependent lookup), arbitrarily choose one.  */
+  /* If the two function declarations represent the same function (this can
+     happen with declarations in multiple scopes and arg-dependent lookup),
+     arbitrarily choose one.  But first make sure the default args we're
+     using match.  */
   if (DECL_P (cand1->fn) && DECL_P (cand2->fn)
       && equal_functions (cand1->fn, cand2->fn))
-    return 1;
+    {
+      tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (cand1->fn));
+      tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (cand2->fn));
+
+      gcc_assert (!DECL_CONSTRUCTOR_P (cand1->fn));
+
+      for (i = 0; i < len; ++i)
+       {
+         parms1 = TREE_CHAIN (parms1);
+         parms2 = TREE_CHAIN (parms2);
+       }
+
+      if (off1)
+       parms1 = TREE_CHAIN (parms1);
+      else if (off2)
+       parms2 = TREE_CHAIN (parms2);
+
+      for (; parms1; ++i)
+       {
+         if (!cp_tree_equal (TREE_PURPOSE (parms1),
+                             TREE_PURPOSE (parms2)))
+           {
+             if (warn)
+               {
+                 permerror (input_location, "default argument mismatch in "
+                            "overload resolution");
+                 inform (input_location,
+                         " candidate 1: %q+#F", cand1->fn);
+                 inform (input_location,
+                         " candidate 2: %q+#F", cand2->fn);
+               }
+             else
+               add_warning (cand1, cand2);
+             break;
+           }
+         parms1 = TREE_CHAIN (parms1);
+         parms2 = TREE_CHAIN (parms2);
+       }
+
+      return 1;
+    }
 
 tweak:
 
index c1885be2e7792c1648ddb9a9bd8bb14341d0b36d..1a96384bf409cf5b323c740229af467e2459997f 100644 (file)
@@ -6164,25 +6164,33 @@ resolve_address_of_overloaded_function (tree target_type,
     }
   else if (TREE_CHAIN (matches))
     {
-      /* There were too many matches.  */
+      /* There were too many matches.  First check if they're all
+        the same function.  */
+      tree match;
 
-      if (flags & tf_error)
+      fn = TREE_PURPOSE (matches);
+      for (match = TREE_CHAIN (matches); match; match = TREE_CHAIN (match))
+       if (!decls_match (fn, TREE_PURPOSE (matches)))
+         break;
+
+      if (match)
        {
-         tree match;
+         if (flags & tf_error)
+           {
+             error ("converting overloaded function %qD to type %q#T is ambiguous",
+                    DECL_NAME (OVL_FUNCTION (overload)),
+                    target_type);
 
-         error ("converting overloaded function %qD to type %q#T is ambiguous",
-                   DECL_NAME (OVL_FUNCTION (overload)),
-                   target_type);
+             /* Since print_candidates expects the functions in the
+                TREE_VALUE slot, we flip them here.  */
+             for (match = matches; match; match = TREE_CHAIN (match))
+               TREE_VALUE (match) = TREE_PURPOSE (match);
 
-         /* Since print_candidates expects the functions in the
-            TREE_VALUE slot, we flip them here.  */
-         for (match = matches; match; match = TREE_CHAIN (match))
-           TREE_VALUE (match) = TREE_PURPOSE (match);
+             print_candidates (matches);
+           }
 
-         print_candidates (matches);
+         return error_mark_node;
        }
-
-      return error_mark_node;
     }
 
   /* Good, exactly one match.  Now, convert it to the correct type.  */
index f02605f5ae0d5a62b1c43ea4cdec9f7b33e4b09c..2eebb79f278ee841106ee0ae9b509fcee306b5b6 100644 (file)
@@ -3607,10 +3607,9 @@ merge_functions (tree s1, tree s2)
          /* If the function from S2 is already in S1, there is no
             need to add it again.  For `extern "C"' functions, we
             might have two FUNCTION_DECLs for the same function, in
-            different namespaces; again, we only need one of them.  */
-         if (fn1 == fn2
-             || (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
-                 && DECL_NAME (fn1) == DECL_NAME (fn2)))
+            different namespaces, but let's leave them in in case
+            they have different default arguments.  */
+         if (fn1 == fn2)
            break;
        }
 
index 92815c08267b67b16cae06d9f5b76c7c18829461..8dd35795a125f28cf19290a7cacce028effde097 100644 (file)
@@ -12679,6 +12679,7 @@ resolve_overloaded_unification (tree tparms,
 {
   tree tempargs = copy_node (targs);
   int good = 0;
+  tree goodfn = NULL_TREE;
   bool addr_p;
 
   if (TREE_CODE (arg) == ADDR_EXPR)
@@ -12724,8 +12725,13 @@ resolve_overloaded_unification (tree tparms,
          if (subargs)
            {
              elem = tsubst (TREE_TYPE (fn), subargs, tf_none, NULL_TREE);
-             good += try_one_overload (tparms, targs, tempargs, parm,
-                                       elem, strict, sub_strict, addr_p);
+             if (try_one_overload (tparms, targs, tempargs, parm,
+                                   elem, strict, sub_strict, addr_p)
+                 && (!goodfn || !decls_match (goodfn, elem)))
+               {
+                 goodfn = elem;
+                 ++good;
+               }
            }
          --processing_template_decl;
        }
@@ -12738,9 +12744,14 @@ resolve_overloaded_unification (tree tparms,
     return false;
   else
     for (; arg; arg = OVL_NEXT (arg))
-      good += try_one_overload (tparms, targs, tempargs, parm,
-                               TREE_TYPE (OVL_CURRENT (arg)),
-                               strict, sub_strict, addr_p);
+      if (try_one_overload (tparms, targs, tempargs, parm,
+                           TREE_TYPE (OVL_CURRENT (arg)),
+                           strict, sub_strict, addr_p)
+         && (!goodfn || !decls_match (goodfn, OVL_CURRENT (arg))))
+       {
+         goodfn = OVL_CURRENT (arg);
+         ++good;
+       }
 
   /* [temp.deduct.type] A template-argument can be deduced from a pointer
      to function or pointer to member function argument if the set of
index 85a616da84f13e350295f73bfeda0c361c8c3f9f..a0fee86c2fa898828c73ce894ad2cf6a0d0c6bda 100644 (file)
@@ -1,3 +1,8 @@
+2009-04-07  Jason Merrill  <jason@redhat.com>
+
+       PR c++/34691
+       * g++.dg/overload/extern-C-1.C: New.
+
 2009-04-07  Dominique d'Humieres  <dominiq@lps.ens.fr>
 
        PR testsuite/39325
diff --git a/gcc/testsuite/g++.dg/overload/extern-C-1.C b/gcc/testsuite/g++.dg/overload/extern-C-1.C
new file mode 100644 (file)
index 0000000..839a0b4
--- /dev/null
@@ -0,0 +1,17 @@
+// PR c++/34691
+
+namespace A {
+  extern "C" void f(int = 5);  // { dg-message "= 5" }
+}
+namespace B {
+  extern "C" void f(int = 4);  // { dg-message "= 4" }
+}
+
+using A::f;
+using B::f;
+int main() {
+  void (*fp)(int) = f;         // OK
+  f(3);                                // OK
+  f();                         // { dg-error "default argument mismatch" }
+}
+