1 // RUN: %clang_cc1 -std=c++2a -verify %s
5 template<typename T
= void>
6 bool operator<(const B
&, const B
&) = default; // expected-error {{comparison operator template cannot be defaulted}}
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 = 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}}
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}}
33 template<class C
> struct D
{
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;
40 bool operator!=(D
) const = default; // expected-error {{invalid parameter type for defaulted equality comparison operator}}
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'}}
49 struct Good
{ using type
= const Dependent
<Good
>&; };
50 template struct Dependent
<Good
>;
52 struct Bad
{ using type
= Dependent
<Bad
>&; };
53 template struct Dependent
<Bad
>; // expected-note {{in instantiation of}}
57 struct strong_ordering
{
59 constexpr operator int() const { return n
; }
60 static const strong_ordering equal
, greater
, less
;
62 constexpr strong_ordering
strong_ordering::equal
= {0};
63 constexpr strong_ordering
strong_ordering::greater
= {1};
64 constexpr strong_ordering
strong_ordering::less
= {-1};
67 namespace LookupContext
{
71 template <typename T
> auto f() {
72 bool operator==(const T
&, const T
&);
73 bool operator<(const T
&, const T
&);
76 std::strong_ordering
operator<=>(const B
&) const = default;
82 struct Cmp
{ Cmp(std::strong_ordering
); };
83 Cmp
operator<=>(const A
&, const A
&);
84 bool operator!=(const Cmp
&, int);
87 Cmp
operator<=>(const B
&) const = default;
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}}
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'}}
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
>();
118 void operator<=>(const A
&, const A
&) = delete;
119 auto cmp2
= N::g() <=> N::g();
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}}
132 template <class T
> struct Bad
{
133 // expected-error@+1{{found 'const float &'}}
134 bool operator==(T
const &) const = default;
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;
145 using Weird_
= Weird
<evil
>;
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
>;
155 friend bool operator==(A
&, A
&); // expected-note {{would lose const qualifier}}
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'}}
165 // out-of-class defaulting
168 bool operator==(S1
const &) const;
171 bool S1::operator==(S1
const &) const = default;
178 friend bool operator==(S2
const &, S2
const &);
181 bool operator==(S2
const &, S2
const &) = default;
186 struct S3
{}; // expected-note{{here}}
187 bool operator==(S3
const &, S3
const &) = default; // expected-error{{not a friend}}
189 struct S4
; // expected-note{{forward declaration}}
190 bool operator==(S4
const &, S4
const &) = default; // expected-error{{not a friend}}
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}}
196 bool operator==(const S6
&, const S6
&); // expected-note {{previous declaration}}
198 friend bool operator==(const S6
&, const S6
&) = default; // expected-error {{because it was already declared outside}}
202 bool operator==(S7
const &) const &&;
204 bool S7::operator==(S7
const &) const && = default; // expected-error {{ref-qualifier '&&' is not allowed on a defaulted comparison operator}}
207 bool operator==(e
, int) = default; // expected-error{{expected class or reference to a constant class}}
209 bool operator==(e
*, int *) = default; // expected-error{{must have at least one}}
213 template <class T
> struct S6
{
214 bool operator==(T
const &) const;
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;
220 template struct S6
<int>; // expected-note{{S6<int>::operator==' requested}}
224 (void)(a
== 0); // expected-note{{S6<float>::operator==' requested}}
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;
233 template <class T
> bool S7
<T
>::operator==(typename
T::S7_
const &) const = default;
236 using S7_
= S7
<evil
>;
238 template struct S7
<float>; // expected-note{{S7<float>' requested}}
241 S7
<int> a
; // expected-note{{S7<int>' requested}}
243 (void)(a
== 0); // expected-error{{invalid operands}}
246 } // namespace p2085_2
254 constexpr A() : x(0), y(0) {}
255 bool operator==(const A
& rhs
) const noexcept
= default;
260 constexpr bool c
= (a
== b
); // no diagnostic, we should not be comparing the
261 // unnamed bit-field which is indeterminate
266 bool c
= (a
== b
); // no diagnostic nor crash during codegen attempting to
267 // access info for unnamed bit-field
272 template <typename
> class a
{};
273 template <typename b
> b
c(a
<b
>);
274 template <typename d
> class e
{
279 template <typename d
, typename g
> constexpr bool operator==(d h
, g i
) {
280 return *c(h
.begin()) == *c(i
.begin());
284 bool operator==(const j
&) const;
286 bool j::operator==(const j
&) const = default;