Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CXX / class / class.compare / class.compare.default / p1.cpp
blob252860bfc4de077c046501835dc331f228898945
1 // RUN: %clang_cc1 -std=c++2a -verify %s
3 struct B {};
5 template<typename T = void>
6 bool operator<(const B&, const B&) = default; // expected-error {{comparison operator template cannot be defaulted}}
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'}}
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 volatile = default; // expected-error {{defaulted comparison function must not be volatile}}
20 bool operator<=>(const A&) = default; // expected-error {{defaulted member three-way comparison operator must be const-qualified}}
21 bool operator>=(const B&) const = default; // expected-error-re {{invalid parameter type for defaulted relational comparison operator; found 'const B &', expected 'const A &'{{$}}}}
22 static bool operator>(const B&) = default; // expected-error {{overloaded 'operator>' cannot be a static member function}}
23 friend bool operator>(A, const A&) = default; // expected-error {{must have the same type}} expected-note {{would be the best match}}
25 template<typename T = void>
26 friend bool operator==(const A&, const A&) = default; // expected-error {{comparison operator template cannot be defaulted}}
27 template<typename T = void>
28 bool operator==(const A&) const = default; // expected-error {{comparison operator template cannot be defaulted}}
31 template<class C> struct D {
32 C i;
33 friend bool operator==(const D&, D) = default; // expected-error {{must have the same type}}
34 friend bool operator>(D, const D&) = default; // expected-error {{must have the same type}}
35 friend bool operator<(const D&, const D&) = default;
36 friend bool operator<=(D, D) = default;
38 bool operator!=(D) const = default; // expected-error {{invalid parameter type for defaulted equality comparison operator}}
41 template<typename T> struct Dependent {
42 using U = typename T::type;
43 bool operator==(U) const = default; // expected-error {{found 'U'}}
44 friend bool operator==(U, U) = default; // expected-error {{found 'U'}}
47 struct Good { using type = const Dependent<Good>&; };
48 template struct Dependent<Good>;
50 struct Bad { using type = Dependent<Bad>&; };
51 template struct Dependent<Bad>; // expected-note {{in instantiation of}}
54 namespace std {
55 struct strong_ordering {
56 int n;
57 constexpr operator int() const { return n; }
58 static const strong_ordering equal, greater, less;
60 constexpr strong_ordering strong_ordering::equal = {0};
61 constexpr strong_ordering strong_ordering::greater = {1};
62 constexpr strong_ordering strong_ordering::less = {-1};
65 namespace LookupContext {
66 struct A {};
68 namespace N {
69 template <typename T> auto f() {
70 bool operator==(const T &, const T &);
71 bool operator<(const T &, const T &);
72 struct B {
73 T a;
74 std::strong_ordering operator<=>(const B &) const = default;
76 return B();
79 auto g() {
80 struct Cmp { Cmp(std::strong_ordering); };
81 Cmp operator<=>(const A&, const A&);
82 bool operator!=(const Cmp&, int);
83 struct B {
84 A a;
85 Cmp operator<=>(const B &) const = default;
87 return B();
90 auto h() {
91 struct B;
92 bool operator==(const B&, const B&);
93 bool operator!=(const B&, const B&); // expected-note 2{{best match}}
94 std::strong_ordering operator<=>(const B&, const B&);
95 bool operator<(const B&, const B&); // expected-note 2{{best match}}
96 bool operator<=(const B&, const B&); // expected-note 2{{best match}}
97 bool operator>(const B&, const B&); // expected-note 2{{best match}}
98 bool operator>=(const B&, const B&); // expected-note 2{{best match}}
100 struct B {
101 bool operator!=(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
102 bool operator<(const B&) const = default; // expected-warning {{implicitly deleted}} expected-note {{deleted here}} expected-note{{replace 'default'}}
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'}}
107 return B();
111 namespace M {
112 bool operator==(const A &, const A &) = delete;
113 bool operator<(const A &, const A &) = delete;
114 bool cmp = N::f<A>() < N::f<A>();
116 void operator<=>(const A &, const A &) = delete;
117 auto cmp2 = N::g() <=> N::g();
119 void use_h() {
120 N::h() != N::h(); // expected-error {{implicitly deleted}}
121 N::h() < N::h(); // expected-error {{implicitly deleted}}
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}}
129 namespace evil1 {
130 template <class T> struct Bad {
131 // expected-error@+1{{found 'const float &'}}
132 bool operator==(T const &) const = default;
133 Bad(int = 0);
136 template <class T> struct Weird {
137 // expected-error@+1{{'float' cannot be used prior to '::'}}
138 bool operator==(typename T::Weird_ const &) const = default;
139 Weird(int = 0);
142 struct evil {
143 using Weird_ = Weird<evil>;
145 template struct Bad<float>; // expected-note{{evil1::Bad<float>' requested}}
146 template struct Weird<float>; // expected-note{{evil1::Weird<float>' requested}}
147 template struct Weird<evil>;
149 } // namespace evil1
151 namespace P1946 {
152 struct A {
153 friend bool operator==(A &, A &); // expected-note {{would lose const qualifier}}
155 struct B {
156 A a; // expected-note {{no viable 'operator=='}}
157 friend bool operator==(B, B) = default; // ok
158 friend bool operator==(const B&, const B&) = default; // expected-warning {{deleted}} expected-note{{replace 'default'}}
162 namespace p2085 {
163 // out-of-class defaulting
165 struct S1 {
166 bool operator==(S1 const &) const;
169 bool S1::operator==(S1 const &) const = default;
171 bool F1(S1 &s) {
172 return s != s;
175 struct S2 {
176 friend bool operator==(S2 const &, S2 const &);
179 bool operator==(S2 const &, S2 const &) = default;
180 bool F2(S2 &s) {
181 return s != s;
184 struct S3 {}; // expected-note{{here}}
185 bool operator==(S3 const &, S3 const &) = default; // expected-error{{not a friend}}
187 struct S4; // expected-note{{forward declaration}}
188 bool operator==(S4 const &, S4 const &) = default; // expected-error{{not a friend}}
190 struct S5; // expected-note 3{{forward declaration}}
191 bool operator==(S5, S5) = default; // expected-error{{not a friend}} expected-error 2{{has incomplete type}}
193 struct S6;
194 bool operator==(const S6&, const S6&); // expected-note {{previous declaration}}
195 struct S6 {
196 friend bool operator==(const S6&, const S6&) = default; // expected-error {{because it was already declared outside}}
199 struct S7 {
200 bool operator==(S7 const &) const &&;
202 bool S7::operator==(S7 const &) const && = default; // expected-error {{ref-qualifier '&&' is not allowed on a defaulted comparison operator}}
204 enum e {};
205 bool operator==(e, int) = default; // expected-error{{expected class or reference to a constant class}}
207 bool operator==(e *, int *) = default; // expected-error{{must have at least one}}
208 } // namespace p2085
210 namespace p2085_2 {
211 template <class T> struct S6 {
212 bool operator==(T const &) const;
214 // expected-error@+2{{found 'const int &'}}
215 // expected-error@+1{{found 'const float &'}}
216 template <class T> bool S6<T>::operator==(T const &) const = default;
218 template struct S6<int>; // expected-note{{S6<int>::operator==' requested}}
220 void f1() {
221 S6<float> a;
222 (void)(a == 0); // expected-note{{S6<float>::operator==' requested}}
225 template <class T> struct S7 {
226 // expected-error@+2{{'float' cannot be used}}
227 // expected-error@+1{{'int' cannot be used}}
228 bool operator==(typename T::S7_ const &) const;
229 S7(int = 0);
231 template <class T> bool S7<T>::operator==(typename T::S7_ const &) const = default;
233 struct evil {
234 using S7_ = S7<evil>;
236 template struct S7<float>; // expected-note{{S7<float>' requested}}
238 void f2() {
239 S7<int> a; // expected-note{{S7<int>' requested}}
240 S7<evil> b;
241 (void)(a == 0); // expected-error{{invalid operands}}
242 (void)(b == 0);
244 } // namespace p2085_2
246 namespace GH61417 {
247 struct A {
248 unsigned x : 1;
249 unsigned : 0;
250 unsigned y : 1;
252 constexpr A() : x(0), y(0) {}
253 bool operator==(const A& rhs) const noexcept = default;
256 void f1() {
257 constexpr A a, b;
258 constexpr bool c = (a == b); // no diagnostic, we should not be comparing the
259 // unnamed bit-field which is indeterminate
262 void f2() {
263 A a, b;
264 bool c = (a == b); // no diagnostic nor crash during codegen attempting to
265 // access info for unnamed bit-field