1 // Force x86-64 because some of our heuristics are actually based
4 // RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
6 // RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -std=c++2a -x c++ %S/Inputs/std-compare.h -emit-pch -o %t.pch
7 // RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s -include-pch %t.pch
9 #include "Inputs/std-compare.h"
11 #define ASSERT_TYPE(...) static_assert(__is_same(__VA_ARGS__))
12 #define ASSERT_EXPR_TYPE(Expr, Expect) static_assert(__is_same(decltype(Expr), Expect));
23 (void)(a
<=> a
); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
24 (void)(b
<=> b
); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
25 (void)(s
.x
[a
] <=> S::x
[a
]); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
28 void test0(long a
, unsigned long b
) {
31 enum EnumC
{C
= 0x10000};
33 (void)((short)a
<=> (unsigned short)b
);
36 (void)(a
<=> (unsigned long)b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
37 (void)(a
<=> (unsigned int) b
);
38 (void)(a
<=> (unsigned short) b
);
39 (void)(a
<=> (unsigned char) b
);
40 (void)((long)a
<=> b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
41 (void)((int)a
<=> b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
42 (void)((short)a
<=> b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
43 (void)((signed char)a
<=> b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
44 (void)((long)a
<=> (unsigned long)b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
45 (void)((int)a
<=> (unsigned int)b
); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
46 (void)((short) a
<=> (unsigned short) b
);
47 (void)((signed char) a
<=> (unsigned char) b
);
50 (void)(A
<=> (unsigned long) b
);
51 (void)(A
<=> (unsigned int) b
);
52 (void)(A
<=> (unsigned short) b
);
53 (void)(A
<=> (unsigned char) b
);
54 (void)((long) A
<=> b
);
55 (void)((int) A
<=> b
);
56 (void)((short) A
<=> b
);
57 (void)((signed char) A
<=> b
);
58 (void)((long) A
<=> (unsigned long) b
);
59 (void)((int) A
<=> (unsigned int) b
);
60 (void)((short) A
<=> (unsigned short) b
);
61 (void)((signed char) A
<=> (unsigned char) b
);
64 (void)(a
<=> (unsigned long) B
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
65 (void)(a
<=> (unsigned int) B
);
66 (void)(a
<=> (unsigned short) B
);
67 (void)(a
<=> (unsigned char) B
);
68 (void)((long) a
<=> B
);
69 (void)((int) a
<=> B
);
70 (void)((short) a
<=> B
);
71 (void)((signed char) a
<=> B
);
72 (void)((long) a
<=> (unsigned long) B
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
73 (void)((int) a
<=> (unsigned int) B
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
74 (void)((short) a
<=> (unsigned short) B
);
75 (void)((signed char) a
<=> (unsigned char) B
);
78 (void)(C
<=> (unsigned long) b
);
79 (void)(C
<=> (unsigned int) b
);
80 (void)(C
<=> (unsigned short) b
); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'unsigned short' is always 'std::strong_ordering::greater'}}
81 (void)(C
<=> (unsigned char) b
); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'unsigned char' is always 'std::strong_ordering::greater'}}
82 (void)((long) C
<=> b
);
83 (void)((int) C
<=> b
);
84 (void)((short) C
<=> b
);
85 (void)((signed char) C
<=> b
);
86 (void)((long) C
<=> (unsigned long) b
);
87 (void)((int) C
<=> (unsigned int) b
);
88 (void)((short) C
<=> (unsigned short) b
);
89 (void)((signed char) C
<=> (unsigned char) b
);
92 (void)(a
<=> (unsigned long) C
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
93 (void)(a
<=> (unsigned int) C
);
94 (void)(a
<=> (unsigned short) C
);
95 (void)(a
<=> (unsigned char) C
);
96 (void)((long) a
<=> C
);
97 (void)((int) a
<=> C
);
98 (void)((short) a
<=> C
); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'short' is always 'std::strong_ordering::less'}}
99 (void)((signed char) a
<=> C
); // expected-warning {{comparison of constant 'C' (65536) with expression of type 'signed char' is always 'std::strong_ordering::less'}}
100 (void)((long) a
<=> (unsigned long) C
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'long' to 'unsigned long'}}
101 (void)((int) a
<=> (unsigned int) C
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
102 (void)((short) a
<=> (unsigned short) C
);
103 (void)((signed char) a
<=> (unsigned char) C
);
106 (void)(0x80000 <=> (unsigned long) b
);
107 (void)(0x80000 <=> (unsigned int) b
);
108 (void)(0x80000 <=> (unsigned short) b
); // expected-warning {{result of comparison of constant 524288 with expression of type 'unsigned short' is always 'std::strong_ordering::greater'}}
109 (void)(0x80000 <=> (unsigned char) b
); // expected-warning {{result of comparison of constant 524288 with expression of type 'unsigned char' is always 'std::strong_ordering::greater'}}
110 (void)((long) 0x80000 <=> b
);
111 (void)((int) 0x80000 <=> b
);
112 (void)((short) 0x80000 <=> b
);
113 (void)((signed char) 0x80000 <=> b
);
114 (void)((long) 0x80000 <=> (unsigned long) b
);
115 (void)((int) 0x80000 <=> (unsigned int) b
);
116 (void)((short) 0x80000 <=> (unsigned short) b
);
117 (void)((signed char) 0x80000 <=> (unsigned char) b
);
120 (void)(a
<=> (unsigned long)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
121 (void)(a
<=> (unsigned int) 0x80000);
122 (void)(a
<=> (unsigned short) 0x80000);
123 (void)(a
<=> (unsigned char) 0x80000);
124 (void)((long) a
<=> 0x80000);
125 (void)((int) a
<=> 0x80000);
126 (void)((short) a
<=> 0x80000); // expected-warning {{comparison of constant 524288 with expression of type 'short' is always 'std::strong_ordering::less'}}
127 (void)((signed char) a
<=> 0x80000); // expected-warning {{comparison of constant 524288 with expression of type 'signed char' is always 'std::strong_ordering::less'}}
128 (void)((long)a
<=> (unsigned long)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
129 (void)((int)a
<=> (unsigned int)0x80000); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
130 (void)((short) a
<=> (unsigned short) 0x80000);
131 (void)((signed char) a
<=> (unsigned char) 0x80000);
134 void test5(bool b
, bool b2
) {
136 (void)(b
<=> b2
); // OK
137 (void)(true <=> b
); // OK
138 (void)(b
<=> -10); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
139 (void)(b
<=> char(1)); // expected-error {{invalid operands to binary expression ('bool' and 'char')}}
140 (void)(b
<=> A
); // expected-error {{invalid operands to binary expression ('bool' and 'EnumA')}}
142 // FIXME: Should this be accepted when narrowing doesn't occur?
143 (void)(b
<=> 0); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
144 (void)(b
<=> 1); // expected-error {{invalid operands to binary expression ('bool' and 'int')}}
147 void test6(signed char sc
) {
148 (void)(sc
<=> 200); // expected-warning{{comparison of constant 200 with expression of type 'signed char' is always 'std::strong_ordering::less'}}
149 (void)(200 <=> sc
); // expected-warning{{comparison of constant 200 with expression of type 'signed char' is always 'std::strong_ordering::greater'}}
152 // Test many signedness combinations.
153 void test7(unsigned long other
) {
154 // Common unsigned, other unsigned, constant unsigned
155 (void)((unsigned)other
<=> (unsigned long)(0x1'ffff'ffff)); // expected-warning{{less}}
156 (void)((unsigned)other
<=> (unsigned long)(0xffff'ffff));
157 (void)((unsigned long)other
<=> (unsigned)(0x1'ffff'ffff));
158 (void)((unsigned long)other
<=> (unsigned)(0xffff'ffff));
160 // Common unsigned, other signed, constant unsigned
161 (void)((int)other
<=> (unsigned long)(0xffff'ffff'ffff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
162 (void)((int)other
<=> (unsigned long)(0x0000'0000'ffff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
163 (void)((int)other
<=> (unsigned long)(0x0000'0000'0fff'ffff)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
164 (void)((int)other
<=> (unsigned)(0x8000'0000)); // expected-error {{argument to 'operator<=>' cannot be narrowed}}
166 // Common unsigned, other unsigned, constant signed
167 (void)((unsigned long)other
<=> (int)(0xffff'ffff)); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
169 // Common unsigned, other signed, constant signed
170 // Should not be possible as the common type should also be signed.
172 // Common signed, other signed, constant signed
173 (void)((int)other
<=> (long)(0xffff'ffff)); // expected-warning{{less}}
174 (void)((int)other
<=> (long)(0xffff'ffff'0000'0000)); // expected-warning{{greater}}
175 (void)((int)other
<=> (long)(0x0fff'ffff));
176 (void)((int)other
<=> (long)(0xffff'ffff'f000'0000));
178 // Common signed, other signed, constant unsigned
179 (void)((int)other
<=> (unsigned char)(0xffff));
180 (void)((int)other
<=> (unsigned char)(0xff));
182 // Common signed, other unsigned, constant signed
183 (void)((unsigned char)other
<=> (int)(0xff));
184 (void)((unsigned char)other
<=> (int)(0xffff)); // expected-warning{{less}}
186 // Common signed, other unsigned, constant unsigned
187 (void)((unsigned char)other
<=> (unsigned short)(0xff));
188 (void)((unsigned char)other
<=> (unsigned short)(0x100)); // expected-warning{{less}}
189 (void)((unsigned short)other
<=> (unsigned char)(0xff));
192 void test8(void *vp
, const void *cvp
, int *ip
) {
193 (void)(vp
<=> cvp
); // OK, void* comparisons are allowed.
198 void test9(long double ld
, double d
, float f
, int i
, long long ll
) {
199 (void)(f
<=> ll
); // OK, floating-point to integer is OK
205 void test_typedef_bug(int *x
, INTPTR y
) {
209 using nullptr_t
= decltype(nullptr);
212 struct ClassB
: Class
{};
214 using FnTy
= void(int);
215 using MemFnTy
= void (Class::*)() const;
216 using MemDataTy
= long(Class::*);
218 void test_nullptr(int *x
, FnTy
*fp
, MemFnTy memp
, MemDataTy memdp
) {
219 auto r1
= (nullptr <=> nullptr); // expected-error {{invalid operands}}
220 auto r2
= (nullptr <=> x
); // expected-error {{invalid operands}}
221 auto r3
= (fp
<=> nullptr); // expected-error {{invalid operands}}
222 auto r4
= (0 <=> fp
); // expected-error {{ordered comparison between pointer and zero}}
223 auto r5
= (nullptr <=> memp
); // expected-error {{invalid operands}}
224 auto r6
= (0 <=> memdp
); // expected-error {{invalid operands}}
225 auto r7
= (0 <=> nullptr); // expected-error {{invalid operands}}
228 void test_memptr(MemFnTy mf
, MemDataTy md
) {
229 (void)(mf
<=> mf
); // expected-error {{invalid operands}} expected-warning {{self-comparison}}
230 (void)(md
<=> md
); // expected-error {{invalid operands}} expected-warning {{self-comparison}}
233 // Test that variable narrowing is deferred for value dependent expressions
235 auto test_template_overflow() {
236 // expected-error@+1 {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned long'}}
237 return (Val
<=> (unsigned long)0);
239 template auto test_template_overflow
<0>();
240 template auto test_template_overflow
<-1>(); // expected-note {{requested here}}
242 void test_enum_integral_compare() {
243 enum EnumA
: int {A
, ANeg
= -1, AMax
= __INT_MAX__
};
244 enum EnumB
: unsigned {B
, BMax
= __UINT32_MAX__
};
245 enum EnumC
: int {C
= -1, C0
= 0};
247 (void)(A
<=> C
); // expected-error {{invalid operands to binary expression ('EnumA' and 'EnumC')}}
249 (void)(A
<=> (unsigned)0);
250 (void)((unsigned)0 <=> A
);
251 (void)(ANeg
<=> (unsigned)0); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
252 (void)((unsigned)0 <=> ANeg
); // expected-error {{cannot be narrowed}}
256 (void)(B
<=> (unsigned long long)42);
257 (void)(B
<=> -1); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
258 (void)(BMax
<=> (unsigned long)-1);
260 (void)(C0
<=> (unsigned)42);
261 (void)(C
<=> (unsigned)42); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
264 namespace EnumCompareTests
{
266 enum class EnumA
{ A
, A2
};
267 enum class EnumB
{ B
};
268 enum class EnumC
: unsigned { C
};
270 void test_enum_enum_compare_no_builtin() {
271 auto r1
= (EnumA::A
<=> EnumA::A2
); // OK
272 ASSERT_EXPR_TYPE(r1
, std::strong_ordering
);
273 (void)(EnumA::A
<=> EnumA::A
); // expected-warning {{self-comparison always evaluates to 'std::strong_ordering::equal'}}
274 (void)(EnumA::A
<=> EnumB::B
); // expected-error {{invalid operands to binary expression ('EnumCompareTests::EnumA' and 'EnumCompareTests::EnumB')}}
275 (void)(EnumB::B
<=> EnumA::A
); // expected-error {{invalid operands}}
280 Tag
<0> operator<=>(EnumA
, EnumA
) { // expected-note {{not viable}}
283 // expected-note@+1 {{while rewriting comparison as call to 'operator<=>' declared here}}
284 Tag
<1> operator<=>(EnumA
, EnumB
) { // expected-note {{not viable}}
288 void test_enum_ovl_provided() {
289 auto r1
= (EnumA::A
<=> EnumA::A
);
290 ASSERT_EXPR_TYPE(r1
, Tag
<0>);
291 auto r2
= (EnumA::A
<=> EnumB::B
);
292 ASSERT_EXPR_TYPE(r2
, Tag
<1>);
293 (void)(EnumB::B
<=> EnumA::A
); // expected-error {{invalid operands to binary expression ('int' and 'Tag<1>')}}
296 void enum_float_test() {
298 (void)(A
<=> (float)0); // expected-error {{invalid operands to binary expression ('EnumA' and 'float')}}
299 (void)((double)0 <=> A
); // expected-error {{invalid operands to binary expression ('double' and 'EnumA')}}
300 (void)((long double)0 <=> A
); // expected-error {{invalid operands to binary expression ('long double' and 'EnumA')}}
303 enum class Bool1
: bool { Zero
,
305 enum Bool2
: bool { B2_Zero
,
308 void test_bool_enum(Bool1 A1
, Bool1 A2
, Bool2 B1
, Bool2 B2
) {
313 } // namespace EnumCompareTests
315 namespace TestUserDefinedConvSeq
{
317 template <class T
, T Val
>
319 constexpr operator T() const { return Val
; }
320 operator T() { return Val
; }
323 void test_user_conv() {
325 using C
= Conv
<int, 0>;
330 (void)((unsigned)0 <=> cc
);
331 (void)((unsigned)0 <=> c
); // expected-error {{argument to 'operator<=>' cannot be narrowed from type 'int' to 'unsigned int'}}
334 using C
= Conv
<int, -1>;
338 (void)(cc
<=> (unsigned)0); // expected-error {{argument to 'operator<=>' evaluates to -1, which cannot be narrowed to type 'unsigned int'}}
339 (void)(c
<=> (unsigned)0); // expected-error {{cannot be narrowed from type 'int' to 'unsigned int'}}
344 constexpr const Conv
<int, -1> operator<=>(X
) { return {}; }
346 static_assert(X() < X());
348 } // namespace TestUserDefinedConvSeq
350 void test_array_conv() {
354 (void)(arr
<=> arr
); // expected-error {{invalid operands to binary expression ('int[5]' and 'int[5]')}}
355 (void)(+arr
<=> arr
);
358 void test_mixed_float_int(float f
, double d
, long double ld
) {
363 extern unsigned short us
;
365 ASSERT_EXPR_TYPE(r1
, std::partial_ordering
);
367 auto r2
= (us
<=> ld
);
368 ASSERT_EXPR_TYPE(r2
, std::partial_ordering
);
371 ASSERT_EXPR_TYPE(r3
, std::partial_ordering
);
373 auto r4
= (0.0 <=> i
);
374 ASSERT_EXPR_TYPE(r4
, std::partial_ordering
);
377 namespace NullptrTest
{
378 using nullptr_t
= decltype(nullptr);
379 void foo(nullptr_t x
, nullptr_t y
) {
380 auto r
= x
<=> y
; // expected-error {{invalid operands}}
382 } // namespace NullptrTest
384 namespace ComplexTest
{
386 enum class StrongE
{};
390 void test_diag(_Complex
int ci
, _Complex
float cf
, _Complex
double cd
, int i
, float f
, StrongE E1
, WeakE E2
, int *p
) { // expected-warning 3 {{'_Complex' is a C99 extension}}
391 (void)(ci
<=> (_Complex
int &)ci
); // expected-warning {{'_Complex' is a C99 extension}} expected-error {{invalid operands}}
392 (void)(ci
<=> cf
); // expected-error {{invalid operands}}
393 (void)(ci
<=> i
); // expected-error {{invalid operands}}
394 (void)(ci
<=> f
); // expected-error {{invalid operands}}
395 (void)(cf
<=> i
); // expected-error {{invalid operands}}
396 (void)(cf
<=> f
); // expected-error {{invalid operands}}
397 (void)(ci
<=> p
); // expected-error {{invalid operands}}
398 (void)(ci
<=> E1
); // expected-error {{invalid operands}}
399 (void)(E2
<=> cf
); // expected-error {{invalid operands}}
402 void test_int(_Complex
int x
, _Complex
int y
) { // expected-warning 2 {{'_Complex' is a C99 extension}}
403 auto r
= x
<=> y
; // expected-error {{invalid operands}}
406 void test_double(_Complex
double x
, _Complex
double y
) { // expected-warning 2 {{'_Complex' is a C99 extension}}
407 auto r
= x
<=> y
; // expected-error {{invalid operands}}
410 } // namespace ComplexTest
413 typedef __attribute__((ext_vector_type(4))) int V
;
415 // This would logically result in a vector of std::strong_ordering, but we
416 // don't support vectors of class type. We could model this as a vector of
417 // int (-1 / 0 / 1), but that doesn't extend to floating-point types (how
418 // to represent 'unordered')? For now, just reject.
419 (void)(v1
<=> v2
); // expected-error {{three-way comparison between vectors is not supported}}
424 extern "C++" struct s
{
425 friend auto operator<=>(s
const &, s
const &) = default;
430 template<typename T
> struct X
{};
431 template<typename T
> bool operator==(const X
<T
> &, int) { return T::error
; } // expected-error 2{{no members}}
432 template<typename T
> int operator<=>(const X
<T
> &, int) { return T::error
; } // expected-error 2{{no members}}
435 template<typename T
> bool f1() { return x1
!= 0; } // expected-note {{instantiation of}}
436 void g1() { f1
<int>(); } // expected-note {{instantiation of}}
439 template<typename T
> bool f2() { return 0 == x2
; } // expected-note {{instantiation of}}
440 void g2() { f2
<int>(); } // expected-note {{instantiation of}}
443 template<typename T
> bool f3() { return x3
< 0; } // expected-note {{instantiation of}}
444 void g3() { f3
<int>(); } // expected-note {{instantiation of}}
447 template<typename T
> bool f4() { return 0 >= x4
; } // expected-note {{instantiation of}}
448 void g4() { f4
<int>(); } // expected-note {{instantiation of}}
450 template<typename T
> struct Y
{};
451 template<typename T
> struct Z
{ Z(int) { T::error
; } using nondeduced
= Z
; }; // expected-error 2{{no members}}
452 template<typename T
> Z
<T
> operator<=>(const Y
<T
>&, int);
453 template<typename T
> bool operator<(const Z
<T
>&, const typename Z
<T
>::nondeduced
&);
454 template<typename T
> bool operator<(const typename Z
<T
>::nondeduced
&, const Z
<T
>&);
457 template<typename T
> bool f5() { return y5
< 0; } // expected-note {{instantiation of}}
458 void g5() { f5
<int>(); } // expected-note {{instantiation of}}
461 template<typename T
> bool f6() { return 0 < y6
; } // expected-note {{instantiation of}}
462 void g6() { f6
<int>(); } // expected-note {{instantiation of}}