[clang] 555399d - [clang][bytecode] Fix shifting negative values (#104663)

via cfe-commits cfe-commits at lists.llvm.org
Sat Aug 17 13:57:22 PDT 2024


Author: Timm Baeder
Date: 2024-08-17T22:57:19+02:00
New Revision: 555399d562201f3114fb22f883cd1b6710af1a0d

URL: https://github.com/llvm/llvm-project/commit/555399d562201f3114fb22f883cd1b6710af1a0d
DIFF: https://github.com/llvm/llvm-project/commit/555399d562201f3114fb22f883cd1b6710af1a0d.diff

LOG: [clang][bytecode] Fix shifting negative values (#104663)

Added: 
    

Modified: 
    clang/lib/AST/ByteCode/Interp.h
    clang/test/AST/ByteCode/cxx23.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index c3ce21cb13770e..9891e3dba0d309 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -2354,6 +2354,17 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
                                  LT::AsUnsigned::from(RHS, Bits), Bits, &R);
   }
 
+  // We did the shift above as unsigned. Restore the sign bit if we need to.
+  if constexpr (Dir == ShiftDir::Right) {
+    if (LHS.isSigned() && LHS.isNegative()) {
+      typename LT::AsUnsigned SignBit;
+      LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits),
+                                LT::AsUnsigned::from(Bits - 1, Bits), Bits,
+                                &SignBit);
+      LT::AsUnsigned::bitOr(R, SignBit, Bits, &R);
+    }
+  }
+
   S.Stk.push<LT>(LT::from(R));
   return true;
 }

diff  --git a/clang/test/AST/ByteCode/cxx23.cpp b/clang/test/AST/ByteCode/cxx23.cpp
index eb05a9fda0dfb1..756eec5b825605 100644
--- a/clang/test/AST/ByteCode/cxx23.cpp
+++ b/clang/test/AST/ByteCode/cxx23.cpp
@@ -224,3 +224,17 @@ namespace ExplicitLambdaInstancePointer {
       static_assert(fp(1) == 1, "");
   }
 }
+
+namespace TwosComplementShifts {
+  using uint32 = __UINT32_TYPE__;
+  using int32 = __INT32_TYPE__;
+  static_assert(uint32(int32(0x1234) << 16) == 0x12340000);
+  static_assert(uint32(int32(0x1234) << 19) == 0x91a00000);
+  static_assert(uint32(int32(0x1234) << 20) == 0x23400000);
+  static_assert(uint32(int32(0x1234) << 24) == 0x34000000);
+  static_assert(uint32(int32(-1) << 31) == 0x80000000);
+
+  static_assert(-2 >> 1 == -1);
+  static_assert(-3 >> 1 == -2);
+  static_assert(-7 >> 1 == -4);
+}


        


More information about the cfe-commits mailing list