MitalAshok created this revision.
Herald added a project: All.
MitalAshok retitled this revision from "Fix 
std::has_unique_object_representations for _BitInt types with padding" to "Fix 
std::has_unique_object_representations for _BitInt types with padding bits".
MitalAshok edited the summary of this revision.
MitalAshok added reviewers: erichkeane, aaron.ballman.
MitalAshok added a reviewer: rsmith.
MitalAshok edited projects, added clang; removed All.
Herald added a project: All.
MitalAshok published this revision for review.
Herald added a subscriber: cfe-commits.

"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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125802

Files:
  clang/lib/AST/ASTContext.cpp
  clang/test/SemaCXX/has_unique_object_reps_bitint.cpp

Index: clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
===================================================================
--- /dev/null
+++ clang/test/SemaCXX/has_unique_object_reps_bitint.cpp
@@ -0,0 +1,76 @@
+// 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)));
+static_assert(sizeof(_BitInt(24)) != 4 || !__has_unique_object_representations(_BitInt(24)));
+
+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));
+
+static_assert(__has_unique_object_representations(_BitInt(7)&) == __has_unique_object_representations(_BitInt(8)&));
+static_assert(__has_unique_object_representations(_BitInt(8)&) == __has_unique_object_representations(int&));
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -2684,7 +2684,12 @@
     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()->isReferenceType() && Field->getType()->isBitIntType();
+  if (!Field->getType()->isReferenceType() && !IsBitIntType &&
       !Context.hasUniqueObjectRepresentations(Field->getType()))
     return llvm::None;
 
@@ -2692,9 +2697,17 @@
       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 +2805,13 @@
     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())
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to