From: Bevin Hansson Date: Tue, 30 Jun 2020 11:35:29 +0000 (+0200) Subject: [AST] Fix handling of some edge cases in fixed-point division. X-Git-Tag: llvmorg-12-init~1499 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=33bae9c265486cd37e0612711a863f0a4b865a26;p=platform%2Fupstream%2Fllvm.git [AST] Fix handling of some edge cases in fixed-point division. Division by zero was not being handled, and division of -EPSILON / MAX did not perform rounding correctly. --- diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp index ebe09c9..9eba40c 100644 --- a/clang/lib/AST/ExprConstant.cpp +++ b/clang/lib/AST/ExprConstant.cpp @@ -12954,6 +12954,10 @@ bool FixedPointExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) { break; } case BO_Div: { + if (RHSFX.getValue() == 0) { + Info.FFDiag(E, diag::note_expr_divide_by_zero); + return false; + } Result = LHSFX.div(RHSFX, &OpOverflow) .convert(ResultFXSema, &ConversionOverflow); break; diff --git a/clang/lib/Basic/FixedPoint.cpp b/clang/lib/Basic/FixedPoint.cpp index e8db43c..ed8b92c 100644 --- a/clang/lib/Basic/FixedPoint.cpp +++ b/clang/lib/Basic/FixedPoint.cpp @@ -282,7 +282,7 @@ APFixedPoint APFixedPoint::div(const APFixedPoint &Other, llvm::APInt::sdivrem(ThisVal, OtherVal, Result, Rem); // If the quotient is negative and the remainder is nonzero, round // towards negative infinity by subtracting epsilon from the result. - if (Result.isNegative() && !Rem.isNullValue()) + if (ThisVal.isNegative() != OtherVal.isNegative() && !Rem.isNullValue()) Result = Result - 1; } else Result = ThisVal.udiv(OtherVal); diff --git a/clang/test/Frontend/fixed_point_div.c b/clang/test/Frontend/fixed_point_div.c index ce1e023..b18ba59 100644 --- a/clang/test/Frontend/fixed_point_div.c +++ b/clang/test/Frontend/fixed_point_div.c @@ -64,6 +64,8 @@ short _Accum sa_const13 = 0.0234375hk / 2.0hk; // CHECK-DAG: @sa_const13 = {{.*}}global i16 1, align 2 short _Accum sa_const14 = -0.0234375hk / 2.0hk; // CHECK-DAG: @sa_const14 = {{.*}}global i16 -2, align 2 +short _Accum sa_const15 = -0.0078125hk / 255.28125hk; +// CHECK-DAG: @sa_const15 = {{.*}}global i16 -1, align 2 void SignedDivision() { // CHECK-LABEL: SignedDivision diff --git a/clang/test/Frontend/fixed_point_errors.c b/clang/test/Frontend/fixed_point_errors.c index c1d80d5..2fd8cfd 100644 --- a/clang/test/Frontend/fixed_point_errors.c +++ b/clang/test/Frontend/fixed_point_errors.c @@ -264,3 +264,6 @@ short _Fract add_sat = (_Sat short _Fract)0.5hr + 0.5hr; short _Accum sub_sat = (_Sat short _Accum)-200.0hk - 80.0hk; short _Accum mul_sat = (_Sat short _Accum)80.0hk * 10.0hk; short _Fract div_sat = (_Sat short _Fract)0.9hr / 0.1hr; + +// Division by zero +short _Accum div_zero = 4.5k / 0.0lr; // expected-error {{initializer element is not a compile-time constant}}