[AST] Fix handling of some edge cases in fixed-point division.
authorBevin Hansson <bevin.hansson@ericsson.com>
Tue, 30 Jun 2020 11:35:29 +0000 (13:35 +0200)
committerBevin Hansson <bevin.hansson@ericsson.com>
Tue, 30 Jun 2020 11:47:12 +0000 (13:47 +0200)
Division by zero was not being handled, and division of
-EPSILON / MAX did not perform rounding correctly.

clang/lib/AST/ExprConstant.cpp
clang/lib/Basic/FixedPoint.cpp
clang/test/Frontend/fixed_point_div.c
clang/test/Frontend/fixed_point_errors.c

index ebe09c9..9eba40c 100644 (file)
@@ -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;
index e8db43c..ed8b92c 100644 (file)
@@ -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);
index ce1e023..b18ba59 100644 (file)
@@ -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
index c1d80d5..2fd8cfd 100644 (file)
@@ -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}}