diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/call.c | 48 | ||||
-rw-r--r-- | gcc/cp/class.c | 34 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 7 | ||||
-rw-r--r-- | gcc/cp/pt.c | 21 |
5 files changed, 95 insertions, 25 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 08daf46..264fea4 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 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 * error.c (dump_function_decl): Don't pretty-print templates if -fno-pretty-templates. diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 745c31f..c942712 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 c1885be..1a96384 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 f02605f..2eebb79 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 92815c0..8dd3579 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 |