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