From 431be04b8b6e31d950ddab340ed866d197d23d4d Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Fri, 4 Nov 2022 15:22:45 -0400 Subject: c++: implement P2468R2, the equality operator you are looking for This paper is resolving the problem of well-formed C++17 code becoming ambiguous in C++20 due to asymmetrical operator== being compared with itself in reverse. I had previously implemented a tiebreaker such that if the two candidates were functions with the same parameter types, we would prefer the non-reversed candidate. But the committee went with a different approach: if there's an operator!= with the same parameter types as the operator==, don't consider the reversed form of the ==. So this patch implements that, and changes my old tiebreaker to give a pedwarn if it is used. I also noticed that we were giving duplicate errors for some testcases, and fixed the tourney logic to avoid that. As a result, a lot of tests of the form struct A { bool operator==(const A&); }; need to be fixed to add a const function-cv-qualifier, e.g. struct A { bool operator==(const A&) const; }; The committee thought such code ought to be fixed, so breaking it was fine. 18_support/comparisons/algorithms/fallback.cc also breaks with this patch, because of the similarly asymmetrical bool operator==(const S&, S&) { return true; } As a result, some of the asserts need to be reversed. The H test in spaceship-eq15.C is specified in the standard to be well-formed because the op!= in the inline namespace is not found by the search, but that seems wrong to me. I've implemented that behavior, but disabled it for now; if we decide that is the way we want to go, we can just remove the "0 &&" in add_candidates to enable it. Co-authored-by: Jakub Jelinek gcc/cp/ChangeLog: * cp-tree.h (fns_correspond): Declare. * decl.cc (fns_correspond): New. * call.cc (add_candidates): Look for op!= matching op==. (joust): Complain about non-standard reversed tiebreaker. (tourney): Fix champ_compared_to_predecessor logic. (build_new_op): Don't complain about error_mark_node not having 'bool' type. * pt.cc (tsubst_copy_and_build): Don't try to be permissive when seen_error(). gcc/testsuite/ChangeLog: * g++.dg/cpp2a/spaceship-eq15.C: New test. * g++.dg/cpp0x/defaulted3.C: Add const. * g++.dg/cpp2a/bit-cast7.C: Add const. * g++.dg/cpp2a/spaceship-rewrite1.C: Expect error. * g++.dg/cpp2a/spaceship-rewrite5.C: Expect error. * g++.old-deja/g++.jason/byval2.C: Expect error. * g++.old-deja/g++.other/overload13.C: Add const. libstdc++-v3/ChangeLog: * testsuite/18_support/comparisons/algorithms/fallback.cc: Adjust asserts. --- gcc/cp/cp-tree.h | 1 + 1 file changed, 1 insertion(+) (limited to 'gcc/cp/cp-tree.h') diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index d13bb3d4c0e..bbc8be21900 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6820,6 +6820,7 @@ extern void note_break_stmt (void); extern bool note_iteration_stmt_body_start (void); extern void note_iteration_stmt_body_end (bool); extern void determine_local_discriminator (tree); +extern bool fns_correspond (tree, tree); extern int decls_match (tree, tree, bool = true); extern bool maybe_version_functions (tree, tree, bool); extern bool merge_default_template_args (tree, tree, bool); -- cgit v1.2.1