[clang] [clang][bytecode] Don't use trunc() to increase APInt bitWidth (PR #180536)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 9 20:23:51 PST 2026
https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/180536
>From 8400379bd1e180c26fd39f91e9a695bafe190060 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
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 | 8 ++++++++
2 files changed, 20 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..d5e307790d94d 100644
--- a/clang/test/AST/ByteCode/intap.cpp
+++ b/clang/test/AST/ByteCode/intap.cpp
@@ -102,6 +102,14 @@ namespace PointerArithmeticOverflow {
// both-note {{cannot refer to element 3402}}
}
+namespace BitfieldWidth {
+ struct S {
+ __int128 foo : 1234; // both-warning {{width of bit-field 'foo'}}
+ };
+ 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