Skip to content

Commit 555399d

Browse files
authored
[clang][bytecode] Fix shifting negative values (#104663)
1 parent b21b907 commit 555399d

File tree

2 files changed

+25
-0
lines changed

2 files changed

+25
-0
lines changed

clang/lib/AST/ByteCode/Interp.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,6 +2354,17 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) {
23542354
LT::AsUnsigned::from(RHS, Bits), Bits, &R);
23552355
}
23562356

2357+
// We did the shift above as unsigned. Restore the sign bit if we need to.
2358+
if constexpr (Dir == ShiftDir::Right) {
2359+
if (LHS.isSigned() && LHS.isNegative()) {
2360+
typename LT::AsUnsigned SignBit;
2361+
LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(1, Bits),
2362+
LT::AsUnsigned::from(Bits - 1, Bits), Bits,
2363+
&SignBit);
2364+
LT::AsUnsigned::bitOr(R, SignBit, Bits, &R);
2365+
}
2366+
}
2367+
23572368
S.Stk.push<LT>(LT::from(R));
23582369
return true;
23592370
}

clang/test/AST/ByteCode/cxx23.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,3 +224,17 @@ namespace ExplicitLambdaInstancePointer {
224224
static_assert(fp(1) == 1, "");
225225
}
226226
}
227+
228+
namespace TwosComplementShifts {
229+
using uint32 = __UINT32_TYPE__;
230+
using int32 = __INT32_TYPE__;
231+
static_assert(uint32(int32(0x1234) << 16) == 0x12340000);
232+
static_assert(uint32(int32(0x1234) << 19) == 0x91a00000);
233+
static_assert(uint32(int32(0x1234) << 20) == 0x23400000);
234+
static_assert(uint32(int32(0x1234) << 24) == 0x34000000);
235+
static_assert(uint32(int32(-1) << 31) == 0x80000000);
236+
237+
static_assert(-2 >> 1 == -1);
238+
static_assert(-3 >> 1 == -2);
239+
static_assert(-7 >> 1 == -4);
240+
}

0 commit comments

Comments
 (0)