diff options
author | Jason Merrill <jason@redhat.com> | 2019-11-19 20:22:12 +0000 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2019-11-19 20:22:12 +0000 |
commit | 1b7cb07c68d5bc35c7b42a65bf79b76e441da7f1 (patch) | |
tree | 97700c240dbdfff23fb6a4a626ad00d32e60b04a /gcc/cp | |
parent | 8c16f377faeb1f15550653b634b25234e4fe1ba6 (diff) |
Consider parm types equivalence for operator rewrite tiebreaker.
The C++ committee continues to discuss how best to avoid breaking existing
code with the new rules for reversed operators. A recent suggestion was to
base the tie-breaker on the parameter types of the candidates, which made a
lot of sense to me, so this patch implements that.
This patch also mentions that a candidate was reversed or rewritten when
printing the list of candidates, and warns about a comparison that becomes
recursive under the new rules. There is no flag for this warning; people
can silence it by swapping the operands.
* call.c (same_fn_or_template): Change to cand_parms_match.
(joust): Adjust.
(print_z_candidate): Mark rewritten/reversed candidates.
(build_new_op_1): Warn about recursive call with reversed arguments.
git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@278465 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/cp/call.c | 63 |
2 files changed, 46 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cc7a58ec5fd..2313a824b48 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-11-12 Jason Merrill <jason@redhat.com> + + * call.c (same_fn_or_template): Change to cand_parms_match. + (joust): Adjust. + (print_z_candidate): Mark rewritten/reversed candidates. + (build_new_op_1): Warn about recursive call with reversed arguments. + 2019-11-15 Andrew Sutton <asutton@lock3software.com> PR c++/89913 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 13639a1c901..f4dfa7b3f56 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -3694,6 +3694,10 @@ print_z_candidate (location_t loc, const char *msgstr, inform (cloc, "%s%#qD (near match)", msg, fn); else if (DECL_DELETED_FN (fn)) inform (cloc, "%s%#qD (deleted)", msg, fn); + else if (candidate->reversed ()) + inform (cloc, "%s%#qD (reversed)", msg, fn); + else if (candidate->rewritten ()) + inform (cloc, "%s%#qD (rewritten)", msg, fn); else inform (cloc, "%s%#qD", msg, fn); if (fn != candidate->fn) @@ -6219,8 +6223,14 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags, else { if (cand->reversed ()) - /* We swapped these in add_candidate, swap them back now. */ - std::swap (cand->convs[0], cand->convs[1]); + { + /* We swapped these in add_candidate, swap them back now. */ + std::swap (cand->convs[0], cand->convs[1]); + if (cand->fn == current_function_decl) + warning_at (loc, 0, "in C++20 this comparison calls the " + "current function recursively with reversed " + "arguments"); + } result = build_over_call (cand, LOOKUP_NORMAL, complain); } @@ -10995,18 +11005,32 @@ joust_maybe_elide_copy (z_candidate *&cand) return false; } -/* True if cand1 and cand2 represent the same function or function - template. */ +/* True if the defining declarations of the two candidates have equivalent + parameters. */ -static bool -same_fn_or_template (z_candidate *cand1, z_candidate *cand2) +bool +cand_parms_match (z_candidate *c1, z_candidate *c2) { - if (cand1->fn == cand2->fn) + tree fn1 = c1->template_decl; + tree fn2 = c2->template_decl; + if (fn1 && fn2) + { + fn1 = most_general_template (TI_TEMPLATE (fn1)); + fn1 = DECL_TEMPLATE_RESULT (fn1); + fn2 = most_general_template (TI_TEMPLATE (fn2)); + fn2 = DECL_TEMPLATE_RESULT (fn2); + } + else + { + fn1 = c1->fn; + fn2 = c2->fn; + } + if (fn1 == fn2) return true; - if (!cand1->template_decl || !cand2->template_decl) + if (identifier_p (fn1) || identifier_p (fn2)) return false; - return (most_general_template (TI_TEMPLATE (cand1->template_decl)) - == most_general_template (TI_TEMPLATE (cand2->template_decl))); + return compparms (TYPE_ARG_TYPES (TREE_TYPE (fn1)), + TYPE_ARG_TYPES (TREE_TYPE (fn2))); } /* Compare two candidates for overloading as described in @@ -11155,20 +11179,11 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn, if (winner && comp != winner) { - if (same_fn_or_template (cand1, cand2)) - { - /* Ambiguity between normal and reversed versions of the - same comparison operator; prefer the normal one. - https://lists.isocpp.org/core/2019/10/7438.php */ - if (cand1->reversed ()) - winner = -1; - else - { - gcc_checking_assert (cand2->reversed ()); - winner = 1; - } - break; - } + /* Ambiguity between normal and reversed comparison operators + with the same parameter types; prefer the normal one. */ + if ((cand1->reversed () != cand2->reversed ()) + && cand_parms_match (cand1, cand2)) + return cand1->reversed () ? -1 : 1; winner = 0; goto tweak; |