c++: implement P2468R2, the equality operator you are looking for
authorJason Merrill <jason@redhat.com>
Fri, 4 Nov 2022 19:22:45 +0000 (15:22 -0400)
committerJason Merrill <jason@redhat.com>
Tue, 8 Nov 2022 00:54:04 +0000 (14:54 -1000)
commit431be04b8b6e31d950ddab340ed866d197d23d4d
treee0d29df251d9de1334b46cd96cd350e8534510e4
parentc838119946c9f75f1e42f4320275355822cc86fc
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 <jakub@redhat.com>
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.
12 files changed:
gcc/cp/call.cc
gcc/cp/cp-tree.h
gcc/cp/decl.cc
gcc/cp/pt.cc
gcc/testsuite/g++.dg/cpp0x/defaulted3.C
gcc/testsuite/g++.dg/cpp2a/bit-cast7.C
gcc/testsuite/g++.dg/cpp2a/spaceship-eq15.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite1.C
gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite5.C
gcc/testsuite/g++.old-deja/g++.jason/byval2.C
gcc/testsuite/g++.old-deja/g++.other/overload13.C
libstdc++-v3/testsuite/18_support/comparisons/algorithms/fallback.cc