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}} 15 16 bool operator<(const A&) const; 17 bool operator<=(const A&) const = default; 18 bool operator==(const A&) const volatile && = default; // surprisingly, OK 19 bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}} 20 bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}} 21 static bool operator>(const B&) = default; // expected-error {{overloaded 'operator>' cannot be a static member function}} 22 friend bool operator>(A, const A&) = default; // expected-error {{must have the same type}} expected-note {{would be the best match}} 23 24 template<typename T = void> 25 friend bool operator==(const A&, const A&) = default; // expected-error {{comparison operator template cannot be defaulted}} 26 template<typename T = void> 27 bool operator==(const A&) const = default; // expected-error {{comparison operator template cannot be defaulted}} 28 }; 29 30 template<typename T> struct Dependent { 31 using U = typename T::type; 32 bool operator==(U) const = default; // expected-error {{found 'Dependent<Bad>::U'}} 33 friend bool operator==(U, U) = default; // expected-error {{found 'Dependent<Bad>::U'}} 34 }; 35 36 struct Good { using type = const Dependent<Good>&; }; 37 template struct Dependent<Good>; 38 39 struct Bad { using type = Dependent<Bad>&; }; 40 template struct Dependent<Bad>; // expected-note {{in instantiation of}} 41 42 43 namespace std { 44 struct strong_ordering { 45 int n; 46 constexpr operator int() const { return n; } 47 static const strong_ordering equal, greater, less; 48 }; 49 constexpr strong_ordering strong_ordering::equal = {0}; 50 constexpr strong_ordering strong_ordering::greater = {1}; 51 constexpr strong_ordering strong_ordering::less = {-1}; 52 } 53 54 namespace LookupContext { 55 struct A {}; 56 57 namespace N { 58 template <typename T> auto f() { 59 bool operator==(const T &, const T &); 60 bool operator<(const T &, const T &); 61 struct B { 62 T a; 63 std::strong_ordering operator<=>(const B &) const = default; 64 }; 65 return B(); 66 } 67 68 auto g() { 69 struct Cmp { Cmp(std::strong_ordering); }; 70 Cmp operator<=>(const A&, const A&); 71 bool operator!=(const Cmp&, int); 72 struct B { 73 A a; 74 Cmp operator<=>(const B &) const = default; 75 }; 76 return B(); 77 } 78 79 auto h() { 80 struct B; 81 bool operator==(const B&, const B&); 82 bool operator!=(const B&, const B&); // expected-note 2{{best match}} 83 std::strong_ordering operator<=>(const B&, const B&); 84 bool operator<(const B&, const B&); // expected-note 2{{best match}} 85 bool operator<=(const B&, const B&); // expected-note 2{{best match}} 86 bool operator>(const B&, const B&); // expected-note 2{{best match}} 87 bool operator>=(const B&, const B&); // expected-note 2{{best match}} 88 89 struct B { 90 bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} 91 bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} 92 bool operator<=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} 93 bool operator>(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} 94 bool operator>=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} 95 }; 96 return B(); 97 } 98 } 99 100 namespace M { 101 bool operator==(const A &, const A &) = delete; 102 bool operator<(const A &, const A &) = delete; 103 bool cmp = N::f<A>() < N::f<A>(); 104 105 void operator<=>(const A &, const A &) = delete; 106 auto cmp2 = N::g() <=> N::g(); 107 108 void use_h() { 109 N::h() != N::h(); // expected-error {{implicitly deleted}} 110 N::h() < N::h(); // expected-error {{implicitly deleted}} 111 N::h() <= N::h(); // expected-error {{implicitly deleted}} 112 N::h() > N::h(); // expected-error {{implicitly deleted}} 113 N::h() >= N::h(); // expected-error {{implicitly deleted}} 114 } 115 } 116 } 117 118 namespace evil1 { 119 template <class T> struct Bad { 120 // expected-error@+1{{found 'const float &'}} 121 bool operator==(T const &) const = default; 122 Bad(int = 0); 123 }; 124 125 template <class T> struct Weird { 126 // expected-error@+1{{'float' cannot be used prior to '::'}} 127 bool operator==(typename T::Weird_ const &) const = default; 128 Weird(int = 0); 129 }; 130 131 struct evil { 132 using Weird_ = Weird<evil>; 133 }; 134 template struct Bad<float>; // expected-note{{evil1::Bad<float>' requested}} 135 template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}} 136 template struct Weird<evil>; 137 138 } // namespace evil1 139 140 namespace P1946 { 141 struct A { 142 friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}} 143 }; 144 struct B { 145 A a; // expected-note {{no viable three-way comparison}} 146 friend bool operator==(B, B) = default; // ok 147 friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}} 148 }; 149 } 150 151 namespace p2085 { 152 // out-of-class defaulting 153 154 struct S1 { 155 bool operator==(S1 const &) const; 156 }; 157 158 bool S1::operator==(S1 const &) const = default; 159 160 bool F1(S1 &s) { 161 return s != s; 162 } 163 164 struct S2 { 165 friend bool operator==(S2 const &, S2 const &); 166 }; 167 168 bool operator==(S2 const &, S2 const &) = default; 169 bool F2(S2 &s) { 170 return s != s; 171 } 172 173 struct S3 {}; // expected-note{{here}} 174 bool operator==(S3 const &, S3 const &) = default; // expected-error{{not a friend}} 175 176 struct S4; // expected-note{{forward declaration}} 177 bool operator==(S4 const &, S4 const &) = default; // expected-error{{not a friend}} 178 179 struct S5; // expected-note 3{{forward declaration}} 180 bool operator==(S5, S5) = default; // expected-error{{not a friend}} expected-error 2{{has incomplete type}} 181 182 enum e {}; 183 bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}} 184 185 bool operator==(e *, int *) = default; // expected-error{{must have at least one}} 186 } // namespace p2085 187 188 namespace p2085_2 { 189 template <class T> struct S6 { 190 // expected-error@+2{{found 'const int &'}} 191 // expected-error@+1{{found 'const float &'}} 192 bool operator==(T const &) const; 193 }; 194 template <class T> bool S6<T>::operator==(T const &) const = default; 195 196 template struct S6<int>; // expected-note{{S6<int>::operator==' requested}} 197 198 void f1() { 199 S6<float> a; 200 (void)(a == 0); // expected-note{{S6<float>::operator==' requested}} 201 } 202 203 template <class T> struct S7 { 204 // expected-error@+2{{'float' cannot be used}} 205 // expected-error@+1{{'int' cannot be used}} 206 bool operator==(typename T::S7_ const &) const; 207 S7(int = 0); 208 }; 209 template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default; 210 211 struct evil { 212 using S7_ = S7<evil>; 213 }; 214 template struct S7<float>; // expected-note{{S7<float>' requested}} 215 216 void f2() { 217 S7<int> a; // expected-note{{S7<int>' requested}} 218 S7<evil> b; 219 (void)(a == 0); // expected-error{{invalid operands}} 220 (void)(b == 0); 221 } 222 } // namespace p2085_2 223