================
@@ -3375,6 +3376,170 @@ void CastOperation::CheckCStyleCast() {
checkCastAlign();
}
+namespace {
+class BitCastBitClassifier {
+ const ASTContext &Ctx;
+
+ static void setRange(llvm::BitVector &BV, uint64_t Start, uint64_t Len) {
+ if (Len != 0)
+ BV.set(Start, Start + Len);
+ }
+
+public:
+ /// Bits in the value representation.
+ llvm::BitVector Value;
+ /// Bits enclosed by a union.
+ llvm::BitVector Union;
+ /// Bits enclosed by ``std::byte`` or unsigned ordinary character type.
+ llvm::BitVector ByteLike;
+
+ explicit BitCastBitClassifier(const ASTContext &Ctx) : Ctx(Ctx) {}
+
+ /// Classify the bits of \p T. Returns ``false`` if the type contains
+ /// constructs that this analysis does not model precisely (e.g.
bit-fields),
+ /// in which case the result is unusable.
+ [[nodiscard]] bool classify(QualType T) {
+ // TODO: Implement classification on big endian.
+ if (Ctx.getTargetInfo().isBigEndian())
+ return false;
+
+ uint64_t Bits = Ctx.getTypeSize(T);
+ Value.resize(Bits, false);
+ Union.resize(Bits, false);
+ ByteLike.resize(Bits, false);
+ return visit(T, 0);
+ }
+
+private:
+ [[nodiscard]] bool visit(QualType T, uint64_t StartBit) {
+ if (T.isNull() || T->isDependentType() || T->isFunctionType() ||
+ T->isReferenceType())
+ return false;
+
+ T = T.getCanonicalType().getUnqualifiedType();
+ uint64_t Bits = Ctx.getTypeSize(T);
+
+ // [bit.cast] permits casting padding to ``std::byte`` and to an unsigned
+ // ordinary character type.
+ {
+ QualType U = T;
+ bool IsByteLike = U->isStdByteType();
+ if (const auto *BT = U->getAs<BuiltinType>())
+ IsByteLike = BT->getKind() == BuiltinType::UChar ||
+ BT->getKind() == BuiltinType::Char_U;
+ if (IsByteLike) {
+ setRange(Value, StartBit, Bits);
+ setRange(ByteLike, StartBit, Bits);
+ return true;
+ }
+ }
+
+ if (const auto *AT = T->getAs<AtomicType>())
+ return visit(AT->getValueType(), StartBit);
+
+ if (const auto *CAT = Ctx.getAsConstantArrayType(T)) {
+ QualType Elem = CAT->getElementType();
+ uint64_t ElemBits = Ctx.getTypeSize(Elem);
+ uint64_t N = CAT->getSize().getZExtValue();
+ for (uint64_t I = 0; I < N; ++I)
+ if (!visit(Elem, StartBit + I * ElemBits))
+ return false;
+ return true;
+ }
+
+ if (const auto *CT = T->getAs<ComplexType>()) {
+ QualType Elem = CT->getElementType();
+ uint64_t ElemBits = Ctx.getTypeSize(Elem);
+ return visit(Elem, StartBit) && visit(Elem, StartBit + ElemBits);
+ }
+
+ if (const auto *VT = T->getAs<VectorType>()) {
+ // Packed bool vectors store one bit per element, followd by padding.
+ if (T->isPackedVectorBoolType(Ctx)) {
+ setRange(Value, StartBit, Bits);
+ return true;
+ }
+ // Otherwise treat vectors as arrays of their element type.
+ QualType Elem = VT->getElementType();
+ uint64_t ElemBits = Ctx.getTypeSize(Elem);
+ for (unsigned I = 0; I < VT->getNumElements(); ++I)
+ if (!visit(Elem, StartBit + I * ElemBits))
+ return false;
+ return true;
+ }
+
+ if (const auto *RT = T->getAs<RecordType>()) {
+ const RecordDecl *RD = RT->getDecl();
+ if (!RD || !RD->getDefinition() || RD->isInvalidDecl())
+ return false;
+ RD = RD->getDefinition();
+
+ if (RD->isUnion()) {
+ setRange(Union, StartBit, Bits);
+ return true;
+ }
+
+ const ASTRecordLayout &Layout = Ctx.getASTRecordLayout(RD);
+ if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD)) {
+ for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
+ const CXXRecordDecl *BD = BS.getType()->getAsCXXRecordDecl();
+ if (!BD)
+ return false;
+ uint64_t Off = Ctx.toBits(Layout.getBaseClassOffset(BD));
+ if (!visit(BS.getType(), StartBit + Off))
+ return false;
+ }
+ }
+
+ unsigned Idx = 0;
+ for (const FieldDecl *FD : RD->fields()) {
+ if (FD->isBitField())
+ // The value representation of a bit-field is a strict subset of
+ // its storage unit; skip rather than risk false positives.
+ return false;
+ uint64_t Off = Layout.getFieldOffset(Idx++);
+ if (!visit(FD->getType(), StartBit + Off))
+ return false;
+ }
+ return true;
+ }
+
+ if (const auto *BIT = T->getAs<BitIntType>())
+ setRange(Value, StartBit, BIT->getNumBits());
+ else if (T->isFloatingType())
+ setRange(Value, StartBit,
+ llvm::APFloat::getSizeInBits(Ctx.getFloatTypeSemantics(T)));
+ else
+ // We assume that any other scalar type is made entirely of value bits.
+ setRange(Value, StartBit, Bits);
+ return true;
+ }
+};
+
+/// Returns true if every input to a ``__builtin_bit_cast`` from \p SrcType to
+/// \p DestType maps at least one source padding bit onto a destination value
+/// bit.
+static bool IsDegenerateBitCast(const ASTContext &Ctx, QualType SrcType,
+ QualType DestType) {
----------------
cor3ntin wrote:
Can we fine a more descriptive name here?
https://github.com/llvm/llvm-project/pull/200362
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits