Index: clang/lib/AST/Interp/Integral.h =================================================================== --- clang/lib/AST/Interp/Integral.h +++ clang/lib/AST/Interp/Integral.h @@ -233,6 +233,18 @@ return false; } + template + static void shiftLeft(const Integral A, const Integral B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V << B.V, OpBits); + } + + template + static void shiftRight(const Integral A, const Integral B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V >> B.V, OpBits); + } + private: template static bool CheckAddUB(T A, T B, T &R) { if constexpr (std::is_signed_v) { Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1357,8 +1357,9 @@ if (!CheckShift(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast(RHS); - S.Stk.push(LT::from(static_cast(LHS) >> URHS, LHS.bitWidth())); + Integral R; + Integral::shiftRight(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push(R); return true; } @@ -1373,9 +1374,9 @@ if (!CheckShift(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast(RHS); - S.Stk.push(LT::from(static_cast(LHS) << URHS, LHS.bitWidth())); - + Integral R; + Integral::shiftLeft(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push(R); return true; } Index: clang/test/AST/Interp/shifts.cpp =================================================================== --- clang/test/AST/Interp/shifts.cpp +++ clang/test/AST/Interp/shifts.cpp @@ -143,4 +143,9 @@ constexpr char c2 = 1; constexpr int i3 = c2 << (__CHAR_BIT__ + 1); // Not ill-formed + + constexpr signed long int L = 1; + constexpr signed int R = 62; + constexpr decltype(L) M = L << R; + constexpr decltype(L) M2 = L >> R; };