117dfdd3aSTimm Bäder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-linux-gnu -fexperimental-new-constant-interpreter %s 212ca72baSTimm Bäder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple armv8 -fexperimental-new-constant-interpreter %s 312ca72baSTimm Bäder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu -fexperimental-new-constant-interpreter %s 412ca72baSTimm Bäder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64le-unknown-unknown -mabi=ieeelongdouble %s 512ca72baSTimm Bäder // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -fexperimental-new-constant-interpreter -triple powerpc64-unknown-unknown -mabi=ieeelongdouble %s 612ca72baSTimm Bäder 712ca72baSTimm Bäder #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ 812ca72baSTimm Bäder # define LITTLE_END 1 912ca72baSTimm Bäder #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 1012ca72baSTimm Bäder # define LITTLE_END 0 1112ca72baSTimm Bäder #else 1212ca72baSTimm Bäder # error "huh?" 1312ca72baSTimm Bäder #endif 1412ca72baSTimm Bäder 1512ca72baSTimm Bäder typedef decltype(nullptr) nullptr_t; 1612ca72baSTimm Bäder typedef __INTPTR_TYPE__ intptr_t; 1712ca72baSTimm Bäder typedef unsigned __INT16_TYPE__ uint16_t; 1812ca72baSTimm Bäder typedef unsigned __INT32_TYPE__ uint32_t; 1912ca72baSTimm Bäder typedef unsigned __INT64_TYPE__ uint64_t; 2012ca72baSTimm Bäder 2112ca72baSTimm Bäder static_assert(sizeof(int) == 4); 2212ca72baSTimm Bäder static_assert(sizeof(long long) == 8); 2312ca72baSTimm Bäder 2412ca72baSTimm Bäder template <class To, class From> 2512ca72baSTimm Bäder constexpr To bit_cast(const From &from) { 2612ca72baSTimm Bäder static_assert(sizeof(To) == sizeof(From)); 2712ca72baSTimm Bäder return __builtin_bit_cast(To, from); 2812ca72baSTimm Bäder } 2912ca72baSTimm Bäder 3012ca72baSTimm Bäder template <class Intermediate, class Init> 3112ca72baSTimm Bäder constexpr bool check_round_trip(const Init &init) { 3212ca72baSTimm Bäder return bit_cast<Init>(bit_cast<Intermediate>(init)) == init; 3312ca72baSTimm Bäder } 3412ca72baSTimm Bäder 3512ca72baSTimm Bäder template <class Intermediate, class Init> 3612ca72baSTimm Bäder constexpr Init round_trip(const Init &init) { 3712ca72baSTimm Bäder return bit_cast<Init>(bit_cast<Intermediate>(init)); 3812ca72baSTimm Bäder } 3912ca72baSTimm Bäder 4012ca72baSTimm Bäder namespace std { 4112ca72baSTimm Bäder enum byte : unsigned char {}; 4212ca72baSTimm Bäder } // namespace std 4312ca72baSTimm Bäder 4412ca72baSTimm Bäder template <int N, typename T = unsigned char, int Pad = 0> 4512ca72baSTimm Bäder struct bits { 4612ca72baSTimm Bäder T : Pad; 4712ca72baSTimm Bäder T bits : N; 4812ca72baSTimm Bäder 4912ca72baSTimm Bäder constexpr bool operator==(const T& rhs) const { 5012ca72baSTimm Bäder return bits == rhs; 5112ca72baSTimm Bäder } 5212ca72baSTimm Bäder }; 5312ca72baSTimm Bäder 5412ca72baSTimm Bäder template <int N, typename T, int P> 5512ca72baSTimm Bäder constexpr bool operator==(const struct bits<N, T, P>& lhs, const struct bits<N, T, P>& rhs) { 5612ca72baSTimm Bäder return lhs.bits == rhs.bits; 5712ca72baSTimm Bäder } 5812ca72baSTimm Bäder 5912ca72baSTimm Bäder template<int N> 6012ca72baSTimm Bäder struct bytes { 6112ca72baSTimm Bäder using size_t = unsigned int; 6212ca72baSTimm Bäder unsigned char d[N]; 6312ca72baSTimm Bäder 6412ca72baSTimm Bäder constexpr unsigned char operator[](size_t index) { 6512ca72baSTimm Bäder if (index < N) 66*b4150ed1STimm Baeder return d[index]; // expected-note {{read of uninitialized object}} 6712ca72baSTimm Bäder return -1; 6812ca72baSTimm Bäder } 6912ca72baSTimm Bäder }; 7012ca72baSTimm Bäder 7112ca72baSTimm Bäder namespace Sanity { 7212ca72baSTimm Bäder /// This is just one byte, and we extract 2 bits from it. 7312ca72baSTimm Bäder /// 7412ca72baSTimm Bäder /// 3 is 0000'0011. 7512ca72baSTimm Bäder /// For both LE and BE, the buffer will contain exactly that 7612ca72baSTimm Bäder /// byte, unaltered and not reordered in any way. It contains all 8 bits. 7712ca72baSTimm Bäder static_assert(__builtin_bit_cast(bits<2>, (unsigned char)3) == (LITTLE_END ? 3 : 0)); 7812ca72baSTimm Bäder 7912ca72baSTimm Bäder /// Similarly, we have one full byte of data, with the two most-significant 8012ca72baSTimm Bäder /// bits set: 8112ca72baSTimm Bäder /// 192 is 1100'0000 8212ca72baSTimm Bäder static_assert(__builtin_bit_cast(bits<2>, (unsigned char)192) == (LITTLE_END ? 0 : 3)); 8312ca72baSTimm Bäder 8412ca72baSTimm Bäder 8512ca72baSTimm Bäder /// Here we are instead bitcasting two 1-bits into a destination of 8 bits. 8612ca72baSTimm Bäder /// On LE, we should pick the two least-significant bits. On BE, the opposite. 8712ca72baSTimm Bäder /// NOTE: Can't verify this with gcc. 8812ca72baSTimm Bäder constexpr auto B1 = bits<2>{3}; 8912ca72baSTimm Bäder static_assert(__builtin_bit_cast(unsigned char, B1) == (LITTLE_END ? 3 : 192)); 9012ca72baSTimm Bäder 9112ca72baSTimm Bäder /// This should be 0000'0110. 9212ca72baSTimm Bäder /// On LE, this should result in 6. 9312ca72baSTimm Bäder /// On BE, 1100'0000 = 192. 9412ca72baSTimm Bäder constexpr auto B2 = bits<3>{6}; 9512ca72baSTimm Bäder static_assert(__builtin_bit_cast(unsigned char, B2) == (LITTLE_END ? 6 : 192)); 9612ca72baSTimm Bäder 9712ca72baSTimm Bäder constexpr auto B3 = bits<4>{6}; 9812ca72baSTimm Bäder static_assert(__builtin_bit_cast(unsigned char, B3) == (LITTLE_END ? 6 : 96)); 9912ca72baSTimm Bäder 10012ca72baSTimm Bäder struct B { 10112ca72baSTimm Bäder std::byte b0 : 4; 10212ca72baSTimm Bäder std::byte b1 : 4; 10312ca72baSTimm Bäder }; 10412ca72baSTimm Bäder 10512ca72baSTimm Bäder /// We can properly decompose one byte (8 bit) int two 4-bit bitfields. 10612ca72baSTimm Bäder constexpr struct { unsigned char b0; } T = {0xee}; 10712ca72baSTimm Bäder constexpr B MB = __builtin_bit_cast(B, T); 10812ca72baSTimm Bäder static_assert(MB.b0 == 0xe); 10912ca72baSTimm Bäder static_assert(MB.b1 == 0xe); 11012ca72baSTimm Bäder } 11112ca72baSTimm Bäder 11212ca72baSTimm Bäder namespace BitFields { 11312ca72baSTimm Bäder struct BitFields { 11412ca72baSTimm Bäder unsigned a : 2; 11512ca72baSTimm Bäder unsigned b : 30; 11612ca72baSTimm Bäder }; 11712ca72baSTimm Bäder 11812ca72baSTimm Bäder constexpr unsigned A = __builtin_bit_cast(unsigned, BitFields{3, 16}); 11912ca72baSTimm Bäder static_assert(A == (LITTLE_END ? 67 : 3221225488)); 12012ca72baSTimm Bäder 12112ca72baSTimm Bäder struct S { 12212ca72baSTimm Bäder unsigned a : 2; 12312ca72baSTimm Bäder unsigned b : 28; 12412ca72baSTimm Bäder unsigned c : 2; 12512ca72baSTimm Bäder }; 12612ca72baSTimm Bäder 12712ca72baSTimm Bäder constexpr S s = __builtin_bit_cast(S, 0xFFFFFFFF); 12812ca72baSTimm Bäder static_assert(s.a == 3); 12912ca72baSTimm Bäder static_assert(s.b == 268435455); 13012ca72baSTimm Bäder static_assert(s.c == 3); 13112ca72baSTimm Bäder 13212ca72baSTimm Bäder void bitfield_indeterminate() { 13312ca72baSTimm Bäder struct BF { unsigned char z : 2; }; 13412ca72baSTimm Bäder enum byte : unsigned char {}; 13512ca72baSTimm Bäder 13612ca72baSTimm Bäder constexpr BF bf = {0x3}; 13712ca72baSTimm Bäder static_assert(bit_cast<bits<2>>(bf).bits == bf.z); 13812ca72baSTimm Bäder static_assert(bit_cast<unsigned char>(bf)); 13912ca72baSTimm Bäder 1402f9cd43aSTimm Baeder static_assert(__builtin_bit_cast(byte, bf)); // expected-error {{not an integral constant expression}} \ 1412f9cd43aSTimm Baeder // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'byte' is invalid}} 14212ca72baSTimm Bäder 14312ca72baSTimm Bäder struct M { 144*b4150ed1STimm Baeder // expected-note@+1 {{subobject declared here}} 14512ca72baSTimm Bäder unsigned char mem[sizeof(BF)]; 14612ca72baSTimm Bäder }; 147*b4150ed1STimm Baeder // expected-error@+2 {{initialized by a constant expression}} 148*b4150ed1STimm Baeder // expected-note@+1 {{not initialized}} 14912ca72baSTimm Bäder constexpr M m = bit_cast<M>(bf); 15012ca72baSTimm Bäder 15112ca72baSTimm Bäder constexpr auto f = []() constexpr { 15212ca72baSTimm Bäder // bits<24, unsigned int, LITTLE_END ? 0 : 8> B = {0xc0ffee}; 15312ca72baSTimm Bäder constexpr struct { unsigned short b1; unsigned char b0; } B = {0xc0ff, 0xee}; 15412ca72baSTimm Bäder return bit_cast<bytes<4>>(B); 15512ca72baSTimm Bäder }; 15612ca72baSTimm Bäder 15712ca72baSTimm Bäder static_assert(f()[0] + f()[1] + f()[2] == 0xc0 + 0xff + 0xee); 15812ca72baSTimm Bäder { 159*b4150ed1STimm Baeder // expected-error@+2 {{initialized by a constant expression}} 160*b4150ed1STimm Baeder // expected-note@+1 {{in call to}} 16112ca72baSTimm Bäder constexpr auto _bad = f()[3]; 16212ca72baSTimm Bäder } 16312ca72baSTimm Bäder 16412ca72baSTimm Bäder struct B { 16512ca72baSTimm Bäder unsigned short s0 : 8; 16612ca72baSTimm Bäder unsigned short s1 : 8; 16712ca72baSTimm Bäder std::byte b0 : 4; 16812ca72baSTimm Bäder std::byte b1 : 4; 16912ca72baSTimm Bäder std::byte b2 : 4; 17012ca72baSTimm Bäder }; 17112ca72baSTimm Bäder constexpr auto g = [f]() constexpr { 17212ca72baSTimm Bäder return bit_cast<B>(f()); 17312ca72baSTimm Bäder }; 17412ca72baSTimm Bäder static_assert(g().s0 + g().s1 + g().b0 + g().b1 == 0xc0 + 0xff + 0xe + 0xe); 17512ca72baSTimm Bäder { 176*b4150ed1STimm Baeder // expected-error@+2 {{initialized by a constant expression}} 177*b4150ed1STimm Baeder // expected-note@+1 {{read of uninitialized object is not allowed in a constant expression}} 17812ca72baSTimm Bäder constexpr auto _bad = g().b2; 17912ca72baSTimm Bäder } 18012ca72baSTimm Bäder } 18112ca72baSTimm Bäder } 18212ca72baSTimm Bäder 18312ca72baSTimm Bäder namespace BoolVectors { 18412ca72baSTimm Bäder typedef bool bool32 __attribute__((ext_vector_type(32))); 18512ca72baSTimm Bäder constexpr auto v = bit_cast<bool32>(0xa1c0ffee); 18612ca72baSTimm Bäder #if LITTLE_END 18712ca72baSTimm Bäder static_assert(!v[0]); 18812ca72baSTimm Bäder static_assert(v[1]); 18912ca72baSTimm Bäder static_assert(v[2]); 19012ca72baSTimm Bäder static_assert(v[3]); 19112ca72baSTimm Bäder static_assert(!v[4]); 19212ca72baSTimm Bäder static_assert(v[5]); 19312ca72baSTimm Bäder static_assert(v[6]); 19412ca72baSTimm Bäder static_assert(v[7]); 19512ca72baSTimm Bäder 19612ca72baSTimm Bäder static_assert(v[8]); 19712ca72baSTimm Bäder static_assert(v[9]); 19812ca72baSTimm Bäder static_assert(v[10]); 19912ca72baSTimm Bäder static_assert(v[11]); 20012ca72baSTimm Bäder static_assert(v[12]); 20112ca72baSTimm Bäder static_assert(v[13]); 20212ca72baSTimm Bäder static_assert(v[14]); 20312ca72baSTimm Bäder static_assert(v[15]); 20412ca72baSTimm Bäder 20512ca72baSTimm Bäder static_assert(!v[16]); 20612ca72baSTimm Bäder static_assert(!v[17]); 20712ca72baSTimm Bäder static_assert(!v[18]); 20812ca72baSTimm Bäder static_assert(!v[19]); 20912ca72baSTimm Bäder static_assert(!v[20]); 21012ca72baSTimm Bäder static_assert(!v[21]); 21112ca72baSTimm Bäder static_assert(v[22]); 21212ca72baSTimm Bäder static_assert(v[23]); 21312ca72baSTimm Bäder 21412ca72baSTimm Bäder static_assert(v[24]); 21512ca72baSTimm Bäder static_assert(!v[25]); 21612ca72baSTimm Bäder static_assert(!v[26]); 21712ca72baSTimm Bäder static_assert(!v[27]); 21812ca72baSTimm Bäder static_assert(!v[28]); 21912ca72baSTimm Bäder static_assert(v[29]); 22012ca72baSTimm Bäder static_assert(!v[30]); 22112ca72baSTimm Bäder static_assert(v[31]); 22212ca72baSTimm Bäder 22312ca72baSTimm Bäder #else 22412ca72baSTimm Bäder static_assert(v[0]); 22512ca72baSTimm Bäder static_assert(!v[1]); 22612ca72baSTimm Bäder static_assert(v[2]); 22712ca72baSTimm Bäder static_assert(!v[3]); 22812ca72baSTimm Bäder static_assert(!v[4]); 22912ca72baSTimm Bäder static_assert(!v[5]); 23012ca72baSTimm Bäder static_assert(!v[6]); 23112ca72baSTimm Bäder static_assert(v[7]); 23212ca72baSTimm Bäder 23312ca72baSTimm Bäder static_assert(v[8]); 23412ca72baSTimm Bäder static_assert(v[9]); 23512ca72baSTimm Bäder static_assert(!v[10]); 23612ca72baSTimm Bäder static_assert(!v[11]); 23712ca72baSTimm Bäder static_assert(!v[12]); 23812ca72baSTimm Bäder static_assert(!v[13]); 23912ca72baSTimm Bäder static_assert(!v[14]); 24012ca72baSTimm Bäder static_assert(!v[15]); 24112ca72baSTimm Bäder 24212ca72baSTimm Bäder static_assert(v[16]); 24312ca72baSTimm Bäder static_assert(v[17]); 24412ca72baSTimm Bäder static_assert(v[18]); 24512ca72baSTimm Bäder static_assert(v[19]); 24612ca72baSTimm Bäder static_assert(v[20]); 24712ca72baSTimm Bäder static_assert(v[21]); 24812ca72baSTimm Bäder static_assert(v[22]); 24912ca72baSTimm Bäder static_assert(v[23]); 25012ca72baSTimm Bäder 25112ca72baSTimm Bäder static_assert(v[24]); 25212ca72baSTimm Bäder static_assert(v[25]); 25312ca72baSTimm Bäder static_assert(v[26]); 25412ca72baSTimm Bäder static_assert(!v[27]); 25512ca72baSTimm Bäder static_assert(v[28]); 25612ca72baSTimm Bäder static_assert(v[29]); 25712ca72baSTimm Bäder static_assert(v[30]); 25812ca72baSTimm Bäder static_assert(!v[31]); 25912ca72baSTimm Bäder #endif 26012ca72baSTimm Bäder 26112ca72baSTimm Bäder struct pad { 26212ca72baSTimm Bäder unsigned short s; 26312ca72baSTimm Bäder unsigned char c; 26412ca72baSTimm Bäder }; 26512ca72baSTimm Bäder 26612ca72baSTimm Bäder constexpr auto p = bit_cast<pad>(v); 26712ca72baSTimm Bäder static_assert(p.s == (LITTLE_END ? 0xffee : 0xa1c0)); 26812ca72baSTimm Bäder static_assert(p.c == (LITTLE_END ? 0xc0 : 0xff)); 26912ca72baSTimm Bäder } 27012ca72baSTimm Bäder 27112ca72baSTimm Bäder namespace TwoShorts { 27212ca72baSTimm Bäder struct B { 27312ca72baSTimm Bäder unsigned short s0 : 8; 27412ca72baSTimm Bäder unsigned short s1 : 8; 27512ca72baSTimm Bäder }; 27612ca72baSTimm Bäder constexpr struct { unsigned short b1;} T = {0xc0ff}; 27712ca72baSTimm Bäder constexpr B MB = __builtin_bit_cast(B, T); 27812ca72baSTimm Bäder #if LITTLE_END 27912ca72baSTimm Bäder static_assert(MB.s0 == 0xff); 28012ca72baSTimm Bäder static_assert(MB.s1 == 0xc0); 28112ca72baSTimm Bäder #else 28212ca72baSTimm Bäder static_assert(MB.s0 == 0xc0); 28312ca72baSTimm Bäder static_assert(MB.s1 == 0xff); 28412ca72baSTimm Bäder 28512ca72baSTimm Bäder #endif 28612ca72baSTimm Bäder } 28712ca72baSTimm Bäder 28812ca72baSTimm Bäder typedef bool bool8 __attribute__((ext_vector_type(8))); 28912ca72baSTimm Bäder typedef bool bool9 __attribute__((ext_vector_type(9))); 29012ca72baSTimm Bäder typedef bool bool16 __attribute__((ext_vector_type(16))); 29112ca72baSTimm Bäder typedef bool bool17 __attribute__((ext_vector_type(17))); 29212ca72baSTimm Bäder typedef bool bool32 __attribute__((ext_vector_type(32))); 29312ca72baSTimm Bäder typedef bool bool128 __attribute__((ext_vector_type(128))); 29412ca72baSTimm Bäder 29512ca72baSTimm Bäder static_assert(bit_cast<unsigned char>(bool8{1,0,1,0,1,0,1,0}) == (LITTLE_END ? 0x55 : 0xAA), ""); 29612ca72baSTimm Bäder 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)}} 29712ca72baSTimm Bäder static_assert(check_round_trip<bool8>(static_cast<unsigned char>(0)), ""); 29812ca72baSTimm Bäder static_assert(check_round_trip<bool8>(static_cast<unsigned char>(1)), ""); 29912ca72baSTimm Bäder static_assert(check_round_trip<bool8>(static_cast<unsigned char>(0x55)), ""); 30012ca72baSTimm Bäder 30112ca72baSTimm Bäder 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), ""); 30212ca72baSTimm Bäder 30312ca72baSTimm Bäder static_assert(check_round_trip<bool16>(static_cast<short>(0xCAFE)), ""); 30412ca72baSTimm Bäder static_assert(check_round_trip<bool32>(static_cast<int>(0xCAFEBABE)), ""); 30512ca72baSTimm Bäder 30612ca72baSTimm Bäder #ifdef __SIZEOF_INT128__ 30712ca72baSTimm Bäder static_assert(check_round_trip<bool128>(static_cast<__int128_t>(0xCAFEBABE0C05FEFEULL)), ""); 30812ca72baSTimm Bäder #endif 30912ca72baSTimm Bäder 31012ca72baSTimm Bäder static_assert(bit_cast<bits<8, uint16_t, 7>, uint16_t>(0xcafe) == (LITTLE_END ? 0x95 : 0x7f)); 31112ca72baSTimm Bäder static_assert(bit_cast<bits<4, uint16_t, 10>, uint16_t>(0xcafe) == (LITTLE_END ? 0x2 : 0xf)); 31212ca72baSTimm Bäder static_assert(bit_cast<bits<4, uint32_t, 19>, uint32_t>(0xa1cafe) == (LITTLE_END ? 0x4 : 0x5)); 31312ca72baSTimm Bäder 31412ca72baSTimm Bäder struct S { 31512ca72baSTimm Bäder // little endian: 31612ca72baSTimm Bäder // MSB .... .... LSB 31712ca72baSTimm Bäder // |y| |x| 31812ca72baSTimm Bäder // 31912ca72baSTimm Bäder // big endian 32012ca72baSTimm Bäder // MSB .... .... LSB 32112ca72baSTimm Bäder // |x| |y| 32212ca72baSTimm Bäder 32312ca72baSTimm Bäder unsigned char x : 4; 32412ca72baSTimm Bäder unsigned char y : 4; 32512ca72baSTimm Bäder 32612ca72baSTimm Bäder constexpr bool operator==(S const &other) const { 32712ca72baSTimm Bäder return x == other.x && y == other.y; 32812ca72baSTimm Bäder } 32912ca72baSTimm Bäder }; 33012ca72baSTimm Bäder 33112ca72baSTimm Bäder constexpr S s{0xa, 0xb}; 33212ca72baSTimm Bäder static_assert(bit_cast<bits<8>>(s) == (LITTLE_END ? 0xba : 0xab)); 33312ca72baSTimm Bäder static_assert(bit_cast<bits<7>>(s) == (LITTLE_END 33412ca72baSTimm Bäder ? 0xba & 0x7f 33512ca72baSTimm Bäder : (0xab & 0xfe) >> 1)); 33612ca72baSTimm Bäder 33712ca72baSTimm Bäder static_assert(round_trip<bits<8>>(s) == s); 33812ca72baSTimm Bäder 33912ca72baSTimm Bäder struct R { 34012ca72baSTimm Bäder unsigned int r : 31; 34112ca72baSTimm Bäder unsigned int : 0; 34212ca72baSTimm Bäder unsigned int : 32; 34312ca72baSTimm Bäder constexpr bool operator==(R const &other) const { 34412ca72baSTimm Bäder return r == other.r; 34512ca72baSTimm Bäder } 34612ca72baSTimm Bäder }; 34712ca72baSTimm Bäder using T = bits<31, signed long long>; 34812ca72baSTimm Bäder constexpr R r{0x4ac0ffee}; 34912ca72baSTimm Bäder constexpr T t = bit_cast<T>(r); 35012ca72baSTimm Bäder static_assert(t == ((0xFFFFFFFF8 << 28) | 0x4ac0ffee)); // sign extension 35112ca72baSTimm Bäder 35212ca72baSTimm Bäder static_assert(round_trip<T>(r) == r); 35312ca72baSTimm Bäder static_assert(round_trip<R>(t) == t); 35412ca72baSTimm Bäder 35512ca72baSTimm Bäder 35612ca72baSTimm Bäder /// The oversized bitfield is an error on Windows and not just a warning. 35712ca72baSTimm Bäder #if !defined(_WIN32) 35812ca72baSTimm Bäder struct U { 35912ca72baSTimm Bäder // expected-warning@+1 {{exceeds the width of its type}} 36012ca72baSTimm Bäder uint32_t trunc : 33; 36112ca72baSTimm Bäder uint32_t u : 31; 36212ca72baSTimm Bäder constexpr bool operator==(U const &other) const { 36312ca72baSTimm Bäder return trunc == other.trunc && u == other.u; 36412ca72baSTimm Bäder } 36512ca72baSTimm Bäder }; 36612ca72baSTimm Bäder struct V { 36712ca72baSTimm Bäder uint64_t notrunc : 32; 36812ca72baSTimm Bäder uint64_t : 1; 36912ca72baSTimm Bäder uint64_t v : 31; 37012ca72baSTimm Bäder constexpr bool operator==(V const &other) const { 37112ca72baSTimm Bäder return notrunc == other.notrunc && v == other.v; 37212ca72baSTimm Bäder } 37312ca72baSTimm Bäder }; 37412ca72baSTimm Bäder 37512ca72baSTimm Bäder constexpr U u{static_cast<unsigned int>(~0), 0x4ac0ffee}; 37612ca72baSTimm Bäder constexpr V v = bit_cast<V>(u); 37712ca72baSTimm Bäder static_assert(v.v == 0x4ac0ffee); 37812ca72baSTimm Bäder 37912ca72baSTimm Bäder static_assert(round_trip<V>(u) == u); 38012ca72baSTimm Bäder static_assert(round_trip<U>(v) == v); 38112ca72baSTimm Bäder 38212ca72baSTimm Bäder constexpr auto w = bit_cast<bits<12, unsigned long, 33>>(u); 38312ca72baSTimm Bäder static_assert(w == (LITTLE_END 38412ca72baSTimm Bäder ? 0x4ac0ffee & 0xFFF 38512ca72baSTimm Bäder : (0x4ac0ffee & (0xFFF << (31 - 12))) >> (31-12) 38612ca72baSTimm Bäder )); 38712ca72baSTimm Bäder #endif 38812ca72baSTimm Bäder 38912ca72baSTimm Bäder 39012ca72baSTimm Bäder namespace NestedStructures { 39112ca72baSTimm Bäder struct J { 39212ca72baSTimm Bäder struct { 39312ca72baSTimm Bäder uint16_t k : 12; 39412ca72baSTimm Bäder } K; 39512ca72baSTimm Bäder struct { 39612ca72baSTimm Bäder uint16_t l : 4; 39712ca72baSTimm Bäder } L; 39812ca72baSTimm Bäder }; 39912ca72baSTimm Bäder 40012ca72baSTimm Bäder static_assert(sizeof(J) == 4); 40112ca72baSTimm Bäder constexpr J j = bit_cast<J>(0x8c0ffee5); 40212ca72baSTimm Bäder 40312ca72baSTimm Bäder static_assert(j.K.k == (LITTLE_END ? 0xee5 : 0x8c0)); 40412ca72baSTimm Bäder static_assert(j.L.l == 0xf /* yay symmetry */); 40512ca72baSTimm Bäder static_assert(bit_cast<bits<4, uint16_t, 16>>(j) == 0xf); 40612ca72baSTimm Bäder struct N { 40712ca72baSTimm Bäder bits<12, uint16_t> k; 40812ca72baSTimm Bäder uint16_t : 16; 40912ca72baSTimm Bäder }; 41012ca72baSTimm Bäder static_assert(bit_cast<N>(j).k == j.K.k); 41112ca72baSTimm Bäder 41212ca72baSTimm Bäder struct M { 41312ca72baSTimm Bäder bits<4, uint16_t, 0> m[2]; 41412ca72baSTimm Bäder constexpr bool operator==(const M& rhs) const { 41512ca72baSTimm Bäder return m[0] == rhs.m[0] && m[1] == rhs.m[1]; 41612ca72baSTimm Bäder }; 41712ca72baSTimm Bäder }; 41812ca72baSTimm Bäder #if LITTLE_END == 1 41912ca72baSTimm Bäder constexpr uint16_t want[2] = {0x5, 0xf}; 42012ca72baSTimm Bäder #else 42112ca72baSTimm Bäder constexpr uint16_t want[2] = {0x8000, 0xf000}; 42212ca72baSTimm Bäder #endif 42312ca72baSTimm Bäder 42412ca72baSTimm Bäder static_assert(bit_cast<M>(j) == bit_cast<M>(want)); 42512ca72baSTimm Bäder } 42612ca72baSTimm Bäder 42712ca72baSTimm Bäder namespace Enums { 42812ca72baSTimm Bäder // ensure we're packed into the top 2 bits 42912ca72baSTimm Bäder constexpr int pad = LITTLE_END ? 6 : 0; 43012ca72baSTimm Bäder struct X 43112ca72baSTimm Bäder { 43212ca72baSTimm Bäder char : pad; 43312ca72baSTimm Bäder enum class direction: char { left, right, up, down } direction : 2; 43412ca72baSTimm Bäder }; 43512ca72baSTimm Bäder 43612ca72baSTimm Bäder constexpr X x = { X::direction::down }; 43712ca72baSTimm Bäder static_assert(bit_cast<bits<2, signed char, pad>>(x) == -1); 43812ca72baSTimm Bäder static_assert(bit_cast<bits<2, unsigned char, pad>>(x) == 3); 43912ca72baSTimm Bäder static_assert( 44012ca72baSTimm Bäder bit_cast<X>((unsigned char)0x40).direction == X::direction::right); 44112ca72baSTimm Bäder } 4422f9cd43aSTimm Baeder 4432f9cd43aSTimm Baeder namespace IndeterminateBits { 4442f9cd43aSTimm Baeder struct S { 4452f9cd43aSTimm Baeder unsigned a : 13; 4462f9cd43aSTimm Baeder unsigned : 17; 4472f9cd43aSTimm Baeder unsigned b : 2; 4482f9cd43aSTimm Baeder }; 4492f9cd43aSTimm Baeder constexpr unsigned A = __builtin_bit_cast(unsigned, S{12, 3}); // expected-error {{must be initialized by a constant expression}} \ 4502f9cd43aSTimm Baeder // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}} 4512f9cd43aSTimm Baeder 4522f9cd43aSTimm Baeder 4532f9cd43aSTimm Baeder /// GCC refuses to compile this as soon as we access the indeterminate bits 4542f9cd43aSTimm Baeder /// in the static_assert. MSVC accepts it. 4552f9cd43aSTimm Baeder struct S2 { 4562f9cd43aSTimm Baeder unsigned char a : 2; 4572f9cd43aSTimm Baeder }; 4582f9cd43aSTimm Baeder constexpr unsigned char B = __builtin_bit_cast(unsigned char, S2{3}); 4592f9cd43aSTimm Baeder static_assert(B == (LITTLE_END ? 3 : 192)); 460*b4150ed1STimm Baeder 461*b4150ed1STimm Baeder 462*b4150ed1STimm Baeder 463*b4150ed1STimm Baeder struct S3 { 464*b4150ed1STimm Baeder unsigned a : 13; 465*b4150ed1STimm Baeder unsigned : 17; 466*b4150ed1STimm Baeder unsigned b : 2; 467*b4150ed1STimm Baeder }; 468*b4150ed1STimm Baeder 469*b4150ed1STimm Baeder struct D { 470*b4150ed1STimm Baeder unsigned a; 471*b4150ed1STimm Baeder }; 472*b4150ed1STimm Baeder constexpr D s = __builtin_bit_cast(D, S3{12, 3}); // expected-error {{must be initialized by a constant expression}} \ 473*b4150ed1STimm Baeder // expected-note {{indeterminate value can only initialize an object of type 'unsigned char' or 'std::byte'; 'unsigned int' is invalid}} 474*b4150ed1STimm Baeder 4752f9cd43aSTimm Baeder } 476