xref: /llvm-project/clang/test/AST/ByteCode/builtin-bit-cast-bitfields.cpp (revision b4150ed128a136409a2510ee00003bd318f703fb)
1 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter %s
2 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple armv8 -fexperimental-new-constant-interpreter %s
3 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
4 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s
5 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s
6 
7 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
8 #  define LITTLE_END 1
9 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
10 #  define LITTLE_END 0
11 #else
12 #  error "huh?"
13 #endif
14 
15 typedef decltype(nullptr) nullptr_t;
16 typedef __INTPTR_TYPE__ intptr_t;
17 typedef unsigned __INT16_TYPE__ uint16_t;
18 typedef unsigned __INT32_TYPE__ uint32_t;
19 typedef unsigned __INT64_TYPE__ uint64_t;
20 
21 static_assert(sizeof(int) == 4);
22 static_assert(sizeof(long long) == 8);
23 
24 template <class To, class From>
25 constexpr To bit_cast(const From &from) {
26   static_assert(sizeof(To) == sizeof(From));
27   return __builtin_bit_cast(To, from);
28 }
29 
30 template <class Intermediate, class Init>
31 constexpr bool check_round_trip(const Init &init) {
32   return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
33 }
34 
35 template <class Intermediate, class Init>
36 constexpr Init round_trip(const Init &init) {
37   return bit_cast<Init>(bit_cast<Intermediate>(init));
38 }
39 
40 namespace std {
41 enum byte : unsigned char {};
42 } // namespace std
43 
44 template <int N, typename T = unsigned char, int Pad = 0>
45 struct bits {
46   T : Pad;
47   T bits : N;
48 
49   constexpr bool operator==(const T& rhs) const {
50     return bits == rhs;
51   }
52 };
53 
54 template <int N, typename T, int P>
55 constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N, T, P>& rhs) {
56   return lhs.bits == rhs.bits;
57 }
58 
59 template<int N>
60 struct bytes {
61   using size_t = unsigned int;
62   unsigned char d[N];
63 
64   constexpr unsigned char operator[](size_t index) {
65     if (index < N)
66       return d[index]; // expected-note {{read of uninitialized object}}
67     return -1;
68   }
69 };
70 
71 namespace Sanity {
72   /// This is just one byte, and we extract 2 bits from it.
73   ///
74   /// 3 is 0000'0011.
75   /// For both LE and BE, the buffer will contain exactly that
76   /// byte, unaltered and not reordered in any way. It contains all 8 bits.
77   static_assert(__builtin_bit_cast(bits<2>, (unsigned char)3) == (LITTLE_END ? 3 : 0));
78 
79   /// Similarly, we have one full byte of data, with the two most-significant
80   /// bits set:
81   /// 192 is 1100'0000
82   static_assert(__builtin_bit_cast(bits<2>, (unsigned char)192) == (LITTLE_END ? 0 : 3));
83 
84 
85   /// Here we are instead bitcasting two 1-bits into a destination of 8 bits.
86   /// On LE, we should pick the two least-significant bits. On BE, the opposite.
87   /// NOTE: Can't verify this with gcc.
88   constexpr auto B1 = bits<2>{3};
89   static_assert(__builtin_bit_cast(unsigned char, B1) == (LITTLE_END ? 3 : 192));
90 
91   /// This should be 0000'0110.
92   /// On LE, this should result in 6.
93   /// On BE, 1100'0000 = 192.
94   constexpr auto B2 = bits<3>{6};
95   static_assert(__builtin_bit_cast(unsigned char, B2) == (LITTLE_END ? 6 : 192));
96 
97   constexpr auto B3 = bits<4>{6};
98   static_assert(__builtin_bit_cast(unsigned char, B3) == (LITTLE_END ? 6 : 96));
99 
100   struct B {
101     std::byte b0 : 4;
102     std::byte b1 : 4;
103   };
104 
105   /// We can properly decompose one byte (8 bit) int two 4-bit bitfields.
106   constexpr struct { unsigned char b0; } T = {0xee};
107   constexpr B MB = __builtin_bit_cast(B, T);
108   static_assert(MB.b0 == 0xe);
109   static_assert(MB.b1 == 0xe);
110 }
111 
112 namespace BitFields {
113   struct BitFields {
114     unsigned a : 2;
115     unsigned b : 30;
116   };
117 
118   constexpr unsigned A = __builtin_bit_cast(unsigned, BitFields{3, 16});
119   static_assert(A == (LITTLE_END ? 67 : 3221225488));
120 
121   struct S {
122     unsigned a : 2;
123     unsigned b : 28;
124     unsigned c : 2;
125   };
126 
127   constexpr S s = __builtin_bit_cast(S, 0xFFFFFFFF);
128   static_assert(s.a == 3);
129   static_assert(s.b == 268435455);
130   static_assert(s.c == 3);
131 
132   void bitfield_indeterminate() {
133     struct BF { unsigned char z : 2; };
134     enum byte : unsigned char {};
135 
136     constexpr BF bf = {0x3};
137     static_assert(bit_cast<bits<2>>(bf).bits == bf.z);
138     static_assert(bit_cast<unsigned char>(bf));
139 
140     static_assert(__builtin_bit_cast(byte, bf)); // expected-error {{not an integral constant expression}} \
141                                                  // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'byte' is invalid}}
142 
143     struct M {
144       // expected-note@+1 {{subobject declared here}}
145       unsigned char mem[sizeof(BF)];
146     };
147     // expected-error@+2 {{initialized by a constant expression}}
148     // expected-note@+1 {{not initialized}}
149     constexpr M m = bit_cast<M>(bf);
150 
151     constexpr auto f = []() constexpr {
152       // bits<24, unsigned int, LITTLE_END ? 0 : 8> B = {0xc0ffee};
153       constexpr struct { unsigned short b1; unsigned char b0;  } B = {0xc0ff, 0xee};
154       return bit_cast<bytes<4>>(B);
155     };
156 
157     static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee);
158     {
159       // expected-error@+2 {{initialized by a constant expression}}
160       // expected-note@+1 {{in call to}}
161       constexpr auto _bad = f()[3];
162     }
163 
164     struct B {
165       unsigned short s0 : 8;
166       unsigned short s1 : 8;
167       std::byte b0 : 4;
168       std::byte b1 : 4;
169       std::byte b2 : 4;
170     };
171     constexpr auto g = [f]() constexpr {
172       return bit_cast<B>(f());
173     };
174     static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe + 0xe);
175     {
176       // expected-error@+2 {{initialized by a constant expression}}
177       // expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}}
178       constexpr auto _bad = g().b2;
179     }
180   }
181 }
182 
183 namespace BoolVectors {
184   typedef bool bool32 __attribute__((ext_vector_type(32)));
185   constexpr auto v = bit_cast<bool32>(0xa1c0ffee);
186 #if LITTLE_END
187   static_assert(!v[0]);
188   static_assert(v[1]);
189   static_assert(v[2]);
190   static_assert(v[3]);
191   static_assert(!v[4]);
192   static_assert(v[5]);
193   static_assert(v[6]);
194   static_assert(v[7]);
195 
196   static_assert(v[8]);
197   static_assert(v[9]);
198   static_assert(v[10]);
199   static_assert(v[11]);
200   static_assert(v[12]);
201   static_assert(v[13]);
202   static_assert(v[14]);
203   static_assert(v[15]);
204 
205   static_assert(!v[16]);
206   static_assert(!v[17]);
207   static_assert(!v[18]);
208   static_assert(!v[19]);
209   static_assert(!v[20]);
210   static_assert(!v[21]);
211   static_assert(v[22]);
212   static_assert(v[23]);
213 
214   static_assert(v[24]);
215   static_assert(!v[25]);
216   static_assert(!v[26]);
217   static_assert(!v[27]);
218   static_assert(!v[28]);
219   static_assert(v[29]);
220   static_assert(!v[30]);
221   static_assert(v[31]);
222 
223 #else
224   static_assert(v[0]);
225   static_assert(!v[1]);
226   static_assert(v[2]);
227   static_assert(!v[3]);
228   static_assert(!v[4]);
229   static_assert(!v[5]);
230   static_assert(!v[6]);
231   static_assert(v[7]);
232 
233   static_assert(v[8]);
234   static_assert(v[9]);
235   static_assert(!v[10]);
236   static_assert(!v[11]);
237   static_assert(!v[12]);
238   static_assert(!v[13]);
239   static_assert(!v[14]);
240   static_assert(!v[15]);
241 
242   static_assert(v[16]);
243   static_assert(v[17]);
244   static_assert(v[18]);
245   static_assert(v[19]);
246   static_assert(v[20]);
247   static_assert(v[21]);
248   static_assert(v[22]);
249   static_assert(v[23]);
250 
251   static_assert(v[24]);
252   static_assert(v[25]);
253   static_assert(v[26]);
254   static_assert(!v[27]);
255   static_assert(v[28]);
256   static_assert(v[29]);
257   static_assert(v[30]);
258   static_assert(!v[31]);
259 #endif
260 
261   struct pad {
262     unsigned short s;
263     unsigned char c;
264   };
265 
266   constexpr auto p = bit_cast<pad>(v);
267   static_assert(p.s == (LITTLE_END ? 0xffee : 0xa1c0));
268   static_assert(p.c == (LITTLE_END ? 0xc0 : 0xff));
269 }
270 
271 namespace TwoShorts {
272   struct B {
273     unsigned short s0 : 8;
274     unsigned short s1 : 8;
275   };
276   constexpr struct { unsigned short b1;} T = {0xc0ff};
277   constexpr B MB = __builtin_bit_cast(B, T);
278 #if LITTLE_END
279     static_assert(MB.s0 == 0xff);
280     static_assert(MB.s1 == 0xc0);
281 #else
282     static_assert(MB.s0 == 0xc0);
283     static_assert(MB.s1 == 0xff);
284 
285 #endif
286 }
287 
288 typedef bool bool8 __attribute__((ext_vector_type(8)));
289 typedef bool bool9 __attribute__((ext_vector_type(9)));
290 typedef bool bool16 __attribute__((ext_vector_type(16)));
291 typedef bool bool17 __attribute__((ext_vector_type(17)));
292 typedef bool bool32 __attribute__((ext_vector_type(32)));
293 typedef bool bool128 __attribute__((ext_vector_type(128)));
294 
295 static_assert(bit_cast<unsigned char>(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), "");
296 constexpr bool8 b8 = __builtin_bit_cast(bool8, 0x55); // both-error {{'__builtin_bit_cast' source type 'int' does not match destination type 'bool8' (vector of 8 'bool' values) (4 vs 1 bytes)}}
297 static_assert(check_round_trip<bool8>(static_cast<unsigned char>(0)), "");
298 static_assert(check_round_trip<bool8>(static_cast<unsigned char>(1)), "");
299 static_assert(check_round_trip<bool8>(static_cast<unsigned char>(0x55)), "");
300 
301 static_assert(bit_cast<unsigned short>(bool16{1,1,1,1,1,0,0,0, 1,1,1,1,0,1,0,0}) == (LITTLE_END ? 0x2F1F : 0xF8F4), "");
302 
303 static_assert(check_round_trip<bool16>(static_cast<short>(0xCAFE)), "");
304 static_assert(check_round_trip<bool32>(static_cast<int>(0xCAFEBABE)), "");
305 
306 #ifdef __SIZEOF_INT128__
307 static_assert(check_round_trip<bool128>(static_cast<__int128_t>(0xCAFEBABE0C05FEFEULL)), "");
308 #endif
309 
310 static_assert(bit_cast<bits<8, uint16_t, 7>, uint16_t>(0xcafe) == (LITTLE_END ? 0x95 : 0x7f));
311 static_assert(bit_cast<bits<4, uint16_t, 10>, uint16_t>(0xcafe) == (LITTLE_END ? 0x2 : 0xf));
312 static_assert(bit_cast<bits<4, uint32_t, 19>, uint32_t>(0xa1cafe) == (LITTLE_END ? 0x4 : 0x5));
313 
314 struct S {
315   // little endian:
316   //    MSB .... .... LSB
317   //        |y|   |x|
318   //
319   // big endian
320   //    MSB .... .... LSB
321   //        |x|   |y|
322 
323   unsigned char x : 4;
324   unsigned char y : 4;
325 
326   constexpr bool operator==(S const &other) const {
327     return x == other.x && y == other.y;
328   }
329 };
330 
331 constexpr S s{0xa, 0xb};
332 static_assert(bit_cast<bits<8>>(s) == (LITTLE_END ? 0xba : 0xab));
333 static_assert(bit_cast<bits<7>>(s) == (LITTLE_END
334                                             ? 0xba & 0x7f
335                                             : (0xab & 0xfe) >> 1));
336 
337 static_assert(round_trip<bits<8>>(s) == s);
338 
339 struct R {
340   unsigned int r : 31;
341   unsigned int : 0;
342   unsigned int : 32;
343   constexpr bool operator==(R const &other) const {
344     return r == other.r;
345   }
346  };
347 using T = bits<31, signed long long>;
348 constexpr R r{0x4ac0ffee};
349 constexpr T t = bit_cast<T>(r);
350 static_assert(t == ((0xFFFFFFFF8 << 28) | 0x4ac0ffee)); // sign extension
351 
352 static_assert(round_trip<T>(r) == r);
353 static_assert(round_trip<R>(t) == t);
354 
355 
356 /// The oversized bitfield is an error on Windows and not just a warning.
357 #if !defined(_WIN32)
358 struct U {
359   // expected-warning@+1 {{exceeds the width of its type}}
360   uint32_t trunc : 33;
361   uint32_t u : 31;
362   constexpr bool operator==(U const &other) const {
363     return trunc == other.trunc && u == other.u;
364   }
365 };
366 struct V {
367   uint64_t notrunc : 32;
368   uint64_t : 1;
369   uint64_t v : 31;
370   constexpr bool operator==(V const &other) const {
371     return notrunc == other.notrunc && v == other.v;
372   }
373 };
374 
375 constexpr U u{static_cast<unsigned int>(~0), 0x4ac0ffee};
376 constexpr V v = bit_cast<V>(u);
377 static_assert(v.v == 0x4ac0ffee);
378 
379 static_assert(round_trip<V>(u) == u);
380 static_assert(round_trip<U>(v) == v);
381 
382 constexpr auto w = bit_cast<bits<12, unsigned long, 33>>(u);
383 static_assert(w == (LITTLE_END
384                     ? 0x4ac0ffee & 0xFFF
385                     : (0x4ac0ffee & (0xFFF << (31 - 12))) >> (31-12)
386                   ));
387 #endif
388 
389 
390 namespace NestedStructures {
391   struct J {
392     struct {
393       uint16_t  k : 12;
394     } K;
395     struct {
396       uint16_t  l : 4;
397     } L;
398   };
399 
400   static_assert(sizeof(J) == 4);
401   constexpr J j = bit_cast<J>(0x8c0ffee5);
402 
403   static_assert(j.K.k == (LITTLE_END ? 0xee5 : 0x8c0));
404   static_assert(j.L.l == 0xf /* yay symmetry */);
405   static_assert(bit_cast<bits<4, uint16_t, 16>>(j) == 0xf);
406   struct N {
407     bits<12, uint16_t> k;
408     uint16_t : 16;
409   };
410   static_assert(bit_cast<N>(j).k == j.K.k);
411 
412   struct M {
413     bits<4, uint16_t, 0> m[2];
414     constexpr bool operator==(const M& rhs) const {
415       return m[0] == rhs.m[0] && m[1] == rhs.m[1];
416     };
417   };
418   #if LITTLE_END == 1
419   constexpr uint16_t want[2] = {0x5, 0xf};
420   #else
421   constexpr uint16_t want[2] = {0x8000, 0xf000};
422   #endif
423 
424   static_assert(bit_cast<M>(j) == bit_cast<M>(want));
425 }
426 
427 namespace Enums {
428   // ensure we're packed into the top 2 bits
429   constexpr int pad = LITTLE_END ? 6 : 0;
430   struct X
431   {
432     char : pad;
433     enum class direction: char { left, right, up, down } direction : 2;
434   };
435 
436   constexpr X x = { X::direction::down };
437   static_assert(bit_cast<bits<2, signed char, pad>>(x) == -1);
438   static_assert(bit_cast<bits<2, unsigned char, pad>>(x) == 3);
439   static_assert(
440     bit_cast<X>((unsigned char)0x40).direction == X::direction::right);
441 }
442 
443 namespace IndeterminateBits {
444   struct S {
445     unsigned a : 13;
446     unsigned   : 17;
447     unsigned b : 2;
448   };
449   constexpr unsigned A = __builtin_bit_cast(unsigned, S{12, 3}); // expected-error {{must be initialized by a constant expression}} \
450                                                                  // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}}
451 
452 
453   /// GCC refuses to compile this as soon as we access the indeterminate bits
454   /// in the static_assert. MSVC accepts it.
455   struct S2 {
456     unsigned char a : 2;
457   };
458   constexpr unsigned char B = __builtin_bit_cast(unsigned char, S2{3});
459   static_assert(B == (LITTLE_END ? 3 : 192));
460 
461 
462 
463   struct S3 {
464     unsigned a : 13;
465     unsigned   : 17;
466     unsigned b : 2;
467   };
468 
469   struct D {
470     unsigned a;
471   };
472   constexpr D s = __builtin_bit_cast(D, S3{12, 3}); // expected-error {{must be initialized by a constant expression}} \
473                                                     // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}}
474 
475 }
476