https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/180536
>From 999fc5ed918fa57e469e901b77d8fc55e87e575f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <[email protected]> Date: Mon, 9 Feb 2026 16:03:11 +0100 Subject: [PATCH] [clang][bytecode] Don't use trunc() to increase APInt bitWidth `FieldDecl::getBitWidthValue()` can return a value higher than the type size of the bit field. We need to account for that. --- clang/lib/AST/ByteCode/Interp.h | 26 ++++++++++++-------------- clang/test/AST/ByteCode/intap.cpp | 13 +++++++++++++ 2 files changed, 25 insertions(+), 14 deletions(-) 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
