diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h index c9a508448e314c..c7cf9b38386915 100644 --- a/clang/lib/AST/Interp/Interp.h +++ b/clang/lib/AST/Interp/Interp.h @@ -91,6 +91,27 @@ bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This); /// Checks if a method is pure virtual. bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD); +/// Checks if Div/Rem operation on LHS and RHS is valid. +template +bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) { + if (RHS.isZero()) { + const SourceInfo &Loc = S.Current->getSource(OpPC); + S.FFDiag(Loc, diag::note_expr_divide_by_zero); + return false; + } + + if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { + APSInt LHSInt = LHS.toAPSInt(); + SmallString<32> Trunc; + (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10); + const SourceInfo &Loc = S.Current->getSource(OpPC); + const Expr *E = S.Current->getExpr(OpPC); + S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType(); + return false; + } + return true; +} + template inline bool IsTrue(const T &V) { return !V.isZero(); } //===----------------------------------------------------------------------===// @@ -195,21 +216,8 @@ bool Rem(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop(); const T &LHS = S.Stk.pop(); - if (RHS.isZero()) { - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_expr_divide_by_zero); + if (!CheckDivRem(S, OpPC, LHS, RHS)) return false; - } - - if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { - APSInt LHSInt = LHS.toAPSInt(); - SmallString<32> Trunc; - (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10); - const SourceInfo &Loc = S.Current->getSource(OpPC); - const Expr *E = S.Current->getExpr(OpPC); - S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType(); - return false; - } const unsigned Bits = RHS.bitWidth() * 2; T Result; @@ -228,21 +236,8 @@ bool Div(InterpState &S, CodePtr OpPC) { const T &RHS = S.Stk.pop(); const T &LHS = S.Stk.pop(); - if (RHS.isZero()) { - const SourceInfo &Loc = S.Current->getSource(OpPC); - S.FFDiag(Loc, diag::note_expr_divide_by_zero); + if (!CheckDivRem(S, OpPC, LHS, RHS)) return false; - } - - if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) { - APSInt LHSInt = LHS.toAPSInt(); - SmallString<32> Trunc; - (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10); - const SourceInfo &Loc = S.Current->getSource(OpPC); - const Expr *E = S.Current->getExpr(OpPC); - S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType(); - return false; - } const unsigned Bits = RHS.bitWidth() * 2; T Result;