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?= <[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 |  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;

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to