From e04c614e09867345ee8ac03390cc75c5f2f1de1e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Tue, 7 Apr 2009 23:44:48 -0400 Subject: [PATCH] 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: r145709 --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/call.c | 48 ++++++++++++++++++++-- gcc/cp/class.c | 34 +++++++++------ gcc/cp/name-lookup.c | 7 ++-- gcc/cp/pt.c | 21 +++++++--- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/overload/extern-C-1.C | 17 ++++++++ 7 files changed, 117 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/extern-C-1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 08daf462594..264fea46725 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2009-04-07 Jason Merrill + + 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 PR c++/25185 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 745c31facc2..c942712cbec 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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: diff --git a/gcc/cp/class.c b/gcc/cp/class.c index c1885be2e77..1a96384bf40 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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. */ diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index f02605f5ae0..2eebb79f278 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -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; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 92815c08267..8dd35795a12 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 85a616da84f..a0fee86c2fa 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2009-04-07 Jason Merrill + + PR c++/34691 + * g++.dg/overload/extern-C-1.C: New. + 2009-04-07 Dominique d'Humieres 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 index 00000000000..839a0b49ae2 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/extern-C-1.C @@ -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" } +} + -- 2.30.2