Author: Timm Baeder Date: 2026-02-10T07:53:23+01:00 New Revision: 461e43371855d4c4ce84931270db5ccd1ccd453b
URL: https://github.com/llvm/llvm-project/commit/461e43371855d4c4ce84931270db5ccd1ccd453b DIFF: https://github.com/llvm/llvm-project/commit/461e43371855d4c4ce84931270db5ccd1ccd453b.diff LOG: [clang][bytecode] Don't use trunc() to increase APInt bitWidth (#180536) `FieldDecl::getBitWidthValue()` can return a value higher than the type size of the bit field. We need to account for that. Added: Modified: clang/lib/AST/ByteCode/Interp.h clang/test/AST/ByteCode/intap.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index ca5b1fd6bf072..0d0f19e4f61dd 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -1703,16 +1703,15 @@ bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) { const Pointer &Field = Ptr.atField(F->Offset); + unsigned BitWidth = std::min(F->Decl->getBitWidthValue(), Value.bitWidth()); if constexpr (needsAlloc<T>()) { T Result = S.allocAP<T>(Value.bitWidth()); - if (T::isSigned()) - Result.copy(Value.toAPSInt() - .trunc(F->Decl->getBitWidthValue()) - .sextOrTrunc(Value.bitWidth())); + if constexpr (T::isSigned()) + Result.copy( + Value.toAPSInt().trunc(BitWidth).sextOrTrunc(Value.bitWidth())); else - Result.copy(Value.toAPSInt() - .trunc(F->Decl->getBitWidthValue()) - .zextOrTrunc(Value.bitWidth())); + Result.copy( + Value.toAPSInt().trunc(BitWidth).zextOrTrunc(Value.bitWidth())); Field.deref<T>() = Result; } else { @@ -1735,16 +1734,15 @@ bool InitBitFieldActivate(InterpState &S, CodePtr OpPC, const Pointer &Field = Ptr.atField(F->Offset); + unsigned BitWidth = std::min(F->Decl->getBitWidthValue(), Value.bitWidth()); if constexpr (needsAlloc<T>()) { T Result = S.allocAP<T>(Value.bitWidth()); - if (T::isSigned()) - Result.copy(Value.toAPSInt() - .trunc(F->Decl->getBitWidthValue()) - .sextOrTrunc(Value.bitWidth())); + if constexpr (T::isSigned()) + Result.copy( + Value.toAPSInt().trunc(BitWidth).sextOrTrunc(Value.bitWidth())); else - Result.copy(Value.toAPSInt() - .trunc(F->Decl->getBitWidthValue()) - .zextOrTrunc(Value.bitWidth())); + Result.copy( + Value.toAPSInt().trunc(BitWidth).zextOrTrunc(Value.bitWidth())); Field.deref<T>() = Result; } else { diff --git a/clang/test/AST/ByteCode/intap.cpp b/clang/test/AST/ByteCode/intap.cpp index efb60cb0abffe..804b16484ca01 100644 --- a/clang/test/AST/ByteCode/intap.cpp +++ b/clang/test/AST/ByteCode/intap.cpp @@ -102,6 +102,19 @@ namespace PointerArithmeticOverflow { // both-note {{cannot refer to element 3402}} } +namespace BitfieldWidth { + struct S { + __int128 foo : 1234; +#if !defined(_WIN32) + // both-warning@-2 {{width of bit-field 'foo' (1'234 bits) exceeds the width of its type; value will be truncated to 128 bits}} +#else + // both-error@-4 {{width of bit-field 'foo' (1234 bits) exceeds the size of its type (128 bits)}} +#endif + }; + constexpr S s{100}; + static_assert(s.foo == 100, ""); +} + namespace i128 { constexpr int128_t I128_1 = 12; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
