Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for trunk/13?
-- >8 -- Here we handle the operator expression u < v inconsistently: in a SFINAE context (such as a requires-expression) we accept the it, and in a non-SFINAE context we reject it with error: request for member 'operator<=>' is ambiguous as per [class.member.lookup]/6. This inconsistency is ultimately because we neglect to propagate error_mark_node after recursing in add_operator_candidates, fixed like so. PR c++/113529 gcc/cp/ChangeLog: * call.cc (add_operator_candidates): Propagate error_mark_node result after recursing to find rewritten candidates. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/spaceship-sfinae3.C: New test. --- gcc/cp/call.cc | 11 +++++++--- .../g++.dg/cpp2a/spaceship-sfinae3.C | 22 +++++++++++++++++++ 2 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 1f5ff417c81..183bb8c1348 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -7007,9 +7007,14 @@ add_operator_candidates (z_candidate **candidates, { flags |= LOOKUP_REWRITTEN; if (rewrite_code != code) - /* Add rewritten candidates in same order. */ - add_operator_candidates (candidates, rewrite_code, ERROR_MARK, - arglist, lookups, flags, complain); + { + /* Add rewritten candidates in same order. */ + tree r = add_operator_candidates (candidates, rewrite_code, + ERROR_MARK, arglist, lookups, + flags, complain); + if (r == error_mark_node) + return error_mark_node; + } z_candidate *save_cand = *candidates; diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C new file mode 100644 index 00000000000..ca159260ec7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C @@ -0,0 +1,22 @@ +// PR c++/113529 +// { dg-do compile { target c++20 } } + +#include <compare> + +struct A { + auto operator<=>(const A&) const = default; + bool operator<(const A&) const; +}; +struct B { + auto operator<=>(const B&) const = default; +}; +struct C : A, B { }; + + +template<class T> +void f(T u, T v) { + static_assert(!requires { u < v; }); + u < v; // { dg-error "request for member 'operator<=>' is ambiguous" } +} + +template void f(C, C); -- 2.43.0.386.ge02ecfcc53