Re: [PATCH,Fortran] -- Check for overflow integer exponentation

2019-06-14 Thread Jerry DeLisle

On 6/14/19 3:56 PM, Steve Kargl wrote:

I have had this patch in my tree since the beginning of May.
During constant folding, gfortran would not issue an error
for overflow for integer exponentation.  Bootstrapped
and regression tested multiple times on x86_64-*-freebsd?
OK to commit?

2019-06-15  Steven G. Kargl  

* arith.c (arith_power): Rework overflow of an integer to an integer
exponent.

2019-06-15  Steven G. Kargl  

* gfortran.dg/integer_exponentiation_4.f90: Update test.
* gfortran.dg/integer_exponentiation_5.F90: Ditto.
* gfortran.dg/no_range_check_1.f90: Ditto.



OK, thanks Steve


[PATCH,Fortran] -- Check for overflow integer exponentation

2019-06-14 Thread Steve Kargl
I have had this patch in my tree since the beginning of May.  
During constant folding, gfortran would not issue an error
for overflow for integer exponentation.  Bootstrapped 
and regression tested multiple times on x86_64-*-freebsd?
OK to commit?

2019-06-15  Steven G. Kargl  

* arith.c (arith_power): Rework overflow of an integer to an integer
exponent.

2019-06-15  Steven G. Kargl  

* gfortran.dg/integer_exponentiation_4.f90: Update test.
* gfortran.dg/integer_exponentiation_5.F90: Ditto.
* gfortran.dg/no_range_check_1.f90: Ditto.

-- 
Steve
Index: gcc/fortran/arith.c
===
--- gcc/fortran/arith.c	(revision 269260)
+++ gcc/fortran/arith.c	(working copy)
@@ -848,8 +848,6 @@ arith_power (gfc_expr *op1, gfc_expr *op2, gfc_expr **
 	{
 	case BT_INTEGER:
 	  {
-		int power;
-
 		/* First, we simplify the cases of op1 == 1, 0 or -1.  */
 		if (mpz_cmp_si (op1->value.integer, 1) == 0)
 		  {
@@ -884,29 +882,36 @@ arith_power (gfc_expr *op1, gfc_expr *op2, gfc_expr **
    "exponent of integer has zero "
    "result at %L", &result->where);
 		  }
-		else if (gfc_extract_int (op2, &power))
+		else
 		  {
-		/* If op2 doesn't fit in an int, the exponentiation will
-		   overflow, because op2 > 0 and abs(op1) > 1.  */
-		mpz_t max;
-		int i;
-		i = gfc_validate_kind (BT_INTEGER, result->ts.kind, false);
+		/* We have abs(op1) > 1 and op2 > 1.
+		   If op2 > bit_size(op1), we'll have an out-of-range
+		   result.  */
+		int k, power;
 
-		if (flag_range_check)
-		  rc = ARITH_OVERFLOW;
-
-		/* Still, we want to give the same value as the
-		   processor.  */
-		mpz_init (max);
-		mpz_add_ui (max, gfc_integer_kinds[i].huge, 1);
-		mpz_mul_ui (max, max, 2);
-		mpz_powm (result->value.integer, op1->value.integer,
-			  op2->value.integer, max);
-		mpz_clear (max);
+		k = gfc_validate_kind (BT_INTEGER, op1->ts.kind, false);
+		power = gfc_integer_kinds[k].bit_size;
+		if (mpz_cmp_si (op2->value.integer, power) < 0)
+		  {
+			gfc_extract_int (op2, &power);
+			mpz_pow_ui (result->value.integer, op1->value.integer,
+power);
+			rc = gfc_range_check (result);
+			if (rc == ARITH_OVERFLOW)
+			  gfc_error_now ("Result of exponentiation at %L "
+	 "exceeds the range of %s", &op1->where,
+	 gfc_typename (&(op1->ts)));
+		  }
+		else
+		  {
+			/* Provide a nonsense value to propagate up. */
+			mpz_set (result->value.integer,
+ gfc_integer_kinds[k].huge);
+			mpz_add_ui (result->value.integer,
+result->value.integer, 1);
+			rc = ARITH_OVERFLOW;
+		  }
 		  }
-		else
-		  mpz_pow_ui (result->value.integer, op1->value.integer,
-			  power);
 	  }
 	  break;
 
Index: gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90
===
--- gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90	(revision 269260)
+++ gcc/testsuite/gfortran.dg/integer_exponentiation_4.f90	(working copy)
@@ -21,10 +21,10 @@ program test
   print *, (-1)**huge(0_8)
   print *, (-1)**(-huge(0_8)-1_8)
 
-  print *, 2**huge(0) ! { dg-error "Arithmetic overflow" }
-  print *, 2**huge(0_8) ! { dg-error "Arithmetic overflow" }
-  print *, (-2)**huge(0) ! { dg-error "Arithmetic overflow" }
-  print *, (-2)**huge(0_8) ! { dg-error "Arithmetic overflow" }
+  print *, 2**huge(0) ! { dg-error "Arithmetic overflow|exceeds the range" }
+  print *, 2**huge(0_8) ! { dg-error "Arithmetic overflow|exceeds the range" }
+  print *, (-2)**huge(0) ! { dg-error "Arithmetic overflow|exceeds the range" }
+  print *, (-2)**huge(0_8) ! { dg-error "Arithmetic overflow|exceeds the range" }
 
   print *, 2**(-huge(0)-1)
   print *, 2**(-huge(0_8)-1_8)
Index: gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90
===
--- gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90	(revision 269260)
+++ gcc/testsuite/gfortran.dg/integer_exponentiation_5.F90	(working copy)
@@ -67,8 +67,6 @@ program test
   TEST(3_8,43_8,i8)
   TEST(-3_8,43_8,i8)
 
-  TEST(17_8,int(huge(0_4),kind=8)+1,i8)
-
 ! REAL BASE !
   TEST(0.0,-1,r4)
   TEST(0.0,-huge(0)-1,r4)
Index: gcc/testsuite/gfortran.dg/no_range_check_1.f90
===
--- gcc/testsuite/gfortran.dg/no_range_check_1.f90	(revision 269260)
+++ gcc/testsuite/gfortran.dg/no_range_check_1.f90	(working copy)
@@ -4,11 +4,8 @@
 ! This testcase arose from PR 31262
   integer :: a
   integer(kind=8) :: b
-  a = -3
   b = -huge(b) / 7
-  a = a ** 73
   b = 7894_8 * b - 78941_8
-  if ((-3)**73 /= a) STOP 1
   if (7894_8 * (-huge(b) / 7) - 78941_8 /= b) STOP 2
 
   a = 1234789786453123