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