1 // RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions 2 3 namespace std { 4 struct strong_ordering { // expected-note 6{{candidate}} 5 int n; operator intstd::strong_ordering6 constexpr operator int() const { return n; } 7 static const strong_ordering less, equal, greater; 8 }; 9 constexpr strong_ordering strong_ordering::less{-1}, 10 strong_ordering::equal{0}, strong_ordering::greater{1}; 11 12 struct weak_ordering { 13 int n; weak_orderingstd::weak_ordering14 constexpr weak_ordering(int n) : n(n) {} weak_orderingstd::weak_ordering15 constexpr weak_ordering(strong_ordering o) : n(o.n) {} operator intstd::weak_ordering16 constexpr operator int() const { return n; } 17 static const weak_ordering less, equivalent, greater; 18 }; 19 constexpr weak_ordering weak_ordering::less{-1}, 20 weak_ordering::equivalent{0}, weak_ordering::greater{1}; 21 22 struct partial_ordering { 23 double d; partial_orderingstd::partial_ordering24 constexpr partial_ordering(double d) : d(d) {} partial_orderingstd::partial_ordering25 constexpr partial_ordering(strong_ordering o) : d(o.n) {} partial_orderingstd::partial_ordering26 constexpr partial_ordering(weak_ordering o) : d(o.n) {} operator doublestd::partial_ordering27 constexpr operator double() const { return d; } 28 static const partial_ordering less, equivalent, greater, unordered; 29 }; 30 constexpr partial_ordering partial_ordering::less{-1}, 31 partial_ordering::equivalent{0}, partial_ordering::greater{1}, 32 partial_ordering::unordered{__builtin_nan("")}; 33 34 static_assert(!(partial_ordering::unordered < 0)); 35 static_assert(!(partial_ordering::unordered == 0)); 36 static_assert(!(partial_ordering::unordered > 0)); 37 } 38 39 namespace Deletedness { 40 struct A { 41 std::strong_ordering operator<=>(const A&) const; 42 }; 43 struct B { 44 bool operator==(const B&) const; 45 bool operator<(const B&) const; 46 }; 47 struct C { 48 std::strong_ordering operator<=>(const C&) const = delete; // expected-note 2{{deleted}} 49 }; 50 struct D1 { 51 bool operator==(const D1&) const; 52 std::strong_ordering operator<=>(int) const; // expected-note 2{{function not viable}} expected-note 2{{function (with reversed parameter order) not viable}} 53 bool operator<(int) const; // expected-note 2{{function not viable}} 54 }; 55 struct D2 { 56 bool operator<(const D2&) const; 57 std::strong_ordering operator<=>(int) const; // expected-note 2{{function not viable}} expected-note 2{{function (with reversed parameter order) not viable}} 58 bool operator==(int) const; // expected-note 2{{function not viable}} 59 }; 60 struct E { 61 bool operator==(const E&) const; 62 bool operator<(const E&) const = delete; // expected-note 2{{deleted}} 63 }; 64 struct F { 65 std::strong_ordering operator<=>(const F&) const; // expected-note 2{{candidate}} 66 std::strong_ordering operator<=>(F) const; // expected-note 2{{candidate}} 67 }; 68 struct G1 { 69 bool operator==(const G1&) const; 70 void operator<(const G1&) const; 71 }; 72 struct G2 { 73 void operator==(const G2&) const; 74 bool operator<(const G2&) const; 75 }; 76 struct H { 77 void operator<=>(const H&) const; 78 }; 79 80 // expected-note@#base {{deleted comparison function for base class 'C'}} 81 // expected-note@#base {{no viable three-way comparison function for base class 'D1'}} 82 // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}} 83 // expected-note@#base {{no viable three-way comparison function for base class 'D2'}} 84 // expected-note@#base {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}} 85 // expected-note@#base {{deleted comparison function for base class 'E'}} 86 // expected-note@#base {{implied comparison for base class 'F' is ambiguous}} 87 template<typename T> struct Cmp : T { // #base 88 std::strong_ordering operator<=>(const Cmp&) const = default; // #cmp expected-note 5{{here}} 89 }; 90 91 void use(...); f()92 void f() { 93 use( 94 Cmp<A>() <=> Cmp<A>(), 95 Cmp<B>() <=> Cmp<B>(), 96 Cmp<C>() <=> Cmp<C>(), // expected-error {{deleted}} 97 Cmp<D1>() <=> Cmp<D1>(), // expected-error {{deleted}} 98 Cmp<D2>() <=> Cmp<D2>(), // expected-error {{deleted}} 99 Cmp<E>() <=> Cmp<E>(), // expected-error {{deleted}} 100 Cmp<F>() <=> Cmp<F>(), // expected-error {{deleted}} 101 // FIXME: The following three errors are not very good. 102 // expected-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}} 103 Cmp<G1>() <=> Cmp<G1>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G1>' first required here}}j 104 // expected-error@#cmp {{value of type 'void' is not contextually convertible to 'bool'}} 105 Cmp<G2>() <=> Cmp<G2>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}G2>' first required here}}j 106 // expected-error@#cmp {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} 107 Cmp<H>() <=> Cmp<H>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}Cmp<{{.*}}H>' first required here}}j 108 0 109 ); 110 } 111 112 // expected-note@#arr {{deleted comparison function for member 'arr'}} 113 // expected-note@#arr {{no viable three-way comparison function for member 'arr'}} 114 // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '<' comparison}} 115 // expected-note@#arr {{no viable three-way comparison function for member 'arr'}} 116 // expected-note@#arr {{three-way comparison cannot be synthesized because there is no viable function for '==' comparison}} 117 // expected-note@#arr {{deleted comparison function for member 'arr'}} 118 // expected-note@#arr {{implied comparison for member 'arr' is ambiguous}} 119 template<typename T> struct CmpArray { 120 T arr[3]; // #arr 121 std::strong_ordering operator<=>(const CmpArray&) const = default; // #cmparray expected-note 5{{here}} 122 }; g()123 void g() { 124 use( 125 CmpArray<A>() <=> CmpArray<A>(), 126 CmpArray<B>() <=> CmpArray<B>(), 127 CmpArray<C>() <=> CmpArray<C>(), // expected-error {{deleted}} 128 CmpArray<D1>() <=> CmpArray<D1>(), // expected-error {{deleted}} 129 CmpArray<D2>() <=> CmpArray<D2>(), // expected-error {{deleted}} 130 CmpArray<E>() <=> CmpArray<E>(), // expected-error {{deleted}} 131 CmpArray<F>() <=> CmpArray<F>(), // expected-error {{deleted}} 132 // FIXME: The following three errors are not very good. 133 // expected-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}} 134 CmpArray<G1>() <=> CmpArray<G1>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G1>' first required here}}j 135 // expected-error@#cmparray {{value of type 'void' is not contextually convertible to 'bool'}} 136 CmpArray<G2>() <=> CmpArray<G2>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}G2>' first required here}}j 137 // expected-error@#cmparray {{no matching conversion for static_cast from 'void' to 'std::strong_ordering'}} 138 CmpArray<H>() <=> CmpArray<H>(), // expected-note-re {{in defaulted three-way comparison operator for '{{.*}}CmpArray<{{.*}}H>' first required here}}j 139 0 140 ); 141 } 142 } 143 144 namespace Access { 145 class A { 146 std::strong_ordering operator<=>(const A &) const; // expected-note {{here}} 147 public: 148 bool operator==(const A &) const; 149 bool operator<(const A &) const; 150 }; 151 struct B { 152 A a; // expected-note {{would invoke a private 'operator<=>'}} 153 friend std::strong_ordering operator<=>(const B &, const B &) = default; // expected-warning {{deleted}} 154 }; 155 156 class C { 157 std::strong_ordering operator<=>(const C &); // not viable (not const) 158 bool operator==(const C &) const; // expected-note {{here}} 159 bool operator<(const C &) const; 160 }; 161 struct D { 162 C c; // expected-note {{would invoke a private 'operator=='}} 163 friend std::strong_ordering operator<=>(const D &, const D &) = default; // expected-warning {{deleted}} 164 }; 165 } 166 167 namespace Synthesis { 168 enum Result { False, True, Mu }; 169 toBool(Result R)170 constexpr bool toBool(Result R) { 171 if (R == Mu) throw "should not ask this question"; 172 return R == True; 173 } 174 175 struct Val { 176 Result equal, less; operator ==Synthesis::Val177 constexpr bool operator==(const Val&) const { return toBool(equal); } operator <Synthesis::Val178 constexpr bool operator<(const Val&) const { return toBool(less); } 179 }; 180 181 template<typename T> struct Cmp { 182 Val val; 183 friend T operator<=>(const Cmp&, const Cmp&) = default; // expected-note {{deleted}} 184 }; 185 cmp(Result equal,Result less=Mu,Result reverse_less=Mu)186 template<typename T> constexpr auto cmp(Result equal, Result less = Mu, Result reverse_less = Mu) { 187 return Cmp<T>{equal, less} <=> Cmp<T>{Mu, reverse_less}; 188 } 189 190 static_assert(cmp<std::strong_ordering>(True) == 0); 191 static_assert(cmp<std::strong_ordering>(False, True) < 0); 192 static_assert(cmp<std::strong_ordering>(False, False) > 0); 193 194 static_assert(cmp<std::weak_ordering>(True) == 0); 195 static_assert(cmp<std::weak_ordering>(False, True) < 0); 196 static_assert(cmp<std::weak_ordering>(False, False) > 0); 197 198 static_assert(cmp<std::partial_ordering>(True) == 0); 199 static_assert(cmp<std::partial_ordering>(False, True) < 0); 200 static_assert(cmp<std::partial_ordering>(False, False, True) > 0); 201 static_assert(!(cmp<std::partial_ordering>(False, False, False) > 0)); 202 static_assert(!(cmp<std::partial_ordering>(False, False, False) == 0)); 203 static_assert(!(cmp<std::partial_ordering>(False, False, False) < 0)); 204 205 // No synthesis is performed for a custom return type, even if it can be 206 // converted from a standard ordering. 207 struct custom_ordering { 208 custom_ordering(std::strong_ordering o); 209 }; f(Cmp<custom_ordering> c)210 void f(Cmp<custom_ordering> c) { 211 c <=> c; // expected-error {{deleted}} 212 } 213 } 214 215 namespace Preference { 216 struct A { 217 A(const A&) = delete; // expected-note {{deleted}} 218 // "usable" candidate that can't actually be called 219 friend void operator<=>(A, A); // expected-note {{passing}} 220 // Callable candidates for synthesis not considered. 221 friend bool operator==(A, A); 222 friend bool operator<(A, A); 223 }; 224 225 struct B { 226 B(); 227 A a; 228 std::strong_ordering operator<=>(const B&) const = default; // expected-error {{call to deleted constructor of 'Preference::A'}} 229 }; 230 bool x = B() < B(); // expected-note {{in defaulted three-way comparison operator for 'Preference::B' first required here}} 231 } 232