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:
parent
5f17649815
commit
a4385e634e
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
21
gcc/cp/pt.c
21
gcc/cp/pt.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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" }
|
||||
}
|
||||
|
Loading…
Reference in New Issue