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() { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits