[clang][bytecode] Check pointer data type for bitcast eligibility (#146552)

So we get the proper type for a heap-allocated value.
This commit is contained in:
Timm Baeder
2025-07-01 20:37:09 +02:00
committed by GitHub
parent 8dbfe83681
commit b54e02a40b
2 changed files with 25 additions and 3 deletions

View File

@@ -335,7 +335,8 @@ bool clang::interp::DoBitCast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
BitcastBuffer Buffer(FullBitWidth); BitcastBuffer Buffer(FullBitWidth);
size_t BuffSize = FullBitWidth.roundToBytes(); size_t BuffSize = FullBitWidth.roundToBytes();
if (!CheckBitcastType(S, OpPC, Ptr.getType(), /*IsToType=*/false)) QualType DataType = Ptr.getFieldDesc()->getDataType(S.getASTContext());
if (!CheckBitcastType(S, OpPC, DataType, /*IsToType=*/false))
return false; return false;
bool Success = readPointerToBuffer(S.getContext(), Ptr, Buffer, bool Success = readPointerToBuffer(S.getContext(), Ptr, Buffer,
@@ -370,8 +371,8 @@ bool clang::interp::DoBitCastPtr(InterpState &S, CodePtr OpPC,
assert(FromPtr.isBlockPointer()); assert(FromPtr.isBlockPointer());
assert(ToPtr.isBlockPointer()); assert(ToPtr.isBlockPointer());
QualType FromType = FromPtr.getType(); QualType FromType = FromPtr.getFieldDesc()->getDataType(S.getASTContext());
QualType ToType = ToPtr.getType(); QualType ToType = ToPtr.getFieldDesc()->getDataType(S.getASTContext());
if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true)) if (!CheckBitcastType(S, OpPC, ToType, /*IsToType=*/true))
return false; return false;

View File

@@ -1,6 +1,7 @@
// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fexperimental-new-constant-interpreter -verify=expected,both %s -DBYTECODE // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -fexperimental-new-constant-interpreter -verify=expected,both %s -DBYTECODE
// RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify=ref,both %s // RUN: %clang_cc1 -std=c++2c -fcxx-exceptions -verify=ref,both %s
typedef __INT64_TYPE__ int64_t;
namespace std { namespace std {
using size_t = decltype(sizeof(0)); using size_t = decltype(sizeof(0));
template<typename T> struct allocator { template<typename T> struct allocator {
@@ -465,3 +466,23 @@ namespace ArrayRoot {
static_assert(foo() == 0); static_assert(foo() == 0);
} }
namespace bitcast {
template <typename F, typename T>
constexpr T bit_cast(const F &f) {
return __builtin_bit_cast(T, f);
}
constexpr int foo() {
double *d = std::allocator<double>{}.allocate(2);
std::construct_at<double>(d, 0);
double &dd = *d;
int64_t i = bit_cast<double, int64_t>(*d);
std::allocator<double>{}.deallocate(d);
return i;
}
static_assert(foo() == 0);
}