[clang] 872f744 - Fix std::has_unique_object_representations for _BitInt types with padding bits

Aaron Ballman via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 1 08:35:29 PDT 2022


Author: Mital Ashok
Date: 2022-06-01T11:34:40-04:00
New Revision: 872f74440f3c8b749d90384a23caa894068504f9

URL: https://github.com/llvm/llvm-project/commit/872f74440f3c8b749d90384a23caa894068504f9
DIFF: https://github.com/llvm/llvm-project/commit/872f74440f3c8b749d90384a23caa894068504f9.diff

LOG: Fix std::has_unique_object_representations for _BitInt types with padding bits

"std::has_unique_object_representations<_BitInt(N)>" was always true,
even if the type has padding bits (since the trait assumes all integer
types have no padding bits). The standard has an explicit note that
this should not hold for types with padding bits.

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

Added: 
    clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/lib/AST/ASTContext.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 83db2a7cd38b6..b58f856800493 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -158,6 +158,8 @@ Bug Fixes
 - Implement `CWG 2394 <https://wg21.link/cwg2394>`_: Const class members
   may be initialized with a defaulted default constructor under the same
   conditions it would be allowed for a const object elsewhere.
+- ``__has_unique_object_representations`` no longer reports that ``_BitInt`` types
+  have unique object representations if they have padding bits.
 
 Improvements to Clang's diagnostics
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 6349d7b7c46f3..eab6c34bb8f1a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,11 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) {
     if (!RD->isUnion())
       return structHasUniqueObjectRepresentations(Context, RD);
   }
-  if (!Field->getType()->isReferenceType() &&
+
+  // A _BitInt type may not be unique if it has padding bits
+  // but if it is a bitfield the padding bits are not used.
+  bool IsBitIntType = Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
       !Context.hasUniqueObjectRepresentations(Field->getType()))
     return llvm::None;
 
@@ -2692,9 +2696,17 @@ getSubobjectSizeInBits(const FieldDecl *Field, const ASTContext &Context) {
       Context.toBits(Context.getTypeSizeInChars(Field->getType()));
   if (Field->isBitField()) {
     int64_t BitfieldSize = Field->getBitWidthValue(Context);
-    if (BitfieldSize > FieldSizeInBits)
+    if (IsBitIntType) {
+      if ((unsigned)BitfieldSize >
+          cast<BitIntType>(Field->getType())->getNumBits())
+        return llvm::None;
+    } else if (BitfieldSize > FieldSizeInBits) {
       return llvm::None;
+    }
     FieldSizeInBits = BitfieldSize;
+  } else if (IsBitIntType &&
+             !Context.hasUniqueObjectRepresentations(Field->getType())) {
+    return llvm::None;
   }
   return FieldSizeInBits;
 }
@@ -2792,8 +2804,13 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const {
     return false;
 
   // All integrals and enums are unique.
-  if (Ty->isIntegralOrEnumerationType())
+  if (Ty->isIntegralOrEnumerationType()) {
+    // Except _BitInt types that have padding bits.
+    if (const auto *BIT = dyn_cast<BitIntType>(Ty))
+      return getTypeSize(BIT) == BIT->getNumBits();
+
     return true;
+  }
 
   // All other pointers are unique.
   if (Ty->isPointerType())

diff  --git a/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp b/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
new file mode 100644
index 0000000000000..83190d006030e
--- /dev/null
+++ b/clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,86 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only -verify -std=c++17 -Wno-bitfield-width %s
+//  expected-no-diagnostics
+
+static_assert(__has_unique_object_representations(_BitInt(8)));
+static_assert(__has_unique_object_representations(unsigned _BitInt(8)));
+static_assert(__has_unique_object_representations(_BitInt(sizeof(int) * 8u)));
+// sizeof(_BitInt(24)) may be 4 to align it to the next greater integer type, in which case it would have 8 padding bits.
+static_assert(__has_unique_object_representations(_BitInt(24)) == (sizeof(_BitInt(24)) == 3));
+
+static_assert(!__has_unique_object_representations(_BitInt(7)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(7)));
+static_assert(!__has_unique_object_representations(_BitInt(2)));
+static_assert(!__has_unique_object_representations(unsigned _BitInt(1)));
+
+template <unsigned N>
+constexpr bool check() {
+  if constexpr (N <= __BITINT_MAXWIDTH__) {
+    static_assert(__has_unique_object_representations(_BitInt(N)) == (sizeof(_BitInt(N)) * 8u == N));
+    static_assert(__has_unique_object_representations(unsigned _BitInt(N)) == (sizeof(unsigned _BitInt(N)) * 8u == N));
+  }
+  return true;
+}
+
+template <unsigned... N>
+constexpr bool do_check = (check<N>() && ...);
+
+static_assert(do_check<2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18>);
+static_assert(do_check<15, 16, 17, 23, 24, 25, 31, 32, 33>);
+static_assert(do_check<39, 40, 41, 47, 48, 49>);
+static_assert(do_check<127, 128, 129, 255, 256, 257, 383, 384, 385>);
+
+template <unsigned N>
+struct in_struct {
+  _BitInt(N) x;
+  static constexpr bool check() {
+    return __has_unique_object_representations(in_struct<N>) == __has_unique_object_representations(_BitInt(N));
+  }
+};
+
+static_assert(in_struct<8>::check());
+static_assert(in_struct<7>::check());
+
+struct bit_fields_1 {
+  _BitInt(7) x : 7;
+  unsigned _BitInt(1) y : 1;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_1) == (sizeof(bit_fields_1) == 1));
+
+struct bit_fields_2 {
+  _BitInt(8) x : 7;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_2));
+
+struct bit_fields_3 {
+  _BitInt(15) x : 8;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_3) == (sizeof(bit_fields_3) == 1));
+
+#if __BITINT_MAXWIDTH__ >= 129
+struct bit_fields_4 {
+  _BitInt(129) x : 128;
+};
+
+static_assert(__has_unique_object_representations(bit_fields_4) == (sizeof(bit_fields_4) == 128 / 8));
+#endif
+
+struct bit_fields_5 {
+  _BitInt(2) x : 8;
+};
+
+static_assert(!__has_unique_object_representations(bit_fields_5));
+
+template <unsigned N>
+struct ref_member {
+  _BitInt(N) & x;
+};
+
+struct int_ref_member {
+  int &x;
+};
+
+static_assert(__has_unique_object_representations(ref_member<7>) == __has_unique_object_representations(ref_member<8>));
+static_assert(__has_unique_object_representations(ref_member<8>) == __has_unique_object_representations(int_ref_member));


        


More information about the cfe-commits mailing list