tbaeder created this revision. tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik. Herald added a project: All. tbaeder requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
We were just casting to `unsigned` before, so that caused problems when shifting more bits than `unsigned` has. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D140845 Files: clang/lib/AST/Interp/Integral.h clang/lib/AST/Interp/Interp.h clang/test/AST/Interp/shifts.cpp Index: clang/test/AST/Interp/shifts.cpp =================================================================== --- clang/test/AST/Interp/shifts.cpp +++ clang/test/AST/Interp/shifts.cpp @@ -143,4 +143,8 @@ 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; }; Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1321,8 +1321,9 @@ if (!CheckShift<RT>(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast<unsigned>(RHS); - S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) >> URHS, LHS.bitWidth())); + Integral<LT::bitWidth(), false> R; + Integral<LT::bitWidth(), false>::shiftRight(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push<LT>(R); return true; } @@ -1337,9 +1338,9 @@ if (!CheckShift<RT>(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast<unsigned>(RHS); - S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) << URHS, LHS.bitWidth())); - + Integral<LT::bitWidth(), false> R; + Integral<LT::bitWidth(), false>::shiftLeft(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push<LT>(R); return true; } Index: clang/lib/AST/Interp/Integral.h =================================================================== --- clang/lib/AST/Interp/Integral.h +++ clang/lib/AST/Interp/Integral.h @@ -241,6 +241,18 @@ return false; } + template <unsigned RHSBits, bool RHSSign> + static void shiftLeft(const Integral A, const Integral<RHSBits, RHSSign> B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V << B.V, OpBits); + } + + template <unsigned RHSBits, bool RHSSign> + static void shiftRight(const Integral A, const Integral<RHSBits, RHSSign> B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V >> B.V, OpBits); + } + private: template <typename T> static bool CheckAddUB(T A, T B, T &R) { if constexpr (std::is_signed_v<T>) {
Index: clang/test/AST/Interp/shifts.cpp =================================================================== --- clang/test/AST/Interp/shifts.cpp +++ clang/test/AST/Interp/shifts.cpp @@ -143,4 +143,8 @@ 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; }; Index: clang/lib/AST/Interp/Interp.h =================================================================== --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1321,8 +1321,9 @@ if (!CheckShift<RT>(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast<unsigned>(RHS); - S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) >> URHS, LHS.bitWidth())); + Integral<LT::bitWidth(), false> R; + Integral<LT::bitWidth(), false>::shiftRight(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push<LT>(R); return true; } @@ -1337,9 +1338,9 @@ if (!CheckShift<RT>(S, OpPC, RHS, Bits)) return false; - unsigned URHS = static_cast<unsigned>(RHS); - S.Stk.push<LT>(LT::from(static_cast<unsigned>(LHS) << URHS, LHS.bitWidth())); - + Integral<LT::bitWidth(), false> R; + Integral<LT::bitWidth(), false>::shiftLeft(LHS.toUnsigned(), RHS, Bits, &R); + S.Stk.push<LT>(R); return true; } Index: clang/lib/AST/Interp/Integral.h =================================================================== --- clang/lib/AST/Interp/Integral.h +++ clang/lib/AST/Interp/Integral.h @@ -241,6 +241,18 @@ return false; } + template <unsigned RHSBits, bool RHSSign> + static void shiftLeft(const Integral A, const Integral<RHSBits, RHSSign> B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V << B.V, OpBits); + } + + template <unsigned RHSBits, bool RHSSign> + static void shiftRight(const Integral A, const Integral<RHSBits, RHSSign> B, + unsigned OpBits, Integral *R) { + *R = Integral::from(A.V >> B.V, OpBits); + } + private: template <typename T> static bool CheckAddUB(T A, T B, T &R) { if constexpr (std::is_signed_v<T>) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits