[clang] 7aec6dc - [clang][bytecode] Initialize bases when bitcasting (#117179)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 4 07:49:08 PST 2024
Author: Timm Baeder
Date: 2024-12-04T16:49:03+01:00
New Revision: 7aec6dc477f8148ed066d10dfc7a012a51b6599c
URL: https://github.com/llvm/llvm-project/commit/7aec6dc477f8148ed066d10dfc7a012a51b6599c
DIFF: https://github.com/llvm/llvm-project/commit/7aec6dc477f8148ed066d10dfc7a012a51b6599c.diff
LOG: [clang][bytecode] Initialize bases when bitcasting (#117179)
Base pointers do not get passed to the callback, so initialize them when iterating bases.
Added:
Modified:
clang/lib/AST/ByteCode/BitcastBuffer.h
clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
clang/lib/AST/ByteCode/Record.h
clang/test/AST/ByteCode/builtin-bit-cast.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/ByteCode/BitcastBuffer.h b/clang/lib/AST/ByteCode/BitcastBuffer.h
index 8442df5c60cf56..c7b170ceb168fa 100644
--- a/clang/lib/AST/ByteCode/BitcastBuffer.h
+++ b/clang/lib/AST/ByteCode/BitcastBuffer.h
@@ -28,6 +28,7 @@ struct Bits {
size_t getOffsetInByte() const { return N % 8; }
bool isFullByte() const { return N % 8 == 0; }
bool nonZero() const { return N != 0; }
+ bool isZero() const { return N == 0; }
Bits operator-(Bits Other) { return Bits(N - Other.N); }
Bits operator+(Bits Other) { return Bits(N + Other.N); }
diff --git a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
index 2fae7f873ab11b..8f7edaa18c74b4 100644
--- a/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
+++ b/clang/lib/AST/ByteCode/InterpBuiltinBitCast.cpp
@@ -127,6 +127,8 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset,
bool Ok = true;
for (const Record::Field &Fi : R->fields()) {
+ if (Fi.isUnnamedBitField())
+ continue;
Pointer Elem = P.atField(Fi.Offset);
Bits BitOffset =
Offset + Bits(Layout.getFieldOffset(Fi.Decl->getFieldIndex()));
@@ -138,6 +140,10 @@ static bool enumerateData(const Pointer &P, const Context &Ctx, Bits Offset,
Layout.getBaseClassOffset(cast<CXXRecordDecl>(B.Decl));
Bits BitOffset = Offset + Bits(Ctx.getASTContext().toBits(ByteOffset));
Ok = Ok && enumerateData(Elem, Ctx, BitOffset, BitsToRead, F);
+ // FIXME: We should only (need to) do this when bitcasting OUT of the
+ // buffer, not when copying data into it.
+ if (Ok)
+ Elem.initialize();
}
return Ok;
@@ -229,19 +235,29 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
FromPtr, Ctx, Buffer.size(),
[&](const Pointer &P, PrimType T, Bits BitOffset,
bool PackedBools) -> bool {
- // if (!P.isInitialized()) {
- // assert(false && "Implement uninitialized value tracking");
- // return ReturnOnUninit;
- // }
+ CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
+ Bits BitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
+ Bits FullBitWidth = BitWidth;
+
+ if (const FieldDecl *FD = P.getField(); FD && FD->isBitField()) {
+ BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
+ (unsigned)FullBitWidth.getQuantity()));
+ } else if (T == PT_Bool && PackedBools)
+ BitWidth = Bits(1);
- // assert(P.isInitialized());
+ if (BitWidth.isZero())
+ return true;
+
+ if (!P.isInitialized()) {
+ assert(false && "Implement uninitialized value tracking");
+ return ReturnOnUninit;
+ }
+
+ assert(P.isInitialized());
// nullptr_t is a PT_Ptr for us, but it's still not std::is_pointer_v.
if (T == PT_Ptr)
assert(false && "Implement casting to pointer types");
- CharUnits ObjectReprChars = ASTCtx.getTypeSizeInChars(P.getType());
- Bits BitWidth = Bits(ASTCtx.toBits(ObjectReprChars));
- Bits FullBitWidth = BitWidth;
auto Buff =
std::make_unique<std::byte[]>(ObjectReprChars.getQuantity());
// Work around floating point types that contain unused padding bytes.
@@ -260,12 +276,6 @@ static bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr,
swapBytes(Buff.get(), NumBits.roundToBytes());
} else {
- if (const FieldDecl *FD = P.getField(); FD && FD->isBitField())
- BitWidth = Bits(std::min(FD->getBitWidthValue(ASTCtx),
- (unsigned)FullBitWidth.getQuantity()));
- else if (T == PT_Bool && PackedBools)
- BitWidth = Bits(1);
-
BITCAST_TYPE_SWITCH(T, { P.deref<T>().bitcastToMemory(Buff.get()); });
if (llvm::sys::IsBigEndianHost)
diff --git a/clang/lib/AST/ByteCode/Record.h b/clang/lib/AST/ByteCode/Record.h
index 7a5c482e4efccd..686b5dbc431d99 100644
--- a/clang/lib/AST/ByteCode/Record.h
+++ b/clang/lib/AST/ByteCode/Record.h
@@ -30,6 +30,7 @@ class Record final {
unsigned Offset;
const Descriptor *Desc;
bool isBitField() const { return Decl->isBitField(); }
+ bool isUnnamedBitField() const { return Decl->isUnnamedBitField(); }
};
/// Describes a base class.
diff --git a/clang/test/AST/ByteCode/builtin-bit-cast.cpp b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
index e956675b18b85f..d3935b4f921b3f 100644
--- a/clang/test/AST/ByteCode/builtin-bit-cast.cpp
+++ b/clang/test/AST/ByteCode/builtin-bit-cast.cpp
@@ -350,9 +350,8 @@ void test_record() {
static_assert(t4 == tuple4{1, 2, 3, 4});
static_assert(check_round_trip<tuple4>(b));
- /// FIXME: We need to initialize the base pointers in the pointer we're bitcasting to.
-// constexpr auto b2 = bit_cast<bases>(t4);
-// static_assert(t4 == b2);
+ constexpr auto b2 = bit_cast<bases>(t4);
+ static_assert(t4 == b2);
}
void test_partially_initialized() {
More information about the cfe-commits
mailing list