re PR c++/34691 (Default argument checking not performed after overload resolution with C linkage)

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: r145710
This commit is contained in:
Jason Merrill 2009-04-07 23:55:00 -04:00 committed by Jason Merrill
parent 5f17649815
commit a4385e634e
7 changed files with 115 additions and 25 deletions

View File

@ -1,5 +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.
* decl.c (grokdeclarator): Reject pointer to qualified function
type.

View 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:

View File

@ -6152,25 +6152,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. */

View File

@ -3601,10 +3601,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;
}

View File

@ -12635,6 +12635,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)
@ -12680,8 +12681,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;
}
@ -12694,9 +12700,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

View 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

View File

@ -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" }
}