]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: ambiguous member lookup for rewritten cands [PR113529]
authorPatrick Palka <ppalka@redhat.com>
Wed, 24 Jan 2024 22:11:09 +0000 (17:11 -0500)
committerPatrick Palka <ppalka@redhat.com>
Fri, 26 Jan 2024 14:41:45 +0000 (09:41 -0500)
Here we handle the operator expression u < v inconsistently: in a SFINAE
context we accept 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.

Reviewed-by: Jason Merrill <jason@redhat.com>
(cherry picked from commit fecb45a936d62ca24dd8b4985ea0555c28edefa8)

gcc/cp/call.cc
gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C [new file with mode: 0644]

index 85274b81d7e26ac7ca17cca852883182b9c3c458..d012680f185717f8a38f7a94c628cbaca92c922b 100644 (file)
@@ -6731,7 +6731,9 @@ op_is_ordered (tree_code code)
 
 /* Subroutine of build_new_op: Add to CANDIDATES all candidates for the
    operator indicated by CODE/CODE2.  This function calls itself recursively to
-   handle C++20 rewritten comparison operator candidates.
+   handle C++20 rewritten comparison operator candidates.  Returns NULL_TREE
+   upon success, and error_mark_node if something went wrong that prevented
+   us from performing overload resolution (e.g. ambiguous member name lookup).
 
    LOOKUPS, if non-NULL, is the set of pertinent namespace-scope operator
    overloads to consider.  This parameter is used when instantiating a
@@ -6908,11 +6910,16 @@ add_operator_candidates (z_candidate **candidates,
 
       if (rewrite_code)
        {
+         tree r;
          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.  */
+             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;
 
@@ -6921,8 +6928,10 @@ add_operator_candidates (z_candidate **candidates,
          vec<tree,va_gc> *revlist = make_tree_vector ();
          revlist->quick_push ((*arglist)[1]);
          revlist->quick_push ((*arglist)[0]);
-         add_operator_candidates (candidates, rewrite_code, ERROR_MARK,
-                                  revlist, lookups, flags, complain);
+         r = add_operator_candidates (candidates, rewrite_code, ERROR_MARK,
+                                      revlist, lookups, flags, complain);
+         if (r == error_mark_node)
+           return error_mark_node;
 
          /* Release the vec if we didn't add a candidate that uses it.  */
          for (z_candidate *c = *candidates; c != save_cand; c = c->next)
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-sfinae3.C
new file mode 100644 (file)
index 0000000..ca15926
--- /dev/null
@@ -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);