llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Timm Baeder (tbaederr) <details> <summary>Changes</summary> We used to incorrectly diagnose this as a "left shift of negative value". --- Full diff: https://github.com/llvm/llvm-project/pull/108987.diff 2 Files Affected: - (modified) clang/lib/AST/ByteCode/Interp.h (+19-16) - (modified) clang/test/AST/ByteCode/shifts.cpp (+1) ``````````diff diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h index 3d507e2e2ba764..52ccefee88642a 100644 --- a/clang/lib/AST/ByteCode/Interp.h +++ b/clang/lib/AST/ByteCode/Interp.h @@ -159,8 +159,10 @@ bool CallBI(InterpState &S, CodePtr OpPC, const Function *Func, bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize, const CallExpr *CE); +enum class ShiftDir { Left, Right }; + /// Checks if the shift operation is legal. -template <typename LT, typename RT> +template <ShiftDir Dir, typename LT, typename RT> bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, unsigned Bits) { if (RHS.isNegative()) { @@ -181,19 +183,21 @@ bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS, return false; } - if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) { - const Expr *E = S.Current->getExpr(OpPC); - // C++11 [expr.shift]p2: A signed left shift must have a non-negative - // operand, and must not overflow the corresponding unsigned type. - if (LHS.isNegative()) { - S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt(); - if (!S.noteUndefinedBehavior()) - return false; - } else if (LHS.toUnsigned().countLeadingZeros() < - static_cast<unsigned>(RHS)) { - S.CCEDiag(E, diag::note_constexpr_lshift_discards); - if (!S.noteUndefinedBehavior()) - return false; + if constexpr (Dir == ShiftDir::Left) { + if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) { + const Expr *E = S.Current->getExpr(OpPC); + // C++11 [expr.shift]p2: A signed left shift must have a non-negative + // operand, and must not overflow the corresponding unsigned type. + if (LHS.isNegative()) { + S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt(); + if (!S.noteUndefinedBehavior()) + return false; + } else if (LHS.toUnsigned().countLeadingZeros() < + static_cast<unsigned>(RHS)) { + S.CCEDiag(E, diag::note_constexpr_lshift_discards); + if (!S.noteUndefinedBehavior()) + return false; + } } } @@ -2394,7 +2398,6 @@ inline bool RVOPtr(InterpState &S, CodePtr OpPC) { //===----------------------------------------------------------------------===// // Shr, Shl //===----------------------------------------------------------------------===// -enum class ShiftDir { Left, Right }; template <class LT, class RT, ShiftDir Dir> inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) { @@ -2431,7 +2434,7 @@ inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS) { } } - if (!CheckShift(S, OpPC, LHS, RHS, Bits)) + if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits)) return false; // Limit the shift amount to Bits - 1. If this happened, diff --git a/clang/test/AST/ByteCode/shifts.cpp b/clang/test/AST/ByteCode/shifts.cpp index 360b87b7ee04f8..0b3383731c6774 100644 --- a/clang/test/AST/ByteCode/shifts.cpp +++ b/clang/test/AST/ByteCode/shifts.cpp @@ -5,6 +5,7 @@ #define INT_MIN (~__INT_MAX__) +constexpr int a = -1 >> 3; namespace shifts { constexpr void test() { // ref-error {{constexpr function never produces a constant expression}} \ `````````` </details> https://github.com/llvm/llvm-project/pull/108987 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits