[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