1cafc7416SRichard Smith // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions 25253d913SRichard Smith 35253d913SRichard Smith namespace std { 4e6e6e34bSRichard Smith struct strong_ordering { // expected-note 6{{candidate}} 55253d913SRichard Smith int n; operator intstd::strong_ordering65253d913SRichard Smith constexpr operator int() const { return n; } 75253d913SRichard Smith static const strong_ordering less, equal, greater; 85253d913SRichard Smith }; 95253d913SRichard Smith constexpr strong_ordering strong_ordering::less{-1}, 105253d913SRichard Smith strong_ordering::equal{0}, strong_ordering::greater{1}; 11cafc7416SRichard Smith 12cafc7416SRichard Smith struct weak_ordering { 13cafc7416SRichard Smith int n; weak_orderingstd::weak_ordering14cafc7416SRichard Smith constexpr weak_ordering(int n) : n(n) {} weak_orderingstd::weak_ordering15cafc7416SRichard Smith constexpr weak_ordering(strong_ordering o) : n(o.n) {} operator intstd::weak_ordering16cafc7416SRichard Smith constexpr operator int() const { return n; } 17cafc7416SRichard Smith static const weak_ordering less, equivalent, greater; 18cafc7416SRichard Smith }; 19cafc7416SRichard Smith constexpr weak_ordering weak_ordering::less{-1}, 20cafc7416SRichard Smith weak_ordering::equivalent{0}, weak_ordering::greater{1}; 21cafc7416SRichard Smith 22cafc7416SRichard Smith struct partial_ordering { 23cafc7416SRichard Smith double d; partial_orderingstd::partial_ordering24cafc7416SRichard Smith constexpr partial_ordering(double d) : d(d) {} partial_orderingstd::partial_ordering25cafc7416SRichard Smith constexpr partial_ordering(strong_ordering o) : d(o.n) {} partial_orderingstd::partial_ordering26cafc7416SRichard Smith constexpr partial_ordering(weak_ordering o) : d(o.n) {} operator doublestd::partial_ordering27cafc7416SRichard Smith constexpr operator double() const { return d; } 28cafc7416SRichard Smith static const partial_ordering less, equivalent, greater, unordered; 29cafc7416SRichard Smith }; 30cafc7416SRichard Smith constexpr partial_ordering partial_ordering::less{-1}, 31cafc7416SRichard Smith partial_ordering::equivalent{0}, partial_ordering::greater{1}, 32cafc7416SRichard Smith partial_ordering::unordered{__builtin_nan("")}; 33cafc7416SRichard Smith 34cafc7416SRichard Smith static_assert(!(partial_ordering::unordered < 0)); 35cafc7416SRichard Smith static_assert(!(partial_ordering::unordered == 0)); 36cafc7416SRichard Smith static_assert(!(partial_ordering::unordered > 0)); 375253d913SRichard Smith } 385253d913SRichard Smith 395253d913SRichard Smith namespace Deletedness { 405253d913SRichard Smith struct A { 415253d913SRichard Smith std::strong_ordering operator<=>(const A&) const; 425253d913SRichard Smith }; 435253d913SRichard Smith struct B { 445253d913SRichard Smith bool operator==(const B&) const; 455253d913SRichard Smith bool operator<(const B&) const; 465253d913SRichard Smith }; 475253d913SRichard Smith struct C { 48e6e6e34bSRichard Smith std::strong_ordering operator<=>(const C&) const = delete; // expected-note 2{{deleted}} 495253d913SRichard Smith }; 505253d913SRichard Smith struct D1 { 515253d913SRichard Smith bool operator==(const D1&) const; 52e6e6e34bSRichard Smith std::strong_ordering operator<=>(int) const; // expected-note 2{{function not viable}} expected-note 2{{function (with reversed parameter order) not viable}} 53e6e6e34bSRichard Smith bool operator<(int) const; // expected-note 2{{function not viable}} 545253d913SRichard Smith }; 555253d913SRichard Smith struct D2 { 565253d913SRichard Smith bool operator<(const D2&) const; 57e6e6e34bSRichard Smith std::strong_ordering operator<=>(int) const; // expected-note 2{{function not viable}} expected-note 2{{function (with reversed parameter order) not viable}} 58e6e6e34bSRichard Smith bool operator==(int) const; // expected-note 2{{function not viable}} 595253d913SRichard Smith }; 605253d913SRichard Smith struct E { 615253d913SRichard Smith bool operator==(const E&) const; 62e6e6e34bSRichard Smith bool operator<(const E&) const = delete; // expected-note 2{{deleted}} 635253d913SRichard Smith }; 645253d913SRichard Smith struct F { 65e6e6e34bSRichard Smith std::strong_ordering operator<=>(const F&) const; // expected-note 2{{candidate}} 66e6e6e34bSRichard Smith std::strong_ordering operator<=>(F) const; // expected-note 2{{candidate}} 675253d913SRichard Smith }; 685253d913SRichard Smith struct G1 { 695253d913SRichard Smith bool operator==(const G1&) const; 705253d913SRichard Smith void operator<(const G1&) const; 715253d913SRichard Smith }; 725253d913SRichard Smith struct G2 { 735253d913SRichard Smith void operator==(const G2&) const; 745253d913SRichard Smith bool operator<(const G2&) const; 755253d913SRichard Smith }; 765253d913SRichard Smith struct H { 775253d913SRichard Smith void operator<=>(const H&) const; 785253d913SRichard Smith }; 795253d913SRichard Smith 805253d913SRichard Smith // expected-note@#base {{deleted comparison function for base class 'C'}} 81c9fd92d5SMatheus Izvekov // expected-note@#base {{no viable three-way comparison function for base class 'D1'}} 825253d913SRichard Smith // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}} 83*02bb2beeSAmirreza Ashouri // expected-note@#base {{no viable 'operator==' for base class 'D2'}} 845253d913SRichard Smith // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}} 855253d913SRichard Smith // expected-note@#base {{deleted comparison function for base class 'E'}} 865253d913SRichard Smith // expected-note@#base {{implied comparison for base class 'F' is ambiguous}} 875253d913SRichard Smith template<typename T> struct Cmp : T { // #base 88cafc7416SRichard Smith std::strong_ordering operator<=>(const Cmp&) const = default; // #cmp expected-note 5{{here}} 895253d913SRichard Smith }; 905253d913SRichard Smith 915253d913SRichard Smith void use(...); f()925253d913SRichard Smith void f() { 935253d913SRichard Smith use( 945253d913SRichard Smith Cmp<A>() <=> Cmp<A>(), 955253d913SRichard Smith Cmp<B>() <=> Cmp<B>(), 965253d913SRichard Smith Cmp<C>() <=> Cmp<C>(), // expected-error {{deleted}} 975253d913SRichard Smith Cmp<D1>() <=> Cmp<D1>(), // expected-error {{deleted}} 985253d913SRichard Smith Cmp<D2>() <=> Cmp<D2>(), // expected-error {{deleted}} 995253d913SRichard Smith Cmp<E>() <=> Cmp<E>(), // expected-error {{deleted}} 1005253d913SRichard Smith Cmp<F>() <=> Cmp<F>(), // expected-error {{deleted}} 101cafc7416SRichard Smith // FIXME: The following three errors are not very good. 102cafc7416SRichard Smith // expected-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}} 103cafc7416SRichard Smith Cmp<G1>() <=> Cmp<G1>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G1>' first required here}}j 104cafc7416SRichard Smith // expected-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}} 105cafc7416SRichard Smith Cmp<G2>() <=> Cmp<G2>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G2>' first required here}}j 106cafc7416SRichard Smith // expected-error@#cmp {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} 107cafc7416SRichard Smith Cmp<H>() <=> Cmp<H>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}H>' first required here}}j 1085253d913SRichard Smith 0 1095253d913SRichard Smith ); 1105253d913SRichard Smith } 111e6e6e34bSRichard Smith 112e6e6e34bSRichard Smith // expected-note@#arr {{deleted comparison function for member 'arr'}} 113c9fd92d5SMatheus Izvekov // expected-note@#arr {{no viable three-way comparison function for member 'arr'}} 114e6e6e34bSRichard Smith // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}} 115*02bb2beeSAmirreza Ashouri // expected-note@#arr {{no viable 'operator==' for member 'arr'}} 116e6e6e34bSRichard Smith // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}} 117e6e6e34bSRichard Smith // expected-note@#arr {{deleted comparison function for member 'arr'}} 118e6e6e34bSRichard Smith // expected-note@#arr {{implied comparison for member 'arr' is ambiguous}} 119e6e6e34bSRichard Smith template<typename T> struct CmpArray { 120e6e6e34bSRichard Smith T arr[3]; // #arr 121e6e6e34bSRichard Smith std::strong_ordering operator<=>(const CmpArray&) const = default; // #cmparray expected-note 5{{here}} 122e6e6e34bSRichard Smith }; g()123e6e6e34bSRichard Smith void g() { 124e6e6e34bSRichard Smith use( 125e6e6e34bSRichard Smith CmpArray<A>() <=> CmpArray<A>(), 126e6e6e34bSRichard Smith CmpArray<B>() <=> CmpArray<B>(), 127e6e6e34bSRichard Smith CmpArray<C>() <=> CmpArray<C>(), // expected-error {{deleted}} 128e6e6e34bSRichard Smith CmpArray<D1>() <=> CmpArray<D1>(), // expected-error {{deleted}} 129e6e6e34bSRichard Smith CmpArray<D2>() <=> CmpArray<D2>(), // expected-error {{deleted}} 130e6e6e34bSRichard Smith CmpArray<E>() <=> CmpArray<E>(), // expected-error {{deleted}} 131e6e6e34bSRichard Smith CmpArray<F>() <=> CmpArray<F>(), // expected-error {{deleted}} 132e6e6e34bSRichard Smith // FIXME: The following three errors are not very good. 133e6e6e34bSRichard Smith // expected-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}} 134e6e6e34bSRichard Smith CmpArray<G1>() <=> CmpArray<G1>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G1>' first required here}}j 135e6e6e34bSRichard Smith // expected-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}} 136e6e6e34bSRichard Smith CmpArray<G2>() <=> CmpArray<G2>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G2>' first required here}}j 137e6e6e34bSRichard Smith // expected-error@#cmparray {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} 138e6e6e34bSRichard Smith CmpArray<H>() <=> CmpArray<H>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}H>' first required here}}j 139e6e6e34bSRichard Smith 0 140e6e6e34bSRichard Smith ); 141e6e6e34bSRichard Smith } 1425253d913SRichard Smith } 143cafc7416SRichard Smith 1448e0c9e21SRichard Smith namespace Access { 1458e0c9e21SRichard Smith class A { 1468e0c9e21SRichard Smith std::strong_ordering operator<=>(const A &) const; // expected-note {{here}} 1478e0c9e21SRichard Smith public: 1488e0c9e21SRichard Smith bool operator==(const A &) const; 1498e0c9e21SRichard Smith bool operator<(const A &) const; 1508e0c9e21SRichard Smith }; 1518e0c9e21SRichard Smith struct B { 1528e0c9e21SRichard Smith A a; // expected-note {{would invoke a private 'operator<=>'}} 1531376c739SNathan James friend std::strong_ordering operator<=>(const B &, const B &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}} 1548e0c9e21SRichard Smith }; 1558e0c9e21SRichard Smith 1568e0c9e21SRichard Smith class C { 1578e0c9e21SRichard Smith std::strong_ordering operator<=>(const C &); // not viable (not const) 1588e0c9e21SRichard Smith bool operator==(const C &) const; // expected-note {{here}} 1598e0c9e21SRichard Smith bool operator<(const C &) const; 1608e0c9e21SRichard Smith }; 1618e0c9e21SRichard Smith struct D { 1628e0c9e21SRichard Smith C c; // expected-note {{would invoke a private 'operator=='}} 1631376c739SNathan James friend std::strong_ordering operator<=>(const D &, const D &) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}} 1648e0c9e21SRichard Smith }; 1658e0c9e21SRichard Smith } 1668e0c9e21SRichard Smith 167cafc7416SRichard Smith namespace Synthesis { 168cafc7416SRichard Smith enum Result { False, True, Mu }; 169cafc7416SRichard Smith toBool(Result R)170cafc7416SRichard Smith constexpr bool toBool(Result R) { 171cafc7416SRichard Smith if (R == Mu) throw "should not ask this question"; 172cafc7416SRichard Smith return R == True; 173cafc7416SRichard Smith } 174cafc7416SRichard Smith 175cafc7416SRichard Smith struct Val { 176cafc7416SRichard Smith Result equal, less; operator ==Synthesis::Val177cafc7416SRichard Smith constexpr bool operator==(const Val&) const { return toBool(equal); } operator <Synthesis::Val178cafc7416SRichard Smith constexpr bool operator<(const Val&) const { return toBool(less); } 179cafc7416SRichard Smith }; 180cafc7416SRichard Smith 181cafc7416SRichard Smith template<typename T> struct Cmp { 182cafc7416SRichard Smith Val val; 183cafc7416SRichard Smith friend T operator<=>(const Cmp&, const Cmp&) = default; // expected-note {{deleted}} 184cafc7416SRichard Smith }; 185cafc7416SRichard Smith cmp(Result equal,Result less=Mu,Result reverse_less=Mu)186cafc7416SRichard Smith template<typename T> constexpr auto cmp(Result equal, Result less = Mu, Result reverse_less = Mu) { 187cafc7416SRichard Smith return Cmp<T>{equal, less} <=> Cmp<T>{Mu, reverse_less}; 188cafc7416SRichard Smith } 189cafc7416SRichard Smith 190cafc7416SRichard Smith static_assert(cmp<std::strong_ordering>(True) == 0); 191cafc7416SRichard Smith static_assert(cmp<std::strong_ordering>(False, True) < 0); 192cafc7416SRichard Smith static_assert(cmp<std::strong_ordering>(False, False) > 0); 193cafc7416SRichard Smith 194cafc7416SRichard Smith static_assert(cmp<std::weak_ordering>(True) == 0); 195cafc7416SRichard Smith static_assert(cmp<std::weak_ordering>(False, True) < 0); 196cafc7416SRichard Smith static_assert(cmp<std::weak_ordering>(False, False) > 0); 197cafc7416SRichard Smith 198cafc7416SRichard Smith static_assert(cmp<std::partial_ordering>(True) == 0); 199cafc7416SRichard Smith static_assert(cmp<std::partial_ordering>(False, True) < 0); 200cafc7416SRichard Smith static_assert(cmp<std::partial_ordering>(False, False, True) > 0); 201cafc7416SRichard Smith static_assert(!(cmp<std::partial_ordering>(False, False, False) > 0)); 202cafc7416SRichard Smith static_assert(!(cmp<std::partial_ordering>(False, False, False) == 0)); 203cafc7416SRichard Smith static_assert(!(cmp<std::partial_ordering>(False, False, False) < 0)); 204cafc7416SRichard Smith 205cafc7416SRichard Smith // No synthesis is performed for a custom return type, even if it can be 206cafc7416SRichard Smith // converted from a standard ordering. 207cafc7416SRichard Smith struct custom_ordering { 208cafc7416SRichard Smith custom_ordering(std::strong_ordering o); 209cafc7416SRichard Smith }; f(Cmp<custom_ordering> c)210cafc7416SRichard Smith void f(Cmp<custom_ordering> c) { 211cafc7416SRichard Smith c <=> c; // expected-error {{deleted}} 212cafc7416SRichard Smith } 213cafc7416SRichard Smith } 214cafc7416SRichard Smith 215cafc7416SRichard Smith namespace Preference { 216cafc7416SRichard Smith struct A { 217cafc7416SRichard Smith A(const A&) = delete; // expected-note {{deleted}} 218cafc7416SRichard Smith // "usable" candidate that can't actually be called 219cafc7416SRichard Smith friend void operator<=>(A, A); // expected-note {{passing}} 220cafc7416SRichard Smith // Callable candidates for synthesis not considered. 221cafc7416SRichard Smith friend bool operator==(A, A); 222cafc7416SRichard Smith friend bool operator<(A, A); 223cafc7416SRichard Smith }; 224cafc7416SRichard Smith 225cafc7416SRichard Smith struct B { 226cafc7416SRichard Smith B(); 227cafc7416SRichard Smith A a; 22815f3cd6bSMatheus Izvekov std::strong_ordering operator<=>(const B&) const = default; // expected-error {{call to deleted constructor of 'A'}} 229cafc7416SRichard Smith }; 2305df593a3SCongcong Cai bool x = B() < B(); // expected-note {{in defaulted three-way comparison operator for 'B' first required here}} 231cafc7416SRichard Smith } 232