[clang] 461e433 - [clang][bytecode] Don't use trunc() to increase APInt bitWidth (#180536)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 9 22:53:27 PST 2026
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 at -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 at -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;
More information about the cfe-commits
mailing list