diff options
author | Jason Merrill <jason@redhat.com> | 2025-04-01 13:04:05 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2025-04-03 11:19:30 -0400 |
commit | bd5597156ca0c7d6fb50c6fe92a7abe6717cb2b5 (patch) | |
tree | a2dff69fe1420d8f748f70722b6b6c0f5d33b665 /gcc/testsuite | |
parent | 26e9139691ac73f53fad64960a0ea48830adfa52 (diff) | |
download | gcc-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.C | 33 |
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> ); |