xref: /llvm-project/clang/test/AST/ByteCode/builtin-bit-cast.cpp (revision 56fd46edb38e4bab7e48c668683ba72709beb64f)
1 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only %s
2 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s
3 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s
4 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s
5 
6 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter %s
7 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
8 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s
9 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s
10 
11 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
12 #  define LITTLE_END 1
13 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
14 #  define LITTLE_END 0
15 #else
16 #  error "huh?"
17 #endif
18 
19 typedef decltype(nullptr) nullptr_t;
20 typedef __INTPTR_TYPE__ intptr_t;
21 
22 static_assert(sizeof(int) == 4);
23 static_assert(sizeof(long long) == 8);
24 
25 template <class To, class From>
26 constexpr To bit_cast(const From &from) {
27   static_assert(sizeof(To) == sizeof(From));
28   return __builtin_bit_cast(To, from);
29 }
30 
31 template <class Intermediate, class Init>
32 constexpr bool check_round_trip(const Init &init) {
33   return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
34 }
35 
36 template <class Intermediate, class Init>
37 constexpr Init round_trip(const Init &init) {
38   return bit_cast<Init>(bit_cast<Intermediate>(init));
39 }
40 
41 
42 namespace Discarding {
43   struct S { int a; };
44   constexpr int f = (__builtin_bit_cast(int, 2), 0);
45   constexpr int f2 = (__builtin_bit_cast(S, 2), 0);
46 }
47 
48 namespace std {
49 enum byte : unsigned char {};
50 } // namespace std
51 
52 using uint8_t = unsigned char;
53 
54 template<int N>
55 struct bytes {
56   using size_t = unsigned int;
57   unsigned char d[N];
58 
59   constexpr unsigned char &operator[](size_t index) {
60     if (index < N)
61       return d[index];
62   }
63 };
64 
65 
66 template <int N, typename T = unsigned char, int Pad = 0>
67 struct bits {
68   T : Pad;
69   T bits : N;
70 
71   constexpr bool operator==(const T& rhs) const {
72     return bits == rhs;
73   }
74 };
75 
76 template <int N, typename T, int P>
77 constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N, T, P>& rhs) {
78   return lhs.bits == rhs.bits;
79 }
80 
81 #ifdef __SIZEOF_INT128__
82 static_assert(check_round_trip<__int128_t>((__int128_t)34));
83 static_assert(check_round_trip<__int128_t>((__int128_t)-34));
84 
85 constexpr unsigned char OneBit[] = {
86   0x1, 0x0,  0x0,  0x0,
87   0x0, 0x0,  0x0,  0x0,
88   0x0, 0x0,  0x0,  0x0,
89   0x0, 0x0,  0x0,  0x0,
90 };
91 constexpr __int128_t One = 1;
92 constexpr __int128_t Expected = One << 120;
93 static_assert(__builtin_bit_cast(__int128_t, OneBit) == (LITTLE_END ? 1 : Expected));
94 
95 #endif
96 
97 static_assert(check_round_trip<double>(17.0));
98 
99 
100 namespace simple {
101   constexpr int A = __builtin_bit_cast(int, 10);
102   static_assert(A == 10);
103 
104   static_assert(__builtin_bit_cast(unsigned, 1.0F) == 1065353216);
105 
106   struct Bytes {
107     char a, b, c, d;
108   };
109   constexpr unsigned B = __builtin_bit_cast(unsigned, Bytes{10, 12, 13, 14});
110   static_assert(B == (LITTLE_END ? 235736074 : 168561934));
111 
112 
113   constexpr unsigned C = __builtin_bit_cast(unsigned, (_BitInt(32))12);
114   static_assert(C == 12);
115 
116   struct BitInts {
117     _BitInt(16) a;
118     _BitInt(16) b;
119   };
120   constexpr unsigned D = __builtin_bit_cast(unsigned, BitInts{12, 13});
121   static_assert(D == (LITTLE_END ? 851980 : 786445));
122 
123 
124 
125   static_assert(__builtin_bit_cast(char, true) == 1);
126 
127   static_assert(check_round_trip<unsigned>((int)-1));
128   static_assert(check_round_trip<unsigned>((int)0x12345678));
129   static_assert(check_round_trip<unsigned>((int)0x87654321));
130   static_assert(check_round_trip<unsigned>((int)0x0C05FEFE));
131   static_assert(round_trip<float>((int)0x0C05FEFE));
132 
133   static_assert(__builtin_bit_cast(intptr_t, nullptr) == 0); // both-error {{not an integral constant expression}} \
134                                                              // both-note {{indeterminate value can only initialize an object}}
135 
136   constexpr int test_from_nullptr_pass = (__builtin_bit_cast(unsigned char[sizeof(nullptr)], nullptr), 0);
137   constexpr unsigned char NPData[sizeof(nullptr)] = {1,2,3,4};
138   constexpr nullptr_t NP = __builtin_bit_cast(nullptr_t, NPData);
139   static_assert(NP == nullptr);
140 }
141 
142 namespace Fail {
143   constexpr int a = 1/0; // both-error {{must be initialized by a constant expression}} \
144                          // both-note {{division by zero}} \
145                          // both-note {{declared here}}
146   constexpr int b = __builtin_bit_cast(int, a); // both-error {{must be initialized by a constant expression}} \
147                                                 // both-note {{initializer of 'a' is not a constant expression}}
148 }
149 
150 namespace ToPtr {
151   struct S {
152     const int *p = nullptr;
153   };
154   struct P {
155     const int *p; // both-note {{invalid type 'const int *' is a member of 'ToPtr::P'}}
156   };
157   constexpr P p = __builtin_bit_cast(P, S{}); // both-error {{must be initialized by a constant expression}} \
158                                               // both-note {{bit_cast to a pointer type is not allowed in a constant expression}}
159 }
160 
161 namespace Invalid {
162   struct S {
163     int a;
164   };
165   constexpr S s = S{1/0}; // both-error {{must be initialized by a constant expression}} \
166                           // both-note {{division by zero}} \
167                           // both-note {{declared here}}
168   constexpr S s2 = __builtin_bit_cast(S, s); // both-error {{must be initialized by a constant expression}} \
169                                              // both-note {{initializer of 's' is not a constant expression}}
170 }
171 
172 namespace NullPtr {
173   constexpr nullptr_t N = __builtin_bit_cast(nullptr_t, (intptr_t)1u);
174   static_assert(N == nullptr);
175   static_assert(__builtin_bit_cast(nullptr_t, (_BitInt(sizeof(void*) * 8))12) == __builtin_bit_cast(nullptr_t, (unsigned _BitInt(sizeof(void*) * 8))0));
176   static_assert(__builtin_bit_cast(nullptr_t, nullptr) == nullptr);
177 }
178 
179 namespace bitint {
180   constexpr _BitInt(sizeof(int) * 8) BI = ~0;
181   constexpr unsigned int I = __builtin_bit_cast(unsigned int, BI);
182   static_assert(I == ~0u, "");
183 
184   constexpr _BitInt(sizeof(int) * 8) IB = __builtin_bit_cast(_BitInt(sizeof(int) * 8), I); // ref-error {{must be initialized by a constant expression}} \
185                                                                                            // ref-note {{constexpr bit cast involving type '_BitInt(32)' is not yet supported}} \
186                                                                                            // ref-note {{declared here}}
187   static_assert(IB == ~0u, ""); // ref-error {{not an integral constant expression}} \
188                                 // ref-note {{initializer of 'IB' is not a constant expression}}
189 }
190 
191 namespace Classes {
192   class A {
193   public:
194     char a[2];
195   };
196   class B : public A {
197   public:
198     char b[2];
199   };
200   static_assert(__builtin_bit_cast(int, B{{0,  0},{0,  0}}) == 0);
201   static_assert(__builtin_bit_cast(int, B{{13, 0},{0,  0}}) == (LITTLE_END ? 13 : 218103808));
202   static_assert(__builtin_bit_cast(int, B{{13, 7},{12, 20}}) == (LITTLE_END ? 336332557 : 218565652));
203 
204   class Ref {
205   public:
206     const int &a;
207     constexpr Ref(const int &a) : a(a) {}
208   };
209   constexpr int I = 12;
210 
211   typedef __INTPTR_TYPE__ intptr_t;
212   static_assert(__builtin_bit_cast(intptr_t, Ref{I}) == 0); // both-error {{not an integral constant expression}} \
213                                                             // both-note {{bit_cast from a type with a reference member is not allowed in a constant expression}}
214 
215   class C : public A {
216     public:
217     constexpr C() : A{1,2} {}
218     virtual constexpr int get() {
219       return 4;
220     }
221   };
222   static_assert(__builtin_bit_cast(_BitInt(sizeof(C) * 8), C()) == 0); // both-error {{source type must be trivially copyable}}
223 
224 
225   class D : virtual A {};
226   static_assert(__builtin_bit_cast(_BitInt(sizeof(D) * 8), D()) == 0); // both-error {{source type must be trivially copyable}}
227 
228   class F {
229   public:
230     char f[2];
231   };
232 
233   class E : public A, public F {
234   public:
235     constexpr E() : A{1,2}, F{3,4}, e{5,6,7,8} {}
236     char e[4];
237   };
238   static_assert(__builtin_bit_cast(long long, E()) == (LITTLE_END ? 578437695752307201 : 72623859790382856));
239 }
240 
241 struct int_splicer {
242   unsigned x;
243   unsigned y;
244 
245   constexpr int_splicer() : x(1), y(2) {}
246   constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
247 
248   constexpr bool operator==(const int_splicer &other) const {
249     return other.x == x && other.y == y;
250   }
251 };
252 
253 constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
254 
255 #if 1
256 static_assert(bit_cast<unsigned long long>(splice) == (LITTLE_END
257                                                            ? 0xCAFEBABE0C05FEFE
258                                                            : 0x0C05FEFECAFEBABE));
259 
260 constexpr int_splicer IS = bit_cast<int_splicer>(0xCAFEBABE0C05FEFE);
261 static_assert(bit_cast<int_splicer>(0xCAFEBABE0C05FEFE).x == (LITTLE_END
262                                                                   ? 0x0C05FEFE
263                                                                   : 0xCAFEBABE));
264 
265 static_assert(check_round_trip<unsigned long long>(splice));
266 static_assert(check_round_trip<long long>(splice));
267 #endif
268 
269 
270 namespace Overread {
271   /// This used to crash becaus we were reading all elements of the
272   /// source array even though we should only be reading 1.
273   constexpr int a[] = {2,3, 4, 5};
274   constexpr int b = __builtin_bit_cast(int, *(a + 1));
275   static_assert(b == 3);
276 
277   struct S {
278     int a;
279   };
280   constexpr S ss[] = {{1},{2}};
281   constexpr int c = __builtin_bit_cast(int, *(ss + 1));
282   static_assert(c == 2);
283 }
284 
285 
286 /// ---------------------------------------------------------------------------
287 /// From here on, it's things copied from test/SemaCXX/constexpr-builtin-bit.cast.cpp
288 
289 void test_int() {
290   static_assert(round_trip<unsigned>((int)-1));
291   static_assert(round_trip<unsigned>((int)0x12345678));
292   static_assert(round_trip<unsigned>((int)0x87654321));
293   static_assert(round_trip<unsigned>((int)0x0C05FEFE));
294 }
295 
296 void test_array() {
297   constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
298   constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
299   static_assert(bit_cast<unsigned>(input) == expected);
300 
301   /// Same things but with a composite array.
302   struct US { unsigned char I; };
303   constexpr US input2[] = {{0xCA}, {0xFE}, {0xBA}, {0xBE}};
304   static_assert(bit_cast<unsigned>(input2) == expected);
305 }
306 
307 void test_record() {
308   struct int_splicer {
309     unsigned x;
310     unsigned y;
311 
312     constexpr bool operator==(const int_splicer &other) const {
313       return other.x == x && other.y == y;
314     }
315   };
316 
317   constexpr int_splicer splice{0x0C05FEFE, 0xCAFEBABE};
318 
319   static_assert(bit_cast<unsigned long long>(splice) == (LITTLE_END
320                                                              ? 0xCAFEBABE0C05FEFE
321                                                              : 0x0C05FEFECAFEBABE));
322 
323   static_assert(bit_cast<int_splicer>(0xCAFEBABE0C05FEFE).x == (LITTLE_END
324                                                                     ? 0x0C05FEFE
325                                                                     : 0xCAFEBABE));
326 
327   static_assert(check_round_trip<unsigned long long>(splice));
328   static_assert(check_round_trip<long long>(splice));
329 
330   struct base2 {
331   };
332 
333   struct base3 {
334     unsigned z;
335   };
336 
337   struct bases : int_splicer, base2, base3 {
338     unsigned doublez;
339   };
340 
341   struct tuple4 {
342     unsigned x, y, z, doublez;
343 
344     bool operator==(tuple4 const &other) const = default;
345     constexpr bool operator==(bases const &other) const {
346       return x == other.x && y == other.y &&
347              z == other.z && doublez == other.doublez;
348     }
349   };
350   constexpr bases b = {{1, 2}, {}, {3}, 4};
351   constexpr tuple4 t4 = bit_cast<tuple4>(b);
352   static_assert(t4 == tuple4{1, 2, 3, 4});
353   static_assert(check_round_trip<tuple4>(b));
354 
355   constexpr auto b2 = bit_cast<bases>(t4);
356   static_assert(t4 == b2);
357 }
358 
359 void test_partially_initialized() {
360   struct pad {
361     signed char x;
362     int y;
363   };
364 
365   struct no_pad {
366     signed char x;
367     signed char p1, p2, p3;
368     int y;
369   };
370 
371   static_assert(sizeof(pad) == sizeof(no_pad));
372 
373 #if 0
374   constexpr pad pir{4, 4};
375   constexpr int piw = bit_cast<no_pad>(pir).x; // both-error {{constexpr variable 'piw' must be initialized by a constant expression}} \
376                                                // both-note {{in call to 'bit_cast<no_pad, pad>(pir)'}}
377 
378 
379   constexpr no_pad bad = bit_cast<no_pad>(pir); // both-error {{constexpr variable 'bad' must be initialized by a constant expression}} \
380                                                 // both-note {{in call to 'bit_cast<no_pad, pad>(pir)'}}
381   // constexpr pad fine = bit_cast<pad>(no_pad{1, 2, 3, 4, 5});
382   // static_assert(fine.x == 1 && fine.y == 5);
383 #endif
384 }
385 
386 
387 void bad_types() {
388   union X {
389     int x;
390   };
391   static_assert(__builtin_bit_cast(int, X{0}) == 0); // both-error {{not an integral constant expression}} \
392                                                      // both-note {{bit_cast from a union type is not allowed in a constant expression}}
393 
394   struct G {
395     int g;
396   };
397   // both-error@+2 {{constexpr variable 'g' must be initialized by a constant expression}}
398   // both-note@+1 {{bit_cast from a union type is not allowed in a constant expression}}
399   constexpr G g = __builtin_bit_cast(G, X{0});
400   // both-error@+2 {{constexpr variable 'x' must be initialized by a constant expression}}
401   // both-note@+1 {{bit_cast to a union type is not allowed in a constant expression}}
402   constexpr X x = __builtin_bit_cast(X, G{0});
403 
404   struct has_pointer {
405     int *ptr; // both-note 2{{invalid type 'int *' is a member of 'has_pointer'}}
406   };
407 
408   constexpr intptr_t ptr = __builtin_bit_cast(intptr_t, has_pointer{0}); // both-error {{constexpr variable 'ptr' must be initialized by a constant expression}} \
409                                                                          // both-note {{bit_cast from a pointer type is not allowed in a constant expression}}
410 
411   // both-error@+2 {{constexpr variable 'hptr' must be initialized by a constant expression}}
412   // both-note@+1 {{bit_cast to a pointer type is not allowed in a constant expression}}
413   constexpr has_pointer hptr =  __builtin_bit_cast(has_pointer, (intptr_t)0);
414 }
415 
416 void test_array_fill() {
417   constexpr unsigned char a[4] = {1, 2};
418   constexpr unsigned int i = bit_cast<unsigned int>(a);
419   static_assert(i == (LITTLE_END ? 0x00000201 : 0x01020000));
420 }
421 
422 struct vol_mem {
423   volatile int x;
424 };
425 
426 // both-error@+2 {{constexpr variable 'run_vol_mem' must be initialized by a constant expression}}
427 // both-note@+1 {{non-literal type 'vol_mem' cannot be used in a constant expression}}
428 constexpr int run_vol_mem = __builtin_bit_cast(int, vol_mem{43});
429 
430 struct mem_ptr {
431   int vol_mem::*x; // both-note{{invalid type 'int vol_mem::*' is a member of 'mem_ptr'}}
432 };
433 
434 // both-error@+2 {{constexpr variable 'run_mem_ptr' must be initialized by a constant expression}}
435 // both-note@+1 {{bit_cast from a member pointer type is not allowed in a constant expression}}
436 constexpr _BitInt(sizeof(mem_ptr) * 8) run_mem_ptr = __builtin_bit_cast(_BitInt(sizeof(mem_ptr) * 8), mem_ptr{nullptr});
437 
438 constexpr int global_int = 0;
439 
440 struct ref_mem {
441   const int &rm;
442 };
443 // both-error@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}}
444 // both-note@+1 {{bit_cast from a type with a reference member is not allowed in a constant expression}}
445 constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int});
446 
447 namespace test_vector {
448 
449 typedef unsigned uint2 __attribute__((vector_size(2 * sizeof(unsigned))));
450 typedef char byte8 __attribute__((vector_size(sizeof(unsigned long long))));
451 
452 constexpr uint2 test_vector = { 0x0C05FEFE, 0xCAFEBABE };
453 
454 static_assert(bit_cast<unsigned long long>(test_vector) == (LITTLE_END
455                                                                 ? 0xCAFEBABE0C05FEFE
456                                                                 : 0x0C05FEFECAFEBABE), "");
457 static_assert(check_round_trip<uint2>(0xCAFEBABE0C05FEFEULL), "");
458 static_assert(check_round_trip<byte8>(0xCAFEBABE0C05FEFEULL), "");
459 
460 #if 0
461 // expected-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
462 // expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}}
463 constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
464 // expected-error@+2 {{constexpr variable 'bad_short_to_bool9' must be initialized by a constant expression}}
465 // expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}}
466 constexpr bool9 bad_short_to_bool9 = __builtin_bit_cast(bool9, static_cast<unsigned short>(0));
467 // expected-error@+2 {{constexpr variable 'bad_int_to_bool17' must be initialized by a constant expression}}
468 // expected-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(17)))' (vector of 17 'bool' values) is not allowed in a constant expression; element size 1 * element count 17 is not a multiple of the byte size 8}}
469 constexpr bool17 bad_int_to_bool17 = __builtin_bit_cast(bool17, 0x0001CAFEU);
470 #endif
471 }
472 
473 namespace test_complex {
474   constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE };
475   static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), "");
476   static_assert(bit_cast<unsigned long long>(test_int_complex) == (LITTLE_END
477                                                                    ? 0xCAFEBABE0C05FEFE
478                                                                    : 0x0C05FEFECAFEBABE), "");
479   static_assert(sizeof(double) == 2 * sizeof(float));
480   struct TwoFloats { float A; float B; };
481   constexpr _Complex float test_float_complex = {1.0f, 2.0f};
482   constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex);
483   static_assert(TF.A == 1.0f && TF.B == 2.0f);
484 
485   constexpr double D = __builtin_bit_cast(double, test_float_complex);
486   constexpr int M = __builtin_bit_cast(int, test_int_complex); // both-error {{size of '__builtin_bit_cast' source type 'const _Complex unsigned int' does not match destination type 'int' (8 vs 4 bytes)}}
487 }
488 
489 
490 namespace OversizedBitField {
491 #if defined(_WIN32)
492   /// This is an error (not just a warning) on Windows and the field ends up with a size of 1 instead of 4.
493 #else
494   typedef unsigned __INT16_TYPE__ uint16_t;
495   typedef unsigned __INT32_TYPE__ uint32_t;
496   struct S {
497     uint16_t a : 20; // both-warning {{exceeds the width of its type}}
498   };
499 
500   static_assert(sizeof(S) == 4);
501   static_assert(__builtin_bit_cast(S, (uint32_t)32).a == (LITTLE_END ? 32 : 0)); // ref-error {{not an integral constant expression}} \
502                                                                                  // ref-note {{constexpr bit_cast involving bit-field is not yet supported}}
503 #endif
504 }
505 
506 typedef bool bool9 __attribute__((ext_vector_type(9)));
507 // both-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
508 // both-note@+1 {{bit_cast involving type 'bool __attribute__((ext_vector_type(9)))' (vector of 9 'bool' values) is not allowed in a constant expression; element size 1 * element count 9 is not a multiple of the byte size 8}}
509 constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
510 
511 // both-warning@+2 {{returning reference to local temporary object}}
512 // both-note@+1 {{temporary created here}}
513 constexpr const intptr_t &returns_local() { return 0L; }
514 
515 // both-error@+2 {{constexpr variable 'test_nullptr_bad' must be initialized by a constant expression}}
516 // both-note@+1 {{read of temporary whose lifetime has ended}}
517 constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());
518