xref: /llvm-project/clang/test/AST/ByteCode/builtin-bit-cast.cpp (revision 56fd46edb38e4bab7e48c668683ba72709beb64f)
1ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only %s
2ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s
3ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s
4ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s
5ef2a104cSTimm Baeder 
6ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter %s
7ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s
8ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s
9ef2a104cSTimm Baeder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s
10ef2a104cSTimm Baeder 
11ef2a104cSTimm Baeder #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
12ef2a104cSTimm Baeder #  define LITTLE_END 1
13ef2a104cSTimm Baeder #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
14ef2a104cSTimm Baeder #  define LITTLE_END 0
15ef2a104cSTimm Baeder #else
16ef2a104cSTimm Baeder #  error "huh?"
17ef2a104cSTimm Baeder #endif
18ef2a104cSTimm Baeder 
19ef2a104cSTimm Baeder typedef decltype(nullptr) nullptr_t;
20ef2a104cSTimm Baeder typedef __INTPTR_TYPE__ intptr_t;
21ef2a104cSTimm Baeder 
22ef2a104cSTimm Baeder static_assert(sizeof(int) == 4);
23ef2a104cSTimm Baeder static_assert(sizeof(long long) == 8);
24ef2a104cSTimm Baeder 
25ef2a104cSTimm Baeder template <class To, class From>
26ef2a104cSTimm Baeder constexpr To bit_cast(const From &from) {
27ef2a104cSTimm Baeder   static_assert(sizeof(To) == sizeof(From));
28ef2a104cSTimm Baeder   return __builtin_bit_cast(To, from);
29ef2a104cSTimm Baeder }
30ef2a104cSTimm Baeder 
31ef2a104cSTimm Baeder template <class Intermediate, class Init>
32ef2a104cSTimm Baeder constexpr bool check_round_trip(const Init &init) {
33ef2a104cSTimm Baeder   return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
34ef2a104cSTimm Baeder }
35ef2a104cSTimm Baeder 
36ef2a104cSTimm Baeder template <class Intermediate, class Init>
37ef2a104cSTimm Baeder constexpr Init round_trip(const Init &init) {
38ef2a104cSTimm Baeder   return bit_cast<Init>(bit_cast<Intermediate>(init));
39ef2a104cSTimm Baeder }
40ef2a104cSTimm Baeder 
415f84b332STimm Baeder 
425f84b332STimm Baeder namespace Discarding {
435f84b332STimm Baeder   struct S { int a; };
445f84b332STimm Baeder   constexpr int f = (__builtin_bit_cast(int, 2), 0);
455f84b332STimm Baeder   constexpr int f2 = (__builtin_bit_cast(S, 2), 0);
465f84b332STimm Baeder }
475f84b332STimm Baeder 
48ef2a104cSTimm Baeder namespace std {
49ef2a104cSTimm Baeder enum byte : unsigned char {};
50ef2a104cSTimm Baeder } // namespace std
51ef2a104cSTimm Baeder 
52ef2a104cSTimm Baeder using uint8_t = unsigned char;
53ef2a104cSTimm Baeder 
54ef2a104cSTimm Baeder template<int N>
55ef2a104cSTimm Baeder struct bytes {
56ef2a104cSTimm Baeder   using size_t = unsigned int;
57ef2a104cSTimm Baeder   unsigned char d[N];
58ef2a104cSTimm Baeder 
59ef2a104cSTimm Baeder   constexpr unsigned char &operator[](size_t index) {
60ef2a104cSTimm Baeder     if (index < N)
61ef2a104cSTimm Baeder       return d[index];
62ef2a104cSTimm Baeder   }
63ef2a104cSTimm Baeder };
64ef2a104cSTimm Baeder 
65ef2a104cSTimm Baeder 
66ef2a104cSTimm Baeder template <int N, typename T = unsigned char, int Pad = 0>
67ef2a104cSTimm Baeder struct bits {
68ef2a104cSTimm Baeder   T : Pad;
69ef2a104cSTimm Baeder   T bits : N;
70ef2a104cSTimm Baeder 
71ef2a104cSTimm Baeder   constexpr bool operator==(const T& rhs) const {
72ef2a104cSTimm Baeder     return bits == rhs;
73ef2a104cSTimm Baeder   }
74ef2a104cSTimm Baeder };
75ef2a104cSTimm Baeder 
76ef2a104cSTimm Baeder template <int N, typename T, int P>
77ef2a104cSTimm Baeder constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N, T, P>& rhs) {
78ef2a104cSTimm Baeder   return lhs.bits == rhs.bits;
79ef2a104cSTimm Baeder }
80ef2a104cSTimm Baeder 
811e19f0f9STimm Baeder #ifdef __SIZEOF_INT128__
821e19f0f9STimm Baeder static_assert(check_round_trip<__int128_t>((__int128_t)34));
831e19f0f9STimm Baeder static_assert(check_round_trip<__int128_t>((__int128_t)-34));
8488823d08STimm Baeder 
8588823d08STimm Baeder constexpr unsigned char OneBit[] = {
8688823d08STimm Baeder   0x1, 0x0,  0x0,  0x0,
8788823d08STimm Baeder   0x0, 0x0,  0x0,  0x0,
8888823d08STimm Baeder   0x0, 0x0,  0x0,  0x0,
8988823d08STimm Baeder   0x0, 0x0,  0x0,  0x0,
9088823d08STimm Baeder };
9188823d08STimm Baeder constexpr __int128_t One = 1;
9288823d08STimm Baeder constexpr __int128_t Expected = One << 120;
9388823d08STimm Baeder static_assert(__builtin_bit_cast(__int128_t, OneBit) == (LITTLE_END ? 1 : Expected));
9488823d08STimm Baeder 
951e19f0f9STimm Baeder #endif
961e19f0f9STimm Baeder 
975b32c595STimm Baeder static_assert(check_round_trip<double>(17.0));
985b32c595STimm Baeder 
99ef2a104cSTimm Baeder 
100ef2a104cSTimm Baeder namespace simple {
101ef2a104cSTimm Baeder   constexpr int A = __builtin_bit_cast(int, 10);
102ef2a104cSTimm Baeder   static_assert(A == 10);
103ef2a104cSTimm Baeder 
104ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(unsigned, 1.0F) == 1065353216);
105ef2a104cSTimm Baeder 
106ef2a104cSTimm Baeder   struct Bytes {
107ef2a104cSTimm Baeder     char a, b, c, d;
108ef2a104cSTimm Baeder   };
109ef2a104cSTimm Baeder   constexpr unsigned B = __builtin_bit_cast(unsigned, Bytes{10, 12, 13, 14});
110ef2a104cSTimm Baeder   static_assert(B == (LITTLE_END ? 235736074 : 168561934));
111ef2a104cSTimm Baeder 
112ef2a104cSTimm Baeder 
113ef2a104cSTimm Baeder   constexpr unsigned C = __builtin_bit_cast(unsigned, (_BitInt(32))12);
114ef2a104cSTimm Baeder   static_assert(C == 12);
115ef2a104cSTimm Baeder 
116ef2a104cSTimm Baeder   struct BitInts {
117ef2a104cSTimm Baeder     _BitInt(16) a;
118ef2a104cSTimm Baeder     _BitInt(16) b;
119ef2a104cSTimm Baeder   };
120ef2a104cSTimm Baeder   constexpr unsigned D = __builtin_bit_cast(unsigned, BitInts{12, 13});
121ef2a104cSTimm Baeder   static_assert(D == (LITTLE_END ? 851980 : 786445));
122ef2a104cSTimm Baeder 
123ef2a104cSTimm Baeder 
124ef2a104cSTimm Baeder 
125ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(char, true) == 1);
126ef2a104cSTimm Baeder 
127ef2a104cSTimm Baeder   static_assert(check_round_trip<unsigned>((int)-1));
128ef2a104cSTimm Baeder   static_assert(check_round_trip<unsigned>((int)0x12345678));
129ef2a104cSTimm Baeder   static_assert(check_round_trip<unsigned>((int)0x87654321));
130ef2a104cSTimm Baeder   static_assert(check_round_trip<unsigned>((int)0x0C05FEFE));
1315b32c595STimm Baeder   static_assert(round_trip<float>((int)0x0C05FEFE));
132ef2a104cSTimm Baeder 
1332f9cd43aSTimm Baeder   static_assert(__builtin_bit_cast(intptr_t, nullptr) == 0); // both-error {{not an integral constant expression}} \
1342f9cd43aSTimm Baeder                                                              // both-note {{indeterminate value can only initialize an object}}
135b6217f67STimm Baeder 
136b6217f67STimm Baeder   constexpr int test_from_nullptr_pass = (__builtin_bit_cast(unsigned char[sizeof(nullptr)], nullptr), 0);
137b6217f67STimm Baeder   constexpr unsigned char NPData[sizeof(nullptr)] = {1,2,3,4};
138b6217f67STimm Baeder   constexpr nullptr_t NP = __builtin_bit_cast(nullptr_t, NPData);
139b6217f67STimm Baeder   static_assert(NP == nullptr);
140ef2a104cSTimm Baeder }
141ef2a104cSTimm Baeder 
142ef2a104cSTimm Baeder namespace Fail {
143ef2a104cSTimm Baeder   constexpr int a = 1/0; // both-error {{must be initialized by a constant expression}} \
144ef2a104cSTimm Baeder                          // both-note {{division by zero}} \
145ef2a104cSTimm Baeder                          // both-note {{declared here}}
146ef2a104cSTimm Baeder   constexpr int b = __builtin_bit_cast(int, a); // both-error {{must be initialized by a constant expression}} \
147ef2a104cSTimm Baeder                                                 // both-note {{initializer of 'a' is not a constant expression}}
148ef2a104cSTimm Baeder }
149ef2a104cSTimm Baeder 
150476b208eSTimm Baeder namespace ToPtr {
151476b208eSTimm Baeder   struct S {
152476b208eSTimm Baeder     const int *p = nullptr;
153476b208eSTimm Baeder   };
154476b208eSTimm Baeder   struct P {
155476b208eSTimm Baeder     const int *p; // both-note {{invalid type 'const int *' is a member of 'ToPtr::P'}}
156476b208eSTimm Baeder   };
157476b208eSTimm Baeder   constexpr P p = __builtin_bit_cast(P, S{}); // both-error {{must be initialized by a constant expression}} \
158476b208eSTimm Baeder                                               // both-note {{bit_cast to a pointer type is not allowed in a constant expression}}
159476b208eSTimm Baeder }
160476b208eSTimm Baeder 
1611425fa91STimm Baeder namespace Invalid {
1621425fa91STimm Baeder   struct S {
1631425fa91STimm Baeder     int a;
1641425fa91STimm Baeder   };
1651425fa91STimm Baeder   constexpr S s = S{1/0}; // both-error {{must be initialized by a constant expression}} \
1661425fa91STimm Baeder                           // both-note {{division by zero}} \
1671425fa91STimm Baeder                           // both-note {{declared here}}
1681425fa91STimm Baeder   constexpr S s2 = __builtin_bit_cast(S, s); // both-error {{must be initialized by a constant expression}} \
1691425fa91STimm Baeder                                              // both-note {{initializer of 's' is not a constant expression}}
1701425fa91STimm Baeder }
1711425fa91STimm Baeder 
172ef2a104cSTimm Baeder namespace NullPtr {
173ef2a104cSTimm Baeder   constexpr nullptr_t N = __builtin_bit_cast(nullptr_t, (intptr_t)1u);
174ef2a104cSTimm Baeder   static_assert(N == nullptr);
175ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(nullptr_t, (_BitInt(sizeof(void*) * 8))12) == __builtin_bit_cast(nullptr_t, (unsigned _BitInt(sizeof(void*) * 8))0));
176ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(nullptr_t, nullptr) == nullptr);
177ef2a104cSTimm Baeder }
178ef2a104cSTimm Baeder 
179ef2a104cSTimm Baeder namespace bitint {
180ef2a104cSTimm Baeder   constexpr _BitInt(sizeof(int) * 8) BI = ~0;
181ef2a104cSTimm Baeder   constexpr unsigned int I = __builtin_bit_cast(unsigned int, BI);
182ef2a104cSTimm Baeder   static_assert(I == ~0u, "");
183ef2a104cSTimm Baeder 
184ef2a104cSTimm Baeder   constexpr _BitInt(sizeof(int) * 8) IB = __builtin_bit_cast(_BitInt(sizeof(int) * 8), I); // ref-error {{must be initialized by a constant expression}} \
185ef2a104cSTimm Baeder                                                                                            // ref-note {{constexpr bit cast involving type '_BitInt(32)' is not yet supported}} \
186ef2a104cSTimm Baeder                                                                                            // ref-note {{declared here}}
187ef2a104cSTimm Baeder   static_assert(IB == ~0u, ""); // ref-error {{not an integral constant expression}} \
188ef2a104cSTimm Baeder                                 // ref-note {{initializer of 'IB' is not a constant expression}}
189ef2a104cSTimm Baeder }
190ef2a104cSTimm Baeder 
191ef2a104cSTimm Baeder namespace Classes {
192ef2a104cSTimm Baeder   class A {
193ef2a104cSTimm Baeder   public:
194ef2a104cSTimm Baeder     char a[2];
195ef2a104cSTimm Baeder   };
196ef2a104cSTimm Baeder   class B : public A {
197ef2a104cSTimm Baeder   public:
198ef2a104cSTimm Baeder     char b[2];
199ef2a104cSTimm Baeder   };
200ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(int, B{{0,  0},{0,  0}}) == 0);
201ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(int, B{{13, 0},{0,  0}}) == (LITTLE_END ? 13 : 218103808));
202ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(int, B{{13, 7},{12, 20}}) == (LITTLE_END ? 336332557 : 218565652));
203ef2a104cSTimm Baeder 
204ef2a104cSTimm Baeder   class Ref {
205ef2a104cSTimm Baeder   public:
206ef2a104cSTimm Baeder     const int &a;
207ef2a104cSTimm Baeder     constexpr Ref(const int &a) : a(a) {}
208ef2a104cSTimm Baeder   };
209ef2a104cSTimm Baeder   constexpr int I = 12;
210ef2a104cSTimm Baeder 
211ef2a104cSTimm Baeder   typedef __INTPTR_TYPE__ intptr_t;
212ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(intptr_t, Ref{I}) == 0); // both-error {{not an integral constant expression}} \
213ef2a104cSTimm Baeder                                                             // both-note {{bit_cast from a type with a reference member is not allowed in a constant expression}}
214ef2a104cSTimm Baeder 
215ef2a104cSTimm Baeder   class C : public A {
216ef2a104cSTimm Baeder     public:
217ef2a104cSTimm Baeder     constexpr C() : A{1,2} {}
218ef2a104cSTimm Baeder     virtual constexpr int get() {
219ef2a104cSTimm Baeder       return 4;
220ef2a104cSTimm Baeder     }
221ef2a104cSTimm Baeder   };
222ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(_BitInt(sizeof(C) * 8), C()) == 0); // both-error {{source type must be trivially copyable}}
223ef2a104cSTimm Baeder 
224ef2a104cSTimm Baeder 
225ef2a104cSTimm Baeder   class D : virtual A {};
226ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(_BitInt(sizeof(D) * 8), D()) == 0); // both-error {{source type must be trivially copyable}}
227ef2a104cSTimm Baeder 
228ef2a104cSTimm Baeder   class F {
229ef2a104cSTimm Baeder   public:
230ef2a104cSTimm Baeder     char f[2];
231ef2a104cSTimm Baeder   };
232ef2a104cSTimm Baeder 
233ef2a104cSTimm Baeder   class E : public A, public F {
234ef2a104cSTimm Baeder   public:
235ef2a104cSTimm Baeder     constexpr E() : A{1,2}, F{3,4}, e{5,6,7,8} {}
236ef2a104cSTimm Baeder     char e[4];
237ef2a104cSTimm Baeder   };
238ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(long long, E()) == (LITTLE_END ? 578437695752307201 : 72623859790382856));
239ef2a104cSTimm Baeder }
240ef2a104cSTimm Baeder 
241ef2a104cSTimm Baeder struct int_splicer {
242ef2a104cSTimm Baeder   unsigned x;
243ef2a104cSTimm Baeder   unsigned y;
244ef2a104cSTimm Baeder 
245ef2a104cSTimm Baeder   constexpr int_splicer() : x(1), y(2) {}
246ef2a104cSTimm Baeder   constexpr int_splicer(unsigned x, unsigned y) : x(x), y(y) {}
247ef2a104cSTimm Baeder 
248ef2a104cSTimm Baeder   constexpr bool operator==(const int_splicer &other) const {
249ef2a104cSTimm Baeder     return other.x == x && other.y == y;
250ef2a104cSTimm Baeder   }
251ef2a104cSTimm Baeder };
252ef2a104cSTimm Baeder 
253ef2a104cSTimm Baeder constexpr int_splicer splice(0x0C05FEFE, 0xCAFEBABE);
254ef2a104cSTimm Baeder 
2552588b8beSTimm Baeder #if 1
256ef2a104cSTimm Baeder static_assert(bit_cast<unsigned long long>(splice) == (LITTLE_END
257ef2a104cSTimm Baeder                                                            ? 0xCAFEBABE0C05FEFE
258ef2a104cSTimm Baeder                                                            : 0x0C05FEFECAFEBABE));
259ef2a104cSTimm Baeder 
260ef2a104cSTimm Baeder constexpr int_splicer IS = bit_cast<int_splicer>(0xCAFEBABE0C05FEFE);
261ef2a104cSTimm Baeder static_assert(bit_cast<int_splicer>(0xCAFEBABE0C05FEFE).x == (LITTLE_END
262ef2a104cSTimm Baeder                                                                   ? 0x0C05FEFE
263ef2a104cSTimm Baeder                                                                   : 0xCAFEBABE));
264ef2a104cSTimm Baeder 
2652588b8beSTimm Baeder static_assert(check_round_trip<unsigned long long>(splice));
2662588b8beSTimm Baeder static_assert(check_round_trip<long long>(splice));
267ef2a104cSTimm Baeder #endif
268ef2a104cSTimm Baeder 
269ef2a104cSTimm Baeder 
27012ca72baSTimm Bäder namespace Overread {
27112ca72baSTimm Bäder   /// This used to crash becaus we were reading all elements of the
27212ca72baSTimm Bäder   /// source array even though we should only be reading 1.
27312ca72baSTimm Bäder   constexpr int a[] = {2,3, 4, 5};
27412ca72baSTimm Bäder   constexpr int b = __builtin_bit_cast(int, *(a + 1));
27512ca72baSTimm Bäder   static_assert(b == 3);
27612ca72baSTimm Bäder 
27712ca72baSTimm Bäder   struct S {
27812ca72baSTimm Bäder     int a;
27912ca72baSTimm Bäder   };
28012ca72baSTimm Bäder   constexpr S ss[] = {{1},{2}};
28112ca72baSTimm Bäder   constexpr int c = __builtin_bit_cast(int, *(ss + 1));
28212ca72baSTimm Bäder   static_assert(c == 2);
28312ca72baSTimm Bäder }
28412ca72baSTimm Bäder 
285ef2a104cSTimm Baeder 
286ef2a104cSTimm Baeder /// ---------------------------------------------------------------------------
287ef2a104cSTimm Baeder /// From here on, it's things copied from test/SemaCXX/constexpr-builtin-bit.cast.cpp
288ef2a104cSTimm Baeder 
289ef2a104cSTimm Baeder void test_int() {
290ef2a104cSTimm Baeder   static_assert(round_trip<unsigned>((int)-1));
291ef2a104cSTimm Baeder   static_assert(round_trip<unsigned>((int)0x12345678));
292ef2a104cSTimm Baeder   static_assert(round_trip<unsigned>((int)0x87654321));
293ef2a104cSTimm Baeder   static_assert(round_trip<unsigned>((int)0x0C05FEFE));
294ef2a104cSTimm Baeder }
295ef2a104cSTimm Baeder 
296ef2a104cSTimm Baeder void test_array() {
297ef2a104cSTimm Baeder   constexpr unsigned char input[] = {0xCA, 0xFE, 0xBA, 0xBE};
298ef2a104cSTimm Baeder   constexpr unsigned expected = LITTLE_END ? 0xBEBAFECA : 0xCAFEBABE;
299ef2a104cSTimm Baeder   static_assert(bit_cast<unsigned>(input) == expected);
300ef2a104cSTimm Baeder 
301ef2a104cSTimm Baeder   /// Same things but with a composite array.
302ef2a104cSTimm Baeder   struct US { unsigned char I; };
303ef2a104cSTimm Baeder   constexpr US input2[] = {{0xCA}, {0xFE}, {0xBA}, {0xBE}};
304ef2a104cSTimm Baeder   static_assert(bit_cast<unsigned>(input2) == expected);
305ef2a104cSTimm Baeder }
306ef2a104cSTimm Baeder 
307ef2a104cSTimm Baeder void test_record() {
308ef2a104cSTimm Baeder   struct int_splicer {
309ef2a104cSTimm Baeder     unsigned x;
310ef2a104cSTimm Baeder     unsigned y;
311ef2a104cSTimm Baeder 
312ef2a104cSTimm Baeder     constexpr bool operator==(const int_splicer &other) const {
313ef2a104cSTimm Baeder       return other.x == x && other.y == y;
314ef2a104cSTimm Baeder     }
315ef2a104cSTimm Baeder   };
316ef2a104cSTimm Baeder 
317ef2a104cSTimm Baeder   constexpr int_splicer splice{0x0C05FEFE, 0xCAFEBABE};
318ef2a104cSTimm Baeder 
319ef2a104cSTimm Baeder   static_assert(bit_cast<unsigned long long>(splice) == (LITTLE_END
320ef2a104cSTimm Baeder                                                              ? 0xCAFEBABE0C05FEFE
321ef2a104cSTimm Baeder                                                              : 0x0C05FEFECAFEBABE));
322ef2a104cSTimm Baeder 
3232588b8beSTimm Baeder   static_assert(bit_cast<int_splicer>(0xCAFEBABE0C05FEFE).x == (LITTLE_END
3242588b8beSTimm Baeder                                                                     ? 0x0C05FEFE
3252588b8beSTimm Baeder                                                                     : 0xCAFEBABE));
326ef2a104cSTimm Baeder 
3272588b8beSTimm Baeder   static_assert(check_round_trip<unsigned long long>(splice));
3282588b8beSTimm Baeder   static_assert(check_round_trip<long long>(splice));
329ef2a104cSTimm Baeder 
330ef2a104cSTimm Baeder   struct base2 {
331ef2a104cSTimm Baeder   };
332ef2a104cSTimm Baeder 
333ef2a104cSTimm Baeder   struct base3 {
334ef2a104cSTimm Baeder     unsigned z;
335ef2a104cSTimm Baeder   };
336ef2a104cSTimm Baeder 
337ef2a104cSTimm Baeder   struct bases : int_splicer, base2, base3 {
338ef2a104cSTimm Baeder     unsigned doublez;
339ef2a104cSTimm Baeder   };
340ef2a104cSTimm Baeder 
341ef2a104cSTimm Baeder   struct tuple4 {
342ef2a104cSTimm Baeder     unsigned x, y, z, doublez;
343ef2a104cSTimm Baeder 
344ef2a104cSTimm Baeder     bool operator==(tuple4 const &other) const = default;
345ef2a104cSTimm Baeder     constexpr bool operator==(bases const &other) const {
346ef2a104cSTimm Baeder       return x == other.x && y == other.y &&
347ef2a104cSTimm Baeder              z == other.z && doublez == other.doublez;
348ef2a104cSTimm Baeder     }
349ef2a104cSTimm Baeder   };
3502588b8beSTimm Baeder   constexpr bases b = {{1, 2}, {}, {3}, 4};
3512588b8beSTimm Baeder   constexpr tuple4 t4 = bit_cast<tuple4>(b);
3522588b8beSTimm Baeder   static_assert(t4 == tuple4{1, 2, 3, 4});
3532588b8beSTimm Baeder   static_assert(check_round_trip<tuple4>(b));
354ef2a104cSTimm Baeder 
3557aec6dc4STimm Baeder   constexpr auto b2 = bit_cast<bases>(t4);
3567aec6dc4STimm Baeder   static_assert(t4 == b2);
357ef2a104cSTimm Baeder }
358ef2a104cSTimm Baeder 
359ef2a104cSTimm Baeder void test_partially_initialized() {
360ef2a104cSTimm Baeder   struct pad {
361ef2a104cSTimm Baeder     signed char x;
362ef2a104cSTimm Baeder     int y;
363ef2a104cSTimm Baeder   };
364ef2a104cSTimm Baeder 
365ef2a104cSTimm Baeder   struct no_pad {
366ef2a104cSTimm Baeder     signed char x;
367ef2a104cSTimm Baeder     signed char p1, p2, p3;
368ef2a104cSTimm Baeder     int y;
369ef2a104cSTimm Baeder   };
370ef2a104cSTimm Baeder 
371ef2a104cSTimm Baeder   static_assert(sizeof(pad) == sizeof(no_pad));
372ef2a104cSTimm Baeder 
373ef2a104cSTimm Baeder #if 0
374ef2a104cSTimm Baeder   constexpr pad pir{4, 4};
375ef2a104cSTimm Baeder   constexpr int piw = bit_cast<no_pad>(pir).x; // both-error {{constexpr variable 'piw' must be initialized by a constant expression}} \
376ef2a104cSTimm Baeder                                                // both-note {{in call to 'bit_cast<no_pad, pad>(pir)'}}
377ef2a104cSTimm Baeder 
378ef2a104cSTimm Baeder 
379ef2a104cSTimm Baeder   constexpr no_pad bad = bit_cast<no_pad>(pir); // both-error {{constexpr variable 'bad' must be initialized by a constant expression}} \
380ef2a104cSTimm Baeder                                                 // both-note {{in call to 'bit_cast<no_pad, pad>(pir)'}}
381ef2a104cSTimm Baeder   // constexpr pad fine = bit_cast<pad>(no_pad{1, 2, 3, 4, 5});
382ef2a104cSTimm Baeder   // static_assert(fine.x == 1 && fine.y == 5);
383ef2a104cSTimm Baeder #endif
384ef2a104cSTimm Baeder }
385ef2a104cSTimm Baeder 
386ef2a104cSTimm Baeder 
387ef2a104cSTimm Baeder void bad_types() {
388ef2a104cSTimm Baeder   union X {
389ef2a104cSTimm Baeder     int x;
390ef2a104cSTimm Baeder   };
391ef2a104cSTimm Baeder   static_assert(__builtin_bit_cast(int, X{0}) == 0); // both-error {{not an integral constant expression}} \
392ef2a104cSTimm Baeder                                                      // both-note {{bit_cast from a union type is not allowed in a constant expression}}
393ef2a104cSTimm Baeder 
394ef2a104cSTimm Baeder   struct G {
395ef2a104cSTimm Baeder     int g;
396ef2a104cSTimm Baeder   };
3972588b8beSTimm Baeder   // both-error@+2 {{constexpr variable 'g' must be initialized by a constant expression}}
3982588b8beSTimm Baeder   // both-note@+1 {{bit_cast from a union type is not allowed in a constant expression}}
399ef2a104cSTimm Baeder   constexpr G g = __builtin_bit_cast(G, X{0});
4002588b8beSTimm Baeder   // both-error@+2 {{constexpr variable 'x' must be initialized by a constant expression}}
4012588b8beSTimm Baeder   // both-note@+1 {{bit_cast to a union type is not allowed in a constant expression}}
402ef2a104cSTimm Baeder   constexpr X x = __builtin_bit_cast(X, G{0});
4032f9cd43aSTimm Baeder 
404ef2a104cSTimm Baeder   struct has_pointer {
4052f9cd43aSTimm Baeder     int *ptr; // both-note 2{{invalid type 'int *' is a member of 'has_pointer'}}
406ef2a104cSTimm Baeder   };
407ef2a104cSTimm Baeder 
408ef2a104cSTimm Baeder   constexpr intptr_t ptr = __builtin_bit_cast(intptr_t, has_pointer{0}); // both-error {{constexpr variable 'ptr' must be initialized by a constant expression}} \
409ef2a104cSTimm Baeder                                                                          // both-note {{bit_cast from a pointer type is not allowed in a constant expression}}
410ef2a104cSTimm Baeder 
4112f9cd43aSTimm Baeder   // both-error@+2 {{constexpr variable 'hptr' must be initialized by a constant expression}}
4122f9cd43aSTimm Baeder   // both-note@+1 {{bit_cast to a pointer type is not allowed in a constant expression}}
4132f9cd43aSTimm Baeder   constexpr has_pointer hptr =  __builtin_bit_cast(has_pointer, (intptr_t)0);
414ef2a104cSTimm Baeder }
415ef2a104cSTimm Baeder 
416ef2a104cSTimm Baeder void test_array_fill() {
417ef2a104cSTimm Baeder   constexpr unsigned char a[4] = {1, 2};
418ef2a104cSTimm Baeder   constexpr unsigned int i = bit_cast<unsigned int>(a);
419ef2a104cSTimm Baeder   static_assert(i == (LITTLE_END ? 0x00000201 : 0x01020000));
420ef2a104cSTimm Baeder }
421ef2a104cSTimm Baeder 
422ef2a104cSTimm Baeder struct vol_mem {
423ef2a104cSTimm Baeder   volatile int x;
424ef2a104cSTimm Baeder };
425ef2a104cSTimm Baeder 
426ef2a104cSTimm Baeder // both-error@+2 {{constexpr variable 'run_vol_mem' must be initialized by a constant expression}}
427ef2a104cSTimm Baeder // both-note@+1 {{non-literal type 'vol_mem' cannot be used in a constant expression}}
428ef2a104cSTimm Baeder constexpr int run_vol_mem = __builtin_bit_cast(int, vol_mem{43});
429ef2a104cSTimm Baeder 
430ef2a104cSTimm Baeder struct mem_ptr {
431ef2a104cSTimm Baeder   int vol_mem::*x; // both-note{{invalid type 'int vol_mem::*' is a member of 'mem_ptr'}}
432ef2a104cSTimm Baeder };
433ef2a104cSTimm Baeder 
434ef2a104cSTimm Baeder // both-error@+2 {{constexpr variable 'run_mem_ptr' must be initialized by a constant expression}}
435ef2a104cSTimm Baeder // both-note@+1 {{bit_cast from a member pointer type is not allowed in a constant expression}}
436ef2a104cSTimm Baeder constexpr _BitInt(sizeof(mem_ptr) * 8) run_mem_ptr = __builtin_bit_cast(_BitInt(sizeof(mem_ptr) * 8), mem_ptr{nullptr});
437ef2a104cSTimm Baeder 
438ef2a104cSTimm Baeder constexpr int global_int = 0;
439ef2a104cSTimm Baeder 
440ef2a104cSTimm Baeder struct ref_mem {
441ef2a104cSTimm Baeder   const int &rm;
442ef2a104cSTimm Baeder };
443ef2a104cSTimm Baeder // both-error@+2 {{constexpr variable 'run_ref_mem' must be initialized by a constant expression}}
444ef2a104cSTimm Baeder // both-note@+1 {{bit_cast from a type with a reference member is not allowed in a constant expression}}
445ef2a104cSTimm Baeder constexpr intptr_t run_ref_mem = __builtin_bit_cast(intptr_t, ref_mem{global_int});
4462f13fbfcSTimm Baeder 
4471b3da362STimm Baeder namespace test_vector {
4482f13fbfcSTimm Baeder 
4491b3da362STimm Baeder typedef unsigned uint2 __attribute__((vector_size(2 * sizeof(unsigned))));
4501b3da362STimm Baeder typedef char byte8 __attribute__((vector_size(sizeof(unsigned long long))));
4512f13fbfcSTimm Baeder 
4521b3da362STimm Baeder constexpr uint2 test_vector = { 0x0C05FEFE, 0xCAFEBABE };
4531b3da362STimm Baeder 
4541b3da362STimm Baeder static_assert(bit_cast<unsigned long long>(test_vector) == (LITTLE_END
4551b3da362STimm Baeder                                                                 ? 0xCAFEBABE0C05FEFE
4561b3da362STimm Baeder                                                                 : 0x0C05FEFECAFEBABE), "");
4571b3da362STimm Baeder static_assert(check_round_trip<uint2>(0xCAFEBABE0C05FEFEULL), "");
4581b3da362STimm Baeder static_assert(check_round_trip<byte8>(0xCAFEBABE0C05FEFEULL), "");
4591b3da362STimm Baeder 
4601b3da362STimm Baeder #if 0
4611b3da362STimm Baeder // expected-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
4621b3da362STimm Baeder // 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}}
4631b3da362STimm Baeder constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
4641b3da362STimm Baeder // expected-error@+2 {{constexpr variable 'bad_short_to_bool9' must be initialized by a constant expression}}
4651b3da362STimm Baeder // 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}}
4661b3da362STimm Baeder constexpr bool9 bad_short_to_bool9 = __builtin_bit_cast(bool9, static_cast<unsigned short>(0));
4671b3da362STimm Baeder // expected-error@+2 {{constexpr variable 'bad_int_to_bool17' must be initialized by a constant expression}}
4681b3da362STimm Baeder // 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}}
4691b3da362STimm Baeder constexpr bool17 bad_int_to_bool17 = __builtin_bit_cast(bool17, 0x0001CAFEU);
4701b3da362STimm Baeder #endif
4711b3da362STimm Baeder }
4722f13fbfcSTimm Baeder 
4732f13fbfcSTimm Baeder namespace test_complex {
4742f13fbfcSTimm Baeder   constexpr _Complex unsigned test_int_complex = { 0x0C05FEFE, 0xCAFEBABE };
4752f13fbfcSTimm Baeder   static_assert(round_trip<_Complex unsigned>(0xCAFEBABE0C05FEFEULL), "");
4762f13fbfcSTimm Baeder   static_assert(bit_cast<unsigned long long>(test_int_complex) == (LITTLE_END
4772f13fbfcSTimm Baeder                                                                    ? 0xCAFEBABE0C05FEFE
4782f13fbfcSTimm Baeder                                                                    : 0x0C05FEFECAFEBABE), "");
4792f13fbfcSTimm Baeder   static_assert(sizeof(double) == 2 * sizeof(float));
4802f13fbfcSTimm Baeder   struct TwoFloats { float A; float B; };
4812f13fbfcSTimm Baeder   constexpr _Complex float test_float_complex = {1.0f, 2.0f};
4822f13fbfcSTimm Baeder   constexpr TwoFloats TF = __builtin_bit_cast(TwoFloats, test_float_complex);
4832f13fbfcSTimm Baeder   static_assert(TF.A == 1.0f && TF.B == 2.0f);
4842f13fbfcSTimm Baeder 
4852f13fbfcSTimm Baeder   constexpr double D = __builtin_bit_cast(double, test_float_complex);
486b63b0101SOleksandr T.   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)}}
4872f13fbfcSTimm Baeder }
48812ca72baSTimm Bäder 
48912ca72baSTimm Bäder 
49012ca72baSTimm Bäder namespace OversizedBitField {
49112ca72baSTimm Bäder #if defined(_WIN32)
49212ca72baSTimm Bäder   /// This is an error (not just a warning) on Windows and the field ends up with a size of 1 instead of 4.
49312ca72baSTimm Bäder #else
49412ca72baSTimm Bäder   typedef unsigned __INT16_TYPE__ uint16_t;
49512ca72baSTimm Bäder   typedef unsigned __INT32_TYPE__ uint32_t;
49612ca72baSTimm Bäder   struct S {
49712ca72baSTimm Bäder     uint16_t a : 20; // both-warning {{exceeds the width of its type}}
49812ca72baSTimm Bäder   };
49912ca72baSTimm Bäder 
50012ca72baSTimm Bäder   static_assert(sizeof(S) == 4);
50112ca72baSTimm Bäder   static_assert(__builtin_bit_cast(S, (uint32_t)32).a == (LITTLE_END ? 32 : 0)); // ref-error {{not an integral constant expression}} \
50212ca72baSTimm Bäder                                                                                  // ref-note {{constexpr bit_cast involving bit-field is not yet supported}}
50312ca72baSTimm Bäder #endif
50412ca72baSTimm Bäder }
5050fb06172STimm Baeder 
5060fb06172STimm Baeder typedef bool bool9 __attribute__((ext_vector_type(9)));
5070fb06172STimm Baeder // both-error@+2 {{constexpr variable 'bad_bool9_to_short' must be initialized by a constant expression}}
5080fb06172STimm Baeder // 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}}
5090fb06172STimm Baeder constexpr unsigned short bad_bool9_to_short = __builtin_bit_cast(unsigned short, bool9{1,1,0,1,0,1,0,1,0});
510*56fd46edSTimm Baeder 
511*56fd46edSTimm Baeder // both-warning@+2 {{returning reference to local temporary object}}
512*56fd46edSTimm Baeder // both-note@+1 {{temporary created here}}
513*56fd46edSTimm Baeder constexpr const intptr_t &returns_local() { return 0L; }
514*56fd46edSTimm Baeder 
515*56fd46edSTimm Baeder // both-error@+2 {{constexpr variable 'test_nullptr_bad' must be initialized by a constant expression}}
516*56fd46edSTimm Baeder // both-note@+1 {{read of temporary whose lifetime has ended}}
517*56fd46edSTimm Baeder constexpr nullptr_t test_nullptr_bad = __builtin_bit_cast(nullptr_t, returns_local());
518