1 // RUN: %clang_cc1 -std=c++2a -verify %s 2 3 struct B {}; 4 5 template<typename T = void> 6 bool operator<(const B&, const B&) = default; // expected-error {{comparison operator template cannot be defaulted}} 7 8 struct A { 9 friend bool operator==(const A&, const A&) = default; 10 friend bool operator!=(const A&, const B&) = default; // expected-error {{parameters for defaulted equality comparison operator must have the same type (found 'const A &' vs 'const B &')}} 11 friend bool operator!=(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted equality comparison}} 12 friend bool operator<(const A&, const A&); 13 friend bool operator<(const B&, const B&) = default; // expected-error {{invalid parameter type for defaulted relational comparison}} 14 friend bool operator>(A, A) = default; // expected-warning {{implicitly deleted}} expected-note{{replace 'default'}} 15 16 bool operator<(const A&) const; 17 bool operator<=(const A&) const = default; 18 bool operator==(const A&) const && = default; // expected-error {{ref-qualifier '&&' is not allowed on a defaulted comparison operator}} 19 bool operator<=(const A&&) const = default; // expected-error {{invalid parameter type for defaulted relational comparison operator; found 'const A &&', expected 'const A &'}} 20 bool operator<=(const int&) const = default; // expected-error {{invalid parameter type for defaulted relational comparison operator; found 'const int &', expected 'const A &'}} 21 bool operator>=(const A&) const volatile = default; // expected-error {{defaulted comparison function must not be volatile}} 22 bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}} 23 bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}} 24 static bool operator>(const B&) = default; // expected-error {{overloaded 'operator>' cannot be a static member function}} 25 friend bool operator>(A, const A&) = default; // expected-error {{must have the same type}} expected-note {{would be the best match}} 26 27 template<typename T = void> 28 friend bool operator==(const A&, const A&) = default; // expected-error {{comparison operator template cannot be defaulted}} 29 template<typename T = void> 30 bool operator==(const A&) const = default; // expected-error {{comparison operator template cannot be defaulted}} 31 }; 32 33 template<class C> struct D { 34 C i; 35 friend bool operator==(const D&, D) = default; // expected-error {{must have the same type}} 36 friend bool operator>(D, const D&) = default; // expected-error {{must have the same type}} 37 friend bool operator<(const D&, const D&) = default; 38 friend bool operator<=(D, D) = default; 39 40 bool operator!=(D) const = default; // expected-error {{invalid parameter type for defaulted equality comparison operator}} 41 }; 42 43 template<typename T> struct Dependent { 44 using U = typename T::type; 45 bool operator==(U) const = default; // expected-error {{found 'U'}} 46 friend bool operator==(U, U) = default; // expected-error {{found 'U'}} 47 }; 48 49 struct Good { using type = const Dependent<Good>&; }; 50 template struct Dependent<Good>; 51 52 struct Bad { using type = Dependent<Bad>&; }; 53 template struct Dependent<Bad>; // expected-note {{in instantiation of}} 54 55 56 namespace std { 57 struct strong_ordering { 58 int n; 59 constexpr operator int() const { return n; } 60 static const strong_ordering equal, greater, less; 61 }; 62 constexpr strong_ordering strong_ordering::equal = {0}; 63 constexpr strong_ordering strong_ordering::greater = {1}; 64 constexpr strong_ordering strong_ordering::less = {-1}; 65 } 66 67 namespace LookupContext { 68 struct A {}; 69 70 namespace N { 71 template <typename T> auto f() { 72 bool operator==(const T &, const T &); 73 bool operator<(const T &, const T &); 74 struct B { 75 T a; 76 std::strong_ordering operator<=>(const B &) const = default; 77 }; 78 return B(); 79 } 80 81 auto g() { 82 struct Cmp { Cmp(std::strong_ordering); }; 83 Cmp operator<=>(const A&, const A&); 84 bool operator!=(const Cmp&, int); 85 struct B { 86 A a; 87 Cmp operator<=>(const B &) const = default; 88 }; 89 return B(); 90 } 91 92 auto h() { 93 struct B; 94 bool operator==(const B&, const B&); 95 bool operator!=(const B&, const B&); // expected-note 2{{best match}} 96 std::strong_ordering operator<=>(const B&, const B&); 97 bool operator<(const B&, const B&); // expected-note 2{{best match}} 98 bool operator<=(const B&, const B&); // expected-note 2{{best match}} 99 bool operator>(const B&, const B&); // expected-note 2{{best match}} 100 bool operator>=(const B&, const B&); // expected-note 2{{best match}} 101 102 struct B { 103 bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}} 104 bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}} 105 bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}} 106 bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}} 107 bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}} 108 }; 109 return B(); 110 } 111 } 112 113 namespace M { 114 bool operator==(const A &, const A &) = delete; 115 bool operator<(const A &, const A &) = delete; 116 bool cmp = N::f<A>() < N::f<A>(); 117 118 void operator<=>(const A &, const A &) = delete; 119 auto cmp2 = N::g() <=> N::g(); 120 121 void use_h() { 122 N::h() != N::h(); // expected-error {{implicitly deleted}} 123 N::h() < N::h(); // expected-error {{implicitly deleted}} 124 N::h() <= N::h(); // expected-error {{implicitly deleted}} 125 N::h() > N::h(); // expected-error {{implicitly deleted}} 126 N::h() >= N::h(); // expected-error {{implicitly deleted}} 127 } 128 } 129 } 130 131 namespace evil1 { 132 template <class T> struct Bad { 133 // expected-error@+1{{found 'const float &'}} 134 bool operator==(T const &) const = default; 135 Bad(int = 0); 136 }; 137 138 template <class T> struct Weird { 139 // expected-error@+1{{'float' cannot be used prior to '::'}} 140 bool operator==(typename T::Weird_ const &) const = default; 141 Weird(int = 0); 142 }; 143 144 struct evil { 145 using Weird_ = Weird<evil>; 146 }; 147 template struct Bad<float>; // expected-note{{evil1::Bad<float>' requested}} 148 template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}} 149 template struct Weird<evil>; 150 151 } // namespace evil1 152 153 namespace P1946 { 154 struct A { 155 friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}} 156 }; 157 struct B { 158 A a; // expected-note {{no viable 'operator=='}} 159 friend bool operator==(B, B) = default; // ok 160 friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}} 161 }; 162 } 163 164 namespace p2085 { 165 // out-of-class defaulting 166 167 struct S1 { 168 bool operator==(S1 const &) const; 169 }; 170 171 bool S1::operator==(S1 const &) const = default; 172 173 bool F1(S1 &s) { 174 return s != s; 175 } 176 177 struct S2 { 178 friend bool operator==(S2 const &, S2 const &); 179 }; 180 181 bool operator==(S2 const &, S2 const &) = default; 182 bool F2(S2 &s) { 183 return s != s; 184 } 185 186 struct S3 {}; // expected-note{{here}} 187 bool operator==(S3 const &, S3 const &) = default; // expected-error{{not a friend}} 188 189 struct S4; // expected-note{{forward declaration}} 190 bool operator==(S4 const &, S4 const &) = default; // expected-error{{not a friend}} 191 192 struct S5; // expected-note 3{{forward declaration}} 193 bool operator==(S5, S5) = default; // expected-error{{not a friend}} expected-error 2{{has incomplete type}} 194 195 struct S6; 196 bool operator==(const S6&, const S6&); // expected-note {{previous declaration}} 197 struct S6 { 198 friend bool operator==(const S6&, const S6&) = default; // expected-error {{because it was already declared outside}} 199 }; 200 201 struct S7 { 202 bool operator==(S7 const &) const &&; 203 }; 204 bool S7::operator==(S7 const &) const && = default; // expected-error {{ref-qualifier '&&' is not allowed on a defaulted comparison operator}} 205 206 enum e {}; 207 bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}} 208 209 bool operator==(e *, int *) = default; // expected-error{{must have at least one}} 210 } // namespace p2085 211 212 namespace p2085_2 { 213 template <class T> struct S6 { 214 bool operator==(T const &) const; 215 }; 216 // expected-error@+2{{found 'const int &'}} 217 // expected-error@+1{{found 'const float &'}} 218 template <class T> bool S6<T>::operator==(T const &) const = default; 219 220 template struct S6<int>; // expected-note{{S6<int>::operator==' requested}} 221 222 void f1() { 223 S6<float> a; 224 (void)(a == 0); // expected-note{{S6<float>::operator==' requested}} 225 } 226 227 template <class T> struct S7 { 228 // expected-error@+2{{'float' cannot be used}} 229 // expected-error@+1{{'int' cannot be used}} 230 bool operator==(typename T::S7_ const &) const; 231 S7(int = 0); 232 }; 233 template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default; 234 235 struct evil { 236 using S7_ = S7<evil>; 237 }; 238 template struct S7<float>; // expected-note{{S7<float>' requested}} 239 240 void f2() { 241 S7<int> a; // expected-note{{S7<int>' requested}} 242 S7<evil> b; 243 (void)(a == 0); // expected-error{{invalid operands}} 244 (void)(b == 0); 245 } 246 } // namespace p2085_2 247 248 namespace GH61417 { 249 struct A { 250 unsigned x : 1; 251 unsigned : 0; 252 unsigned y : 1; 253 254 constexpr A() : x(0), y(0) {} 255 bool operator==(const A& rhs) const noexcept = default; 256 }; 257 258 void f1() { 259 constexpr A a, b; 260 constexpr bool c = (a == b); // no diagnostic, we should not be comparing the 261 // unnamed bit-field which is indeterminate 262 } 263 264 void f2() { 265 A a, b; 266 bool c = (a == b); // no diagnostic nor crash during codegen attempting to 267 // access info for unnamed bit-field 268 } 269 } 270 271 namespace GH96043 { 272 template <typename> class a {}; 273 template <typename b> b c(a<b>); 274 template <typename d> class e { 275 public: 276 typedef a<d *> f; 277 f begin(); 278 }; 279 template <typename d, typename g> constexpr bool operator==(d h, g i) { 280 return *c(h.begin()) == *c(i.begin()); 281 } 282 struct j { 283 e<j> bar; 284 bool operator==(const j &) const; 285 }; 286 bool j::operator==(const j &) const = default; 287 } 288