[Clang][AST] Fix __has_unique_object_representations computation for unnamed bitfields.
authorRoy Jacobson <roi.jacobson1@gmail.com>
Sat, 11 Mar 2023 16:39:33 +0000 (18:39 +0200)
committerRoy Jacobson <roi.jacobson1@gmail.com>
Sat, 1 Apr 2023 21:54:45 +0000 (00:54 +0300)
As pointed out in https://github.com/llvm/llvm-project/issues/61336, objects with
unnamed bitfields aren't be uniquely representable.

Reviewed By: shafik, Endill

Differential Revision: https://reviews.llvm.org/D145852

clang/docs/ReleaseNotes.rst
clang/lib/AST/ASTContext.cpp
clang/test/SemaCXX/type-traits.cpp

index 4640ecc..cd9aae9 100644 (file)
@@ -291,6 +291,9 @@ Bug Fixes to C++ Support
   template parameters with different nested constraints.
 - Fix type equivalence comparison between auto types to take constraints into
   account.
+- Fix bug in the computation of the ``__has_unique_object_representations``
+  builtin for types with unnamed bitfields.
+  (`#61336 <https://github.com/llvm/llvm-project/issues/61336>`_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
index 612fcd4..bd4f2ff 100644 (file)
@@ -2716,6 +2716,11 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) {
   int64_t FieldSizeInBits =
       Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
+    // If we have explicit padding bits, they don't contribute bits
+    // to the actual object representation, so return 0.
+    if (Field->isUnnamedBitfield())
+      return 0;
+
     int64_t BitfieldSize = Field->getBitWidthValue(Context);
     if (IsBitIntType) {
       if ((unsigned)BitfieldSize >
index 7d425ac..e3fc657 100644 (file)
@@ -2828,6 +2828,17 @@ static_assert(!has_unique_object_representations<WeirdAlignment>::value, "Alignm
 static_assert(!has_unique_object_representations<WeirdAlignmentUnion>::value, "Alignment causes padding");
 static_assert(!has_unique_object_representations<WeirdAlignment[42]>::value, "Also no arrays that have padding");
 
+struct __attribute__((packed)) PackedNoPadding1 {
+  short i;
+  int j;
+};
+struct __attribute__((packed)) PackedNoPadding2 {
+  int j;
+  short i;
+};
+static_assert(has_unique_object_representations<PackedNoPadding1>::value, "Packed structs have no padding");
+static_assert(has_unique_object_representations<PackedNoPadding2>::value, "Packed structs have no padding");
+
 static_assert(!has_unique_object_representations<int(int)>::value, "Functions are not unique");
 static_assert(!has_unique_object_representations<int(int) const>::value, "Functions are not unique");
 static_assert(!has_unique_object_representations<int(int) volatile>::value, "Functions are not unique");
@@ -2878,9 +2889,35 @@ struct AlignedPaddedBitfield {
   char d : 2;
 };
 
+struct UnnamedBitfield {
+  int named : 8;
+  int : 24;
+};
+
+struct __attribute__((packed)) UnnamedBitfieldPacked {
+  int named : 8;
+  int : 24;
+};
+
+struct UnnamedEmptyBitfield {
+  int named;
+  int : 0;
+};
+
+struct UnnamedEmptyBitfieldSplit {
+  short named;
+  int : 0;
+  short also_named;
+};
+
 static_assert(!has_unique_object_representations<PaddedBitfield>::value, "Bitfield padding");
 static_assert(has_unique_object_representations<UnPaddedBitfield>::value, "Bitfield padding");
 static_assert(!has_unique_object_representations<AlignedPaddedBitfield>::value, "Bitfield padding");
+static_assert(!has_unique_object_representations<UnnamedBitfield>::value, "Bitfield padding");
+static_assert(!has_unique_object_representations<UnnamedBitfieldPacked>::value, "Bitfield padding");
+static_assert(has_unique_object_representations<UnnamedEmptyBitfield>::value, "Bitfield padding");
+static_assert(sizeof(UnnamedEmptyBitfieldSplit) != (sizeof(short) * 2), "Wrong size");
+static_assert(!has_unique_object_representations<UnnamedEmptyBitfieldSplit>::value, "Bitfield padding");
 
 struct BoolBitfield {
   bool b : 8;