llvm-project/clang/test/AST/ByteCode/builtin-bit-cast-long-double.cpp
Timm Baeder 32fc625a3f
Reapply "Reapply "[clang][bytecode] Allocate IntegralAP and Floating … (#145014)
…types usi… (#144676)"

This reverts commit 68471d29eed2c49f9b439e505b3f24d387d54f97.

IntegralAP contains a union:
  union {
    uint64_t *Memory = nullptr;
    uint64_t Val;
  };

On 64bit systems, both Memory and Val have the same size. However, on 32
bit system, Val is 64bit and Memory only 32bit. Which means the default
initializer for Memory will only zero half of Val. We fixed this by
zero-initializing Val explicitly in the IntegralAP(unsigned BitWidth)
constructor.


See also the discussion in
https://github.com/llvm/llvm-project/pull/144246
2025-06-20 18:06:01 +02:00

104 lines
3.3 KiB
C++

// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s
// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fno-signed-char
// RUN: %clang_cc1 -verify=ref,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple x86_64-apple-macosx10.14.0 %s -fexperimental-new-constant-interpreter
// 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
// RUN: %clang_cc1 -verify=expected,both -std=c++2a -fsyntax-only -triple aarch64_be-linux-gnu %s -fexperimental-new-constant-interpreter
#if !__x86_64
// both-no-diagnostics
#endif
typedef decltype(nullptr) nullptr_t;
typedef __INTPTR_TYPE__ intptr_t;
static_assert(sizeof(int) == 4);
static_assert(sizeof(long long) == 8);
template <class To, class From>
constexpr To bit_cast(const From &from) {
static_assert(sizeof(To) == sizeof(From));
return __builtin_bit_cast(To, from);
#if __x86_64
// both-note@-2 {{indeterminate value can only initialize an object of type}}
#endif
}
template <class Intermediate, class Init>
constexpr bool check_round_trip(const Init &init) {
return bit_cast<Init>(bit_cast<Intermediate>(init)) == init;
}
template <class Intermediate, class Init>
constexpr Init round_trip(const Init &init) {
return bit_cast<Init>(bit_cast<Intermediate>(init));
}
namespace test_long_double {
#if __x86_64
constexpr __int128_t test_cast_to_int128 = bit_cast<__int128_t>((long double)0); // both-error{{must be initialized by a constant expression}}\
// both-note{{in call}}
constexpr long double ld = 3.1425926539;
struct bytes {
unsigned char d[16];
};
static_assert(round_trip<bytes>(ld), "");
static_assert(round_trip<long double>(10.0L));
constexpr long double foo() {
bytes A = __builtin_bit_cast(bytes, ld);
long double ld = __builtin_bit_cast(long double, A);
return ld;
}
static_assert(foo() == ld);
constexpr bool f(bool read_uninit) {
bytes b = bit_cast<bytes>(ld);
unsigned char ld_bytes[10] = {
0x0, 0x48, 0x9f, 0x49, 0xf0,
0x3c, 0x20, 0xc9, 0x0, 0x40,
};
for (int i = 0; i != 10; ++i)
if (ld_bytes[i] != b.d[i])
return false;
if (read_uninit && b.d[10]) // both-note{{read of uninitialized object is not allowed in a constant expression}}
return false;
return true;
}
static_assert(f(/*read_uninit=*/false), "");
static_assert(f(/*read_uninit=*/true), ""); // both-error{{static assertion expression is not an integral constant expression}} \
// both-note{{in call to 'f(true)'}}
constexpr bytes ld539 = {
0x0, 0x0, 0x0, 0x0,
0x0, 0x0, 0xc0, 0x86,
0x8, 0x40, 0x0, 0x0,
0x0, 0x0, 0x0, 0x0,
};
constexpr long double fivehundredandthirtynine = 539.0;
static_assert(bit_cast<long double>(ld539) == fivehundredandthirtynine, "");
struct LD {
long double v;
};
constexpr LD ld2 = __builtin_bit_cast(LD, ld539.d);
constexpr long double five39 = __builtin_bit_cast(long double, ld539.d);
static_assert(ld2.v == five39);
#else
static_assert(round_trip<__int128_t>(34.0L));
#endif
}