xref: /llvm-project/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp (revision 1fbbf4c418bc4945839a70fe2849cbe6fbcc3d66)
1 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s
2 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char
3 // RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s
4 
5 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter
6 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char -fexperimental-new-constant-interpreter
7 // RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter
8 
9 #if !__x86_64
10 // both-no-diagnostics
11 #endif
12 
13 
14 typedef decltype(nullptr) nullptr_t;
15 typedef __INTPTR_TYPE__ intptr_t;
16 
17 static_assert(sizeof(int) == 4);
18 static_assert(sizeof(long long) == 8);
19 
20 template <class To, class From>
21 constexpr To bit_cast(const From &from) {
22   static_assert(sizeof(To) == sizeof(From));
23   return __builtin_bit_cast(To, from);
24 }
25 
26 template <class Intermediate, class Init>
27 constexpr bool check_round_trip(const Init &init) {
28   return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
29 }
30 
31 template <class Intermediate, class Init>
32 constexpr Init round_trip(const Init &init) {
33   return bit_cast<Init>(bit_cast<Intermediate>(init));
34 }
35 
36 
37 
38 
39 namespace test_long_double {
40 #if __x86_64
41 /// FIXME: We could enable this, but since it aborts, it causes the usual mempory leak.
42 #if 0
43 constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // expected-error{{must be initialized by a constant expression}}\
44                                                                                  // expected-note{{in call}}
45 #endif
46 constexpr long double ld = 3.1425926539;
47 
48 struct bytes {
49   unsigned char d[16];
50 };
51 
52 static_assert(round_trip<bytes>(ld), "");
53 
54 static_assert(round_trip<long double>(10.0L));
55 
56 constexpr long double foo() {
57   bytes A = __builtin_bit_cast(bytes, ld);
58   long double ld = __builtin_bit_cast(long double, A);
59   return ld;
60 }
61 static_assert(foo() == ld);
62 
63 constexpr bool f(bool read_uninit) {
64   bytes b = bit_cast<bytes>(ld);
65   unsigned char ld_bytes[10] = {
66     0x0,  0x48, 0x9f, 0x49, 0xf0,
67     0x3c, 0x20, 0xc9, 0x0,  0x40,
68   };
69 
70   for (int i = 0; i != 10; ++i)
71     if (ld_bytes[i] != b.d[i])
72       return false;
73 
74   if (read_uninit && b.d[10]) // both-note{{read of uninitialized object is not allowed in a constant expression}}
75     return false;
76 
77   return true;
78 }
79 
80 static_assert(f(/*read_uninit=*/false), "");
81 static_assert(f(/*read_uninit=*/true), ""); // both-error{{static assertion expression is not an integral constant expression}} \
82                                             // both-note{{in call to 'f(true)'}}
83 constexpr bytes ld539 = {
84   0x0, 0x0,  0x0,  0x0,
85   0x0, 0x0,  0xc0, 0x86,
86   0x8, 0x40, 0x0,  0x0,
87   0x0, 0x0,  0x0,  0x0,
88 };
89 constexpr long double fivehundredandthirtynine = 539.0;
90 static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
91 
92 struct LD {
93   long double v;
94 };
95 
96 constexpr LD ld2 = __builtin_bit_cast(LD, ld539.d);
97 constexpr long double five39 = __builtin_bit_cast(long double, ld539.d);
98 static_assert(ld2.v == five39);
99 
100 #else
101 static_assert(round_trip<__int128_t>(34.0L));
102 #endif
103 }
104