Skip to content

Commit 745bd74

Browse files
committed
[clang][bytecode] Initialize bases when bitcasting
When bitcasting into a composite type, we might be initialzing all the fields of a base, but we still need to mark the base pointer itself as initialized. I have a feeling we need to do the same with composite fields, too.
1 parent f5fa371 commit 745bd74

File tree

3 files changed

+28
-17
lines changed

3 files changed

+28
-17
lines changed

clang/lib/AST/ByteCode/BitcastBuffer.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct Bits {
2828
size_t getOffsetInByte() const { return N % 8; }
2929
bool isFullByte() const { return N % 8 == 0; }
3030
bool nonZero() const { return N != 0; }
31+
bool isZero() const { return N == 0; }
3132

3233
Bits operator-(Bits Other) { return Bits(N - Other.N); }
3334
Bits operator+(Bits Other) { return Bits(N + Other.N); }

clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,10 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset,
134134
Layout.getBaseClassOffset(cast<CXXRecordDecl>(B.Decl));
135135
Bits BitOffset = Offset + Bits(Ctx.getASTContext().toBits(ByteOffset));
136136
Ok = Ok && enumerateData(Elem, Ctx, BitOffset, F);
137+
// FIXME: We should only (need to) do this when bitcasting OUT of the
138+
// buffer, not when copying data into it.
139+
if (Ok)
140+
Elem.initialize();
137141
}
138142

139143
return Ok;
@@ -225,19 +229,32 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
225229
FromPtr, Ctx,
226230
[&](const Pointer &P, PrimType T, Bits BitOffset,
227231
bool PackedBools) -> bool {
228-
// if (!P.isInitialized()) {
229-
// assert(false && "Implement uninitialized value tracking");
230-
// return ReturnOnUninit;
231-
// }
232+
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
233+
Bits BitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
234+
Bits FullBitWidth = BitWidth;
235+
236+
if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) {
237+
// Unnamed bitfields should be skipped altogether.
238+
if (FD->isUnnamedBitField())
239+
return true;
240+
BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
241+
(unsigned)FullBitWidth.getQuantity()));
242+
} else if (T == PT_Bool && PackedBools)
243+
BitWidth = Bits(1);
232244

233-
// assert(P.isInitialized());
245+
if (BitWidth.isZero())
246+
return true;
247+
248+
if (!P.isInitialized()) {
249+
assert(false && "Implement uninitialized value tracking");
250+
return ReturnOnUninit;
251+
}
252+
253+
assert(P.isInitialized());
234254
// nullptr_t is a PT_Ptr for us, but it's still not std::is_pointer_v.
235255
if (T == PT_Ptr)
236256
assert(false && "Implement casting to pointer types");
237257

238-
CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
239-
Bits BitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
240-
Bits FullBitWidth = BitWidth;
241258
auto Buff =
242259
std::make_unique<std::byte[]>(ObjectReprChars.getQuantity());
243260
// Work around floating point types that contain unused padding bytes.
@@ -256,12 +273,6 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
256273
swapBytes(Buff.get(), NumBits.roundToBytes());
257274

258275
} else {
259-
if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
260-
BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
261-
(unsigned)FullBitWidth.getQuantity()));
262-
else if (T == PT_Bool && PackedBools)
263-
BitWidth = Bits(1);
264-
265276
BITCAST_TYPE_SWITCH(T, { P.deref<T>().bitcastToMemory(Buff.get()); });
266277

267278
if (llvm::sys::IsBigEndianHost)

clang/test/AST/ByteCode/builtin-bit-cast.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,8 @@ void test_record() {
335335
static_assert(t4 == tuple4{1, 2, 3, 4});
336336
static_assert(check_round_trip<tuple4>(b));
337337

338-
/// FIXME: We need to initialize the base pointers in the pointer we're bitcasting to.
339-
// constexpr auto b2 = bit_cast<bases>(t4);
340-
// static_assert(t4 == b2);
338+
constexpr auto b2 = bit_cast<bases>(t4);
339+
static_assert(t4 == b2);
341340
}
342341

343342
void test_partially_initialized() {

0 commit comments

Comments
 (0)