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