216 lines · cpp
1// RUN: %clang_cc1 -std=c++2a -verify %s2 3namespace std {4 class strong_ordering {5 int n;6 constexpr strong_ordering(int n) : n(n) {}7 public:8 static const strong_ordering less, equal, greater;9 bool operator!=(int) { return n != 0; }10 };11 constexpr strong_ordering strong_ordering::less{-1},12 strong_ordering::equal{0}, strong_ordering::greater{1};13 14 class weak_ordering {15 int n;16 constexpr weak_ordering(int n) : n(n) {}17 public:18 constexpr weak_ordering(strong_ordering o);19 static const weak_ordering less, equivalent, greater;20 bool operator!=(int) { return n != 0; }21 };22 constexpr weak_ordering weak_ordering::less{-1},23 weak_ordering::equivalent{0}, weak_ordering::greater{1};24 25 class partial_ordering {26 int n;27 constexpr partial_ordering(int n) : n(n) {}28 public:29 constexpr partial_ordering(strong_ordering o);30 constexpr partial_ordering(weak_ordering o);31 static const partial_ordering less, equivalent, greater, unordered;32 bool operator!=(int) { return n != 0; }33 };34 constexpr partial_ordering partial_ordering::less{-1},35 partial_ordering::equivalent{0}, partial_ordering::greater{1},36 partial_ordering::unordered{2};37}38 39namespace DeducedNotCat {40 struct A {41 A operator<=>(const A&) const; // expected-note {{selected 'operator<=>' for member 'a' declared here}}42 };43 struct B {44 A a; // expected-note {{return type 'A' of three-way comparison for member 'a' is not a standard comparison category type}}45 auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}46 };47}48 49namespace DeducedVsSynthesized {50 struct A {51 bool operator==(const A&) const;52 bool operator<(const A&) const;53 };54 struct B {55 A a; // expected-note {{no viable three-way comparison function for member 'a'}}56 auto operator<=>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}57 };58}59 60namespace Deduction {61 template<typename T> struct wrap {62 T t;63 friend auto operator<=>(const wrap&, const wrap&) = default;64 };65 66 using strong = wrap<int>;67 using strong2 = wrap<int*>;68 struct weak {69 friend std::weak_ordering operator<=>(weak, weak);70 };71 using partial = wrap<float>;72 73 template<typename ...T> struct A : T... {74 friend auto operator<=>(const A&, const A&) = default;75 };76 77 template<typename Expected, typename ...Ts> void f() {78 using T = Expected; // expected-note {{previous}}79 using T = decltype(A<Ts...>() <=> A<Ts...>()); // expected-error {{different type}}80 void(A<Ts...>() <=> A<Ts...>()); // trigger synthesis of body81 }82 83 template void f<std::strong_ordering>();84 template void f<std::strong_ordering, strong>();85 template void f<std::strong_ordering, strong, strong2>();86 87 template void f<std::weak_ordering, weak>();88 template void f<std::weak_ordering, weak, strong>();89 template void f<std::weak_ordering, strong, weak>();90 91 template void f<std::partial_ordering, partial>();92 template void f<std::partial_ordering, weak, partial>();93 template void f<std::partial_ordering, strong, partial>();94 template void f<std::partial_ordering, partial, weak>();95 template void f<std::partial_ordering, partial, strong>();96 template void f<std::partial_ordering, weak, partial, strong>();97 98 // Check that the above mechanism works.99 template void f<std::strong_ordering, weak>(); // expected-note {{instantiation of}}100 101 std::strong_ordering x = A<strong>() <=> A<strong>();102}103 104namespace PR44723 {105 // Make sure we trigger return type deduction for a callee 'operator<=>'106 // before inspecting its return type.107 template<int> struct a {108 friend constexpr auto operator<=>(a const &lhs, a const &rhs) {109 return std::strong_ordering::equal;110 }111 };112 struct b {113 friend constexpr auto operator<=>(b const &, b const &) = default;114 a<0> m_value;115 };116 std::strong_ordering cmp_b = b() <=> b();117 118 struct c {119 auto operator<=>(const c&) const&; // expected-note {{selected 'operator<=>' for base class 'c' declared here}}120 };121 struct d : c { // expected-note {{base class 'c' declared here}}122 friend auto operator<=>(const d&, const d&) = default; // #d123 // expected-error@#d {{return type of defaulted 'operator<=>' cannot be deduced because three-way comparison for base class 'c' has a deduced return type and is not yet defined}}124 // expected-warning@#d {{implicitly deleted}}125 // expected-note@#d {{replace 'default'}}126 };127 auto c::operator<=>(const c&) const& { // #c128 return std::strong_ordering::equal;129 }130 // expected-error@+1 {{overload resolution selected deleted operator '<=>'}}131 std::strong_ordering cmp_d = d() <=> d();132 // expected-note@#c 2{{candidate}}133 // expected-note@#d {{candidate function has been implicitly deleted}}134}135 136namespace BadDeducedType {137 struct A {138 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'auto &'}}139 friend auto &operator<=>(const A&, const A&) = default;140 };141 142 struct B {143 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'const auto'}}144 friend const auto operator<=>(const B&, const B&) = default;145 };146 147 template<typename T> struct X {}; // expected-note {{here}}148 struct C {149 // expected-error@+1 {{deduction not allowed in function return type}}150 friend X operator<=>(const C&, const C&) = default;151 };152 153 template<typename T> concept CmpCat = true;154 struct D {155 // expected-error@+1 {{deduced return type for defaulted three-way comparison operator must be 'auto', not 'CmpCat auto'}}156 friend CmpCat auto operator<=>(const D&, const D&) = default;157 };158}159 160namespace PR48856 {161 struct A {162 auto operator<=>(const A &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}163 void (*x)(); // expected-note {{because there is no viable three-way comparison function for member 'x'}}164 };165 166 struct B {167 auto operator<=>(const B &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}168 void (B::*x)(); // expected-note {{because there is no viable three-way comparison function for member 'x'}}169 };170 171 struct C {172 auto operator<=>(const C &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}173 int C::*x; // expected-note {{because there is no viable three-way comparison function for member 'x'}}174 };175}176 177namespace PR50591 {178 struct a1 {179 operator int() const;180 };181 struct b1 {182 auto operator<=>(b1 const &) const = default;183 a1 f;184 };185 std::strong_ordering cmp_b1 = b1() <=> b1();186 187 struct a2 {188 operator float() const;189 };190 struct b2 {191 auto operator<=>(b2 const &) const = default;192 a2 f;193 };194 std::partial_ordering cmp_b2 = b2() <=> b2();195 196 using fp = void (*)();197 198 struct a3 {199 operator fp() const;200 };201 struct b3 {202 auto operator<=>(b3 const &) const = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}}203 a3 f; // expected-note {{because there is no viable three-way comparison function}}204 };205 206 struct a4 { // Test that function pointer conversion operator here is ignored for this overload resolution.207 operator int() const;208 operator fp() const;209 };210 struct b4 {211 auto operator<=>(b4 const &) const = default;212 a4 f;213 };214 std::strong_ordering cmp_b4 = b4() <=> b4();215}216