aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-04-01 13:04:05 -0400
committerJason Merrill <jason@redhat.com>2025-04-03 11:19:30 -0400
commitbd5597156ca0c7d6fb50c6fe92a7abe6717cb2b5 (patch)
treea2dff69fe1420d8f748f70722b6b6c0f5d33b665 /gcc/testsuite
parent26e9139691ac73f53fad64960a0ea48830adfa52 (diff)
downloadgcc-bd5597156ca0c7d6fb50c6fe92a7abe6717cb2b5.zip
gcc-bd5597156ca0c7d6fb50c6fe92a7abe6717cb2b5.tar.gz
gcc-bd5597156ca0c7d6fb50c6fe92a7abe6717cb2b5.tar.bz2
c++: operator!= rewriting and arg-dep lookup
When considering an op== as a rewrite target, we need to disqualify it if there is a matching op!= in the same scope. But add_candidates was assuming that we could use the same set of op!= for all op==, which is wrong if arg-dep lookup finds op== in multiple namespaces. This broke 20_util/optional/relops/constrained.cc if the order of the ADL set changed. gcc/cp/ChangeLog: * call.cc (add_candidates): Re-lookup ne_fns if we move into another namespace. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/spaceship-rewrite6.C: New test.
Diffstat (limited to 'gcc/testsuite')
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite6.C33
1 files changed, 33 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite6.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite6.C
new file mode 100644
index 0000000..0ec74e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/spaceship-rewrite6.C
@@ -0,0 +1,33 @@
+// { dg-do compile { target c++20 } }
+
+// We wrongly considered D to be ne_comparable because we were looking for a
+// corresponding op!= for N::op== in ::, because ::op== happened to be the
+// first thing in the lookup set.
+
+template<bool, typename _Tp = void>
+struct enable_if;
+
+template<typename _Tp>
+struct enable_if<true, _Tp>
+{ typedef _Tp type; };
+
+template <class T, class U> struct A { };
+
+namespace N {
+ struct X { };
+ template <class T> auto operator== (const A<T,X>&, const A<T,X>&)
+ -> typename enable_if<sizeof(T() == T()), bool>::type;
+ template <class T> auto operator!= (const A<T,X>&, const A<T,X>&)
+ -> typename enable_if<sizeof(T() != T()), bool>::type;
+}
+
+template<typename T, typename U = T>
+concept ne_comparable
+= requires (const A<T,N::X>& t, const A<U,N::X>& u) {
+ t != u;
+};
+
+struct D { };
+int operator==(D, D);
+bool operator!=(D, D) = delete;
+static_assert( ! ne_comparable<D> );