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