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

Reply via email to