xref: /llvm-project/clang/test/CXX/class/class.compare/class.compare.default/p3.cpp (revision f9a14782000e6aa2c4031bc97b20c351a9f281c3)
15253d913SRichard Smith // This test is for the [class.compare.default]p3 added by P2002R0
2*f9a14782SAmy Huang // Also covers modifications made by P2448R2
35253d913SRichard Smith 
4*f9a14782SAmy Huang // RUN: %clang_cc1 -std=c++2a -verify=expected,cxx2a %s
5*f9a14782SAmy Huang // RUN: %clang_cc1 -std=c++23 -verify=expected %s
65253d913SRichard Smith 
75253d913SRichard Smith namespace std {
85253d913SRichard Smith   struct strong_ordering {
95253d913SRichard Smith     int n;
operator intstd::strong_ordering105253d913SRichard Smith     constexpr operator int() const { return n; }
115253d913SRichard Smith     static const strong_ordering less, equal, greater;
125253d913SRichard Smith   };
135253d913SRichard Smith   constexpr strong_ordering strong_ordering::less = {-1};
145253d913SRichard Smith   constexpr strong_ordering strong_ordering::equal = {0};
155253d913SRichard Smith   constexpr strong_ordering strong_ordering::greater = {1};
165253d913SRichard Smith }
175253d913SRichard Smith 
185253d913SRichard Smith struct A {
195253d913SRichard Smith   friend bool operator==(const A&, const A&) = default;
205253d913SRichard Smith   friend bool operator!=(const A&, const A&) = default;
215253d913SRichard Smith 
225253d913SRichard Smith   friend std::strong_ordering operator<=>(const A&, const A&) = default;
235253d913SRichard Smith   friend bool operator<(const A&, const A&) = default;
245253d913SRichard Smith   friend bool operator<=(const A&, const A&) = default;
255253d913SRichard Smith   friend bool operator>(const A&, const A&) = default;
265253d913SRichard Smith   friend bool operator>=(const A&, const A&) = default;
275253d913SRichard Smith };
285253d913SRichard Smith struct TestA {
294a4e90a8SRichard Smith   friend constexpr bool operator==(const A&, const A&) noexcept;
304a4e90a8SRichard Smith   friend constexpr bool operator!=(const A&, const A&) noexcept;
315253d913SRichard Smith 
324a4e90a8SRichard Smith   friend constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept;
335253d913SRichard Smith   friend constexpr bool operator<(const A&, const A&);
345253d913SRichard Smith   friend constexpr bool operator<=(const A&, const A&);
355253d913SRichard Smith   friend constexpr bool operator>(const A&, const A&);
365253d913SRichard Smith   friend constexpr bool operator>=(const A&, const A&);
375253d913SRichard Smith };
385253d913SRichard Smith 
395253d913SRichard Smith // Declaration order doesn't matter, even though the secondary operators need
405253d913SRichard Smith // to know whether the primary ones are constexpr.
415253d913SRichard Smith struct ReversedA {
425253d913SRichard Smith   friend bool operator>=(const ReversedA&, const ReversedA&) = default;
435253d913SRichard Smith   friend bool operator>(const ReversedA&, const ReversedA&) = default;
445253d913SRichard Smith   friend bool operator<=(const ReversedA&, const ReversedA&) = default;
455253d913SRichard Smith   friend bool operator<(const ReversedA&, const ReversedA&) = default;
465253d913SRichard Smith   friend std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) = default;
475253d913SRichard Smith 
485253d913SRichard Smith   friend bool operator!=(const ReversedA&, const ReversedA&) = default;
495253d913SRichard Smith   friend bool operator==(const ReversedA&, const ReversedA&) = default;
505253d913SRichard Smith };
515253d913SRichard Smith struct TestReversedA {
525253d913SRichard Smith   friend constexpr bool operator>=(const ReversedA&, const ReversedA&);
535253d913SRichard Smith   friend constexpr bool operator>(const ReversedA&, const ReversedA&);
545253d913SRichard Smith   friend constexpr bool operator<=(const ReversedA&, const ReversedA&);
555253d913SRichard Smith   friend constexpr bool operator<(const ReversedA&, const ReversedA&);
564a4e90a8SRichard Smith   friend constexpr std::strong_ordering operator<=>(const ReversedA&, const ReversedA&) noexcept;
575253d913SRichard Smith 
584a4e90a8SRichard Smith   friend constexpr bool operator!=(const ReversedA&, const ReversedA&) noexcept;
594a4e90a8SRichard Smith   friend constexpr bool operator==(const ReversedA&, const ReversedA&) noexcept;
605253d913SRichard Smith };
615253d913SRichard Smith 
625253d913SRichard Smith struct B {
635253d913SRichard Smith   A a;
645253d913SRichard Smith   friend bool operator==(const B&, const B&) = default;
655253d913SRichard Smith   friend bool operator!=(const B&, const B&) = default;
665253d913SRichard Smith 
675253d913SRichard Smith   friend std::strong_ordering operator<=>(const B&, const B&) = default;
685253d913SRichard Smith   friend bool operator<(const B&, const B&) = default;
695253d913SRichard Smith   friend bool operator<=(const B&, const B&) = default;
705253d913SRichard Smith   friend bool operator>(const B&, const B&) = default;
715253d913SRichard Smith   friend bool operator>=(const B&, const B&) = default;
725253d913SRichard Smith };
735253d913SRichard Smith struct TestB {
744a4e90a8SRichard Smith   friend constexpr bool operator==(const B&, const B&) noexcept;
754a4e90a8SRichard Smith   friend constexpr bool operator!=(const B&, const B&) noexcept;
765253d913SRichard Smith 
775253d913SRichard Smith   friend constexpr std::strong_ordering operator<=>(const B&, const B&);
785253d913SRichard Smith   friend constexpr bool operator<(const B&, const B&);
795253d913SRichard Smith   friend constexpr bool operator<=(const B&, const B&);
805253d913SRichard Smith   friend constexpr bool operator>(const B&, const B&);
815253d913SRichard Smith   friend constexpr bool operator>=(const B&, const B&);
825253d913SRichard Smith };
835253d913SRichard Smith 
845253d913SRichard Smith struct C {
85*f9a14782SAmy Huang   friend bool operator==(const C&, const C&); // expected-note {{previous}} \
86*f9a14782SAmy Huang                                               // cxx2a-note 2{{declared here}}
875253d913SRichard Smith   friend bool operator!=(const C&, const C&) = default; // expected-note {{previous}}
885253d913SRichard Smith 
89*f9a14782SAmy Huang   friend std::strong_ordering operator<=>(const C&, const C&); // expected-note {{previous}} \
90*f9a14782SAmy Huang                                                                // cxx2a-note 2{{declared here}}
915253d913SRichard Smith   friend bool operator<(const C&, const C&) = default; // expected-note {{previous}}
925253d913SRichard Smith   friend bool operator<=(const C&, const C&) = default; // expected-note {{previous}}
935253d913SRichard Smith   friend bool operator>(const C&, const C&) = default; // expected-note {{previous}}
945253d913SRichard Smith   friend bool operator>=(const C&, const C&) = default; // expected-note {{previous}}
955253d913SRichard Smith };
965253d913SRichard Smith struct TestC {
975253d913SRichard Smith   friend constexpr bool operator==(const C&, const C&); // expected-error {{non-constexpr}}
985253d913SRichard Smith   friend constexpr bool operator!=(const C&, const C&); // expected-error {{non-constexpr}}
995253d913SRichard Smith 
1005253d913SRichard Smith   friend constexpr std::strong_ordering operator<=>(const C&, const C&); // expected-error {{non-constexpr}}
1015253d913SRichard Smith   friend constexpr bool operator<(const C&, const C&); // expected-error {{non-constexpr}}
1025253d913SRichard Smith   friend constexpr bool operator<=(const C&, const C&); // expected-error {{non-constexpr}}
1035253d913SRichard Smith   friend constexpr bool operator>(const C&, const C&); // expected-error {{non-constexpr}}
1045253d913SRichard Smith   friend constexpr bool operator>=(const C&, const C&); // expected-error {{non-constexpr}}
1055253d913SRichard Smith };
1065253d913SRichard Smith 
1075253d913SRichard Smith struct D {
1085253d913SRichard Smith   A a;
1095253d913SRichard Smith   C c;
1105253d913SRichard Smith   A b;
1115253d913SRichard Smith   friend bool operator==(const D&, const D&) = default; // expected-note {{previous}}
1125253d913SRichard Smith   friend bool operator!=(const D&, const D&) = default; // expected-note {{previous}}
1135253d913SRichard Smith 
1145253d913SRichard Smith   friend std::strong_ordering operator<=>(const D&, const D&) = default; // expected-note {{previous}}
1155253d913SRichard Smith   friend bool operator<(const D&, const D&) = default; // expected-note {{previous}}
1165253d913SRichard Smith   friend bool operator<=(const D&, const D&) = default; // expected-note {{previous}}
1175253d913SRichard Smith   friend bool operator>(const D&, const D&) = default; // expected-note {{previous}}
1185253d913SRichard Smith   friend bool operator>=(const D&, const D&) = default; // expected-note {{previous}}
1195253d913SRichard Smith };
1205253d913SRichard Smith struct TestD {
1215253d913SRichard Smith   friend constexpr bool operator==(const D&, const D&); // expected-error {{non-constexpr}}
1225253d913SRichard Smith   friend constexpr bool operator!=(const D&, const D&); // expected-error {{non-constexpr}}
1235253d913SRichard Smith 
1245253d913SRichard Smith   friend constexpr std::strong_ordering operator<=>(const D&, const D&); // expected-error {{non-constexpr}}
1255253d913SRichard Smith   friend constexpr bool operator<(const D&, const D&); // expected-error {{non-constexpr}}
1265253d913SRichard Smith   friend constexpr bool operator<=(const D&, const D&); // expected-error {{non-constexpr}}
1275253d913SRichard Smith   friend constexpr bool operator>(const D&, const D&); // expected-error {{non-constexpr}}
1285253d913SRichard Smith   friend constexpr bool operator>=(const D&, const D&); // expected-error {{non-constexpr}}
1295253d913SRichard Smith };
1305253d913SRichard Smith 
1315253d913SRichard Smith 
1325253d913SRichard Smith struct E {
1335253d913SRichard Smith   A a;
134*f9a14782SAmy Huang   C c; // cxx2a-note 2{{non-constexpr comparison function would be used to compare member 'c'}}
1355253d913SRichard Smith   A b;
136*f9a14782SAmy Huang   friend constexpr bool operator==(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
1375253d913SRichard Smith   friend constexpr bool operator!=(const E&, const E&) = default;
1385253d913SRichard Smith 
139*f9a14782SAmy Huang   friend constexpr std::strong_ordering operator<=>(const E&, const E&) = default; // cxx2a-error {{cannot be declared constexpr}}
1405253d913SRichard Smith   friend constexpr bool operator<(const E&, const E&) = default;
1415253d913SRichard Smith   friend constexpr bool operator<=(const E&, const E&) = default;
1425253d913SRichard Smith   friend constexpr bool operator>(const E&, const E&) = default;
1435253d913SRichard Smith   friend constexpr bool operator>=(const E&, const E&) = default;
1445253d913SRichard Smith };
1455253d913SRichard Smith 
146*f9a14782SAmy Huang struct E2 : A, C { // cxx2a-note 2{{non-constexpr comparison function would be used to compare base class 'C'}}
147*f9a14782SAmy Huang   friend constexpr bool operator==(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
1485253d913SRichard Smith   friend constexpr bool operator!=(const E2&, const E2&) = default;
1495253d913SRichard Smith 
150*f9a14782SAmy Huang   friend constexpr std::strong_ordering operator<=>(const E2&, const E2&) = default; // cxx2a-error {{cannot be declared constexpr}}
1515253d913SRichard Smith   friend constexpr bool operator<(const E2&, const E2&) = default;
1525253d913SRichard Smith   friend constexpr bool operator<=(const E2&, const E2&) = default;
1535253d913SRichard Smith   friend constexpr bool operator>(const E2&, const E2&) = default;
1545253d913SRichard Smith   friend constexpr bool operator>=(const E2&, const E2&) = default;
1555253d913SRichard Smith };
1565253d913SRichard Smith 
1575253d913SRichard Smith struct F {
158*f9a14782SAmy Huang   friend bool operator==(const F&, const F&); // cxx2a-note {{declared here}}
159*f9a14782SAmy Huang   friend constexpr bool operator!=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
1605253d913SRichard Smith 
161*f9a14782SAmy Huang   friend std::strong_ordering operator<=>(const F&, const F&); // cxx2a-note 4{{non-constexpr comparison function declared here}}
162*f9a14782SAmy Huang   friend constexpr bool operator<(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
163*f9a14782SAmy Huang   friend constexpr bool operator<=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
164*f9a14782SAmy Huang   friend constexpr bool operator>(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
165*f9a14782SAmy Huang   friend constexpr bool operator>=(const F&, const F&) = default; // cxx2a-error {{cannot be declared constexpr}}
1665253d913SRichard Smith };
1675253d913SRichard Smith 
1685253d913SRichard Smith // No implicit 'constexpr' if it's not the first declaration.
1695253d913SRichard Smith // FIXME: This rule creates problems for reordering of declarations; is this
1705253d913SRichard Smith // really the right model?
1715253d913SRichard Smith struct G;
1726a763343SRoy Jacobson bool operator==(const G&, const G&); // expected-note {{previous declaration}}
1736a763343SRoy Jacobson bool operator!=(const G&, const G&); // expected-note {{previous declaration}}
1746a763343SRoy Jacobson std::strong_ordering operator<=>(const G&, const G&); // expected-note {{previous declaration}}
1756a763343SRoy Jacobson bool operator<(const G&, const G&); // expected-note {{previous declaration}}
1766a763343SRoy Jacobson bool operator<=(const G&, const G&); // expected-note {{previous declaration}}
1776a763343SRoy Jacobson bool operator>(const G&, const G&); // expected-note {{previous declaration}}
1786a763343SRoy Jacobson bool operator>=(const G&, const G&); // expected-note {{previous declaration}}
1795253d913SRichard Smith struct G {
1806a763343SRoy Jacobson   friend bool operator==(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1816a763343SRoy Jacobson   friend bool operator!=(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1825253d913SRichard Smith 
1836a763343SRoy Jacobson   friend std::strong_ordering operator<=>(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1846a763343SRoy Jacobson   friend bool operator<(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1856a763343SRoy Jacobson   friend bool operator<=(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1866a763343SRoy Jacobson   friend bool operator>(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1876a763343SRoy Jacobson   friend bool operator>=(const G&, const G&) = default; // expected-error {{because it was already declared outside}}
1885253d913SRichard Smith };
1895253d913SRichard Smith bool operator==(const G&, const G&);
1905253d913SRichard Smith bool operator!=(const G&, const G&);
1915253d913SRichard Smith 
1925253d913SRichard Smith std::strong_ordering operator<=>(const G&, const G&);
1935253d913SRichard Smith bool operator<(const G&, const G&);
1945253d913SRichard Smith bool operator<=(const G&, const G&);
1955253d913SRichard Smith bool operator>(const G&, const G&);
1965253d913SRichard Smith bool operator>=(const G&, const G&);
1971f3f8c36SRichard Smith 
1981f3f8c36SRichard Smith namespace PR44721 {
operator ==(T const &,T const &)1991f3f8c36SRichard Smith   template <typename T> bool operator==(T const &, T const &) { return true; }
operator !=(T const &,U const &)2001f3f8c36SRichard Smith   template <typename T, typename U> bool operator!=(T const &, U const &) { return true; }
operator <=>(T const &,T const &)2011f3f8c36SRichard Smith   template <typename T> int operator<=>(T const &, T const &) { return 0; }
2021f3f8c36SRichard Smith 
2031f3f8c36SRichard Smith   struct S {
2041f3f8c36SRichard Smith     friend bool operator==(const S &, const S &) = default;
2051f3f8c36SRichard Smith     friend bool operator<=>(const S &, const S &) = default;
2061f3f8c36SRichard Smith     int x;
2071f3f8c36SRichard Smith   };
2081f3f8c36SRichard Smith }
209