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