]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: non-dep cmp op rewritten from <=> returning int [PR121779]
authorPatrick Palka <ppalka@redhat.com>
Tue, 9 Sep 2025 18:39:57 +0000 (14:39 -0400)
committerPatrick Palka <ppalka@redhat.com>
Tue, 9 Sep 2025 18:39:57 +0000 (14:39 -0400)
Apparently an explicitly defined operator<=> isn't required to return
std::foo_ordering, so build_min_non_dep_op_overload needs to be able
to rebuild forms of (x <=> y) @ 0 where the @ resolved to a built-in and
in turn isn't expressed as a function call.

PR c++/121779

gcc/cp/ChangeLog:

* tree.cc (build_min_non_dep_op_overload): Handle comparison
operator expressions rewritten from a <=> that returns a
non-class type.

gcc/testsuite/ChangeLog:

* g++.dg/lookup/operator-8.C: Remove outdated comment about
this test failing.
* g++.dg/lookup/operator-8a.C: New test.

Reviewed-by: Jason Merrill <jason@redhat.com>
gcc/cp/tree.cc
gcc/testsuite/g++.dg/lookup/operator-8.C
gcc/testsuite/g++.dg/lookup/operator-8a.C [new file with mode: 0644]

index e354da0f01858b8a757e7ae5932ef672dc2a0f63..03b58ff60059eb60c790f0920ae97c1768599b99 100644 (file)
@@ -3730,7 +3730,9 @@ build_min_non_dep_op_overload (enum tree_code op,
             rebuild the <=>.  Note that both OVERLOAD and the provided arguments
             in this case already correspond to the selected operator<=>.  */
 
-         tree spaceship_non_dep = CALL_EXPR_ARG (non_dep, reversed ? 1 : 0);
+         tree spaceship_non_dep = (TREE_CODE (non_dep) == CALL_EXPR
+                                   ? CALL_EXPR_ARG (non_dep, reversed ? 1 : 0)
+                                   : TREE_OPERAND (non_dep, reversed ? 1 : 0));
          gcc_checking_assert (TREE_CODE (spaceship_non_dep) == CALL_EXPR);
          tree spaceship_op0 = va_arg (p, tree);
          tree spaceship_op1 = va_arg (p, tree);
@@ -3744,8 +3746,19 @@ build_min_non_dep_op_overload (enum tree_code op,
                                                    TREE_VALUE (overload),
                                                    spaceship_op0,
                                                    spaceship_op1);
-         tree op1 = CALL_EXPR_ARG (non_dep, reversed ? 0 : 1);
+         tree op1 = (TREE_CODE (non_dep) == CALL_EXPR
+                     ? CALL_EXPR_ARG (non_dep, reversed ? 0 : 1)
+                     : TREE_OPERAND (non_dep, reversed ? 0 : 1));
          gcc_checking_assert (integer_zerop (op1));
+
+         if (TREE_CODE (non_dep) != CALL_EXPR)
+           {
+             gcc_checking_assert (COMPARISON_CLASS_P (non_dep));
+             if (reversed)
+               std::swap (op0, op1);
+             return build_min_non_dep (TREE_CODE (non_dep), non_dep, op0, op1);
+           }
+
          vec_safe_push (args, op0);
          vec_safe_push (args, op1);
          overload = CALL_EXPR_FN (non_dep);
index 32d432dd8432d05bd9cdfe16aefe1699fcf2f812..4646a6f1303e787c7647c2bb95317af826798beb 100644 (file)
@@ -1,9 +1,6 @@
 // Verify phase 1 lookup works properly for rewritten non-dependent conditional
 // operator expressions.
 
-// This test currently fails due to build_min_non_dep_op_overload not knowing
-// how to handle rewritten operator expressions; see the FIXME in build_new_op.
-
 // { dg-do compile { target c++20 } }
 
 #include <compare>
diff --git a/gcc/testsuite/g++.dg/lookup/operator-8a.C b/gcc/testsuite/g++.dg/lookup/operator-8a.C
new file mode 100644 (file)
index 0000000..48df783
--- /dev/null
@@ -0,0 +1,40 @@
+// PR c++/121779
+// A version of operator-8.C where the operator<=> return type is int.
+
+// { dg-do compile { target c++20 } }
+
+struct A {
+  bool operator==(int);
+  int operator<=>(int);
+};
+
+template<class T>
+void f() {
+  A a;
+  (void)(a != 0);
+  (void)(0 != a);
+  (void)(a < 0);
+  (void)(0 < a);
+  (void)(a <= 0);
+  (void)(0 <= a);
+  (void)(a > 0);
+  (void)(0 > a);
+  (void)(a >= 0);
+  (void)(0 >= a);
+}
+
+// These later-declared namespace-scope overloads shouldn't be considered
+// when instantiating f<int>.
+bool operator!=(A, int) = delete;
+bool operator<(A, int) = delete;
+bool operator<=(A, int) = delete;
+bool operator>(A, int) = delete;
+bool operator>=(A, int) = delete;
+
+bool operator!=(int, A) = delete;
+bool operator<(int, A) = delete;
+bool operator<=(int, A) = delete;
+bool operator>(int, A) = delete;
+bool operator>=(int, A) = delete;
+
+template void f<int>();