PR fortran/93499 - ICE on division by zero in declaration statements

Message ID trinity-f86e15b9-80ce-449c-b869-c537ae44cfd4-1589050375174@3c-app-gmx-bap45
State New
Headers show
Series
  • PR fortran/93499 - ICE on division by zero in declaration statements
Related show

Commit Message

Harald Anlauf May 9, 2020, 6:52 p.m.
Hi,

the attached should be mostly self-explaining.  Division by zero handling
appeared to be incomplete.  It was not dealt with properly when occurring
in declaration statements.  We now try to handle this.

OK for mainline?

Thanks,
Harald



PR fortran/93499 - ICE on division by zero in declaration statements

	Division by zero in declaration statements could sometimes
	generate NULL pointers being passed around that lead to ICEs.

gcc/fortran/ChangeLog:

2020-05-09  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/93499
	* arith.c (gfc_divide): Catch division by zero.
	(eval_intrinsic_f3): Safeguard for NULL operands.

gcc/testsuite/ChangeLog:

2020-05-09  Harald Anlauf  <anlauf@gmx.de>

	PR fortran/93499
	* gfortran.dg/pr93499.f90: New test.

Comments

Jakub Jelinek via Gcc-patches May 10, 2020, 7:13 a.m. | #1
Hi Harald,

> the attached should be mostly self-explaining.  Division by zero handling

> appeared to be incomplete.  It was not dealt with properly when occurring

> in declaration statements.  We now try to handle this.

> 

> OK for mainline?


OK.

Thanks for the patch!

Regards

	Thomas

Patch

diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index 422ef40c431..1cd0867a941 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -1746,6 +1746,9 @@  eval_intrinsic_f3 (gfc_intrinsic_op op,
   gfc_expr *result;
   eval_f f;

+  if (!op1 && !op2)
+    return NULL;
+
   result = reduce_binary0 (op1, op2);
   if (result != NULL)
     return eval_type_intrinsic0(op, result);
@@ -1803,6 +1806,37 @@  gfc_multiply (gfc_expr *op1, gfc_expr *op2)
 gfc_expr *
 gfc_divide (gfc_expr *op1, gfc_expr *op2)
 {
+  if (op2 && op2->expr_type == EXPR_CONSTANT)
+    {
+      arith rc = ARITH_OK;
+      switch (op2->ts.type)
+	{
+	case BT_INTEGER:
+	  /* non-integer divided by integer 0 is handled elsewhere.  */
+	  if (mpz_sgn (op2->value.integer) == 0
+	      && op1->ts.type == BT_INTEGER)
+	    rc = ARITH_DIV0;
+	  break;
+	case BT_REAL:
+	  if (mpfr_sgn (op2->value.real) == 0
+	      && flag_range_check == 1)
+	    rc = ARITH_DIV0;
+	  break;
+	case BT_COMPLEX:
+	  if (mpc_cmp_si_si (op2->value.complex, 0, 0) == 0
+	      && flag_range_check == 1)
+	    rc = ARITH_DIV0;
+	  break;
+	default:
+	  gfc_internal_error ("gfc_divide(): Bad basic type");
+	}
+      if (rc == ARITH_DIV0)
+	{
+	  gfc_seen_div0 = true;
+	  gfc_error ("Division by zero at %L", &op2->where);
+	  return NULL;
+	}
+    }
   return eval_intrinsic_f3 (INTRINSIC_DIVIDE, gfc_arith_divide, op1, op2);
 }

diff --git a/gcc/testsuite/gfortran.dg/pr93499.f90 b/gcc/testsuite/gfortran.dg/pr93499.f90
new file mode 100644
index 00000000000..7a414bb6016
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr93499.f90
@@ -0,0 +1,10 @@ 
+! { dg-do compile }
+! PR 93499 - this used to ICE. Original test case by Gerhard Steinmetz.
+
+program p
+  integer :: a((0.)/0)  ! { dg-error "Division by zero" }
+  type t(n)
+     integer, len :: n
+  end type t
+  type(t((0)/0))  :: x  ! { dg-error "Division by zero" }
+end