[gcc/devel/omp/gcc-9] Catch division by zero errors in array sizes.

Tobias Burnus burnus@gcc.gnu.org
Thu Mar 5 14:36:00 GMT 2020


https://gcc.gnu.org/g:2f25907603e2a26ba3e5d76880d31ce25d1f0ae7

commit 2f25907603e2a26ba3e5d76880d31ce25d1f0ae7
Author: Thomas Koenig <tkoenig@gcc.gnu.org>
Date:   Mon Dec 30 13:10:37 2019 +0000

    Catch division by zero errors in array sizes.
    
    2019-12-30  Thomas Koenig  <tkoenig@gcc.gnu.org>
    
    	Backport from trunk
    	PR fortran/92961
    	* gfortran.h (gfc_seen_div0): Add declaration.
    	* arith.h (gfc_seen_div0): Add definition.
    	(eval_intrinsic): For integer division by zero, set gfc_seen_div0.
    	* decl.c (variable_decl):  If resolution resp. simplification
    	fails for array spec and a division of zero error has been
    	seen, return MATCH_ERROR.
    
    2019-12-30  Thomas Koenig  <tkoenig@gcc.gnu.org>
    
    	Backport from trunk
    	PR fortran/92961
    	* gfortran.dg/arith_divide_2.f90: New test.
    
    From-SVN: r279767

Diff:
---
 gcc/fortran/arith.c                          |  6 ++++++
 gcc/fortran/decl.c                           | 31 ++++++++++++++++++++++++----
 gcc/fortran/gfortran.h                       |  2 ++
 gcc/testsuite/gfortran.dg/arith_divide_2.f90 |  9 ++++++++
 4 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index a4f8795..8c02504 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -32,6 +32,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "target-memory.h"
 #include "constructor.h"
 
+bool gfc_seen_div0;
+
 /* MPFR does not have a direct replacement for mpz_set_f() from GMP.
    It's easily implemented with a few calls though.  */
 
@@ -1620,6 +1622,10 @@ eval_intrinsic (gfc_intrinsic_op op,
       gfc_error (gfc_arith_error (rc), &op1->where);
       if (rc == ARITH_OVERFLOW)
 	goto done;
+
+      if (rc == ARITH_DIV0 && op2->ts.type == BT_INTEGER)
+	gfc_seen_div0 = true;
+
       return NULL;
     }
 
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index 52a98cd..053f783 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2511,6 +2511,8 @@ variable_decl (int elem)
 	  goto cleanup;
 	}
 
+      gfc_seen_div0 = false;
+      
       /* F2018:C830 (R816) An explicit-shape-spec whose bounds are not
 	 constant expressions shall appear only in a subprogram, derived
 	 type definition, BLOCK construct, or interface body.  */
@@ -2527,7 +2529,12 @@ variable_decl (int elem)
 	  for (int i = 0; i < as->rank; i++)
 	    {
 	      e = gfc_copy_expr (as->lower[i]);
-	      gfc_resolve_expr (e);
+	      if (!gfc_resolve_expr (e) && gfc_seen_div0)
+		{
+		  m = MATCH_ERROR;
+		  goto cleanup;
+		}
+
 	      gfc_simplify_expr (e, 0);
 	      if (e && (e->expr_type != EXPR_CONSTANT))
 		{
@@ -2537,7 +2544,12 @@ variable_decl (int elem)
 	      gfc_free_expr (e);
 
 	      e = gfc_copy_expr (as->upper[i]);
-	      gfc_resolve_expr (e);
+	      if (!gfc_resolve_expr (e)  && gfc_seen_div0)
+		{
+		  m = MATCH_ERROR;
+		  goto cleanup;
+		}
+
 	      gfc_simplify_expr (e, 0);
 	      if (e && (e->expr_type != EXPR_CONSTANT))
 		{
@@ -2563,7 +2575,12 @@ variable_decl (int elem)
 	      if (e->expr_type != EXPR_CONSTANT)
 		{
 		  n = gfc_copy_expr (e);
-		  gfc_simplify_expr (n, 1);
+		  if (!gfc_simplify_expr (n, 1)  && gfc_seen_div0) 
+		    {
+		      m = MATCH_ERROR;
+		      goto cleanup;
+		    }
+
 		  if (n->expr_type == EXPR_CONSTANT)
 		    gfc_replace_expr (e, n);
 		  else
@@ -2573,7 +2590,12 @@ variable_decl (int elem)
 	      if (e->expr_type != EXPR_CONSTANT)
 		{
 		  n = gfc_copy_expr (e);
-		  gfc_simplify_expr (n, 1);
+		  if (!gfc_simplify_expr (n, 1)  && gfc_seen_div0) 
+		    {
+		      m = MATCH_ERROR;
+		      goto cleanup;
+		    }
+		  
 		  if (n->expr_type == EXPR_CONSTANT)
 		    gfc_replace_expr (e, n);
 		  else
@@ -2910,6 +2932,7 @@ variable_decl (int elem)
 
 cleanup:
   /* Free stuff up and return.  */
+  gfc_seen_div0 = false;
   gfc_free_expr (initializer);
   gfc_free_array_spec (as);
 
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 29b962d..d7071ae 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2967,6 +2967,8 @@ void gfc_arith_done_1 (void);
 arith gfc_check_integer_range (mpz_t p, int kind);
 bool gfc_check_character_range (gfc_char_t, int);
 
+extern bool gfc_seen_div0;
+
 /* trans-types.c */
 bool gfc_check_any_c_kind (gfc_typespec *);
 int gfc_validate_kind (bt, int, bool);
diff --git a/gcc/testsuite/gfortran.dg/arith_divide_2.f90 b/gcc/testsuite/gfortran.dg/arith_divide_2.f90
new file mode 100644
index 0000000..ffafa26
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/arith_divide_2.f90
@@ -0,0 +1,9 @@
+! { dg-do compile }
+! PR 92961 - this used to ICE. Original test case by Gerhard Steinmetz.
+program p
+   integer :: a((0)/0)    ! { dg-error "Division by zero" }
+   integer :: b(0/(0))    ! { dg-error "Division by zero" }
+   integer :: c((0)/(0))  ! { dg-error "Division by zero" }
+   integer :: d(0/0)      ! { dg-error "Division by zero" }
+   integer :: x = ubound(a,1) ! { dg-error "must be an array" }
+end



More information about the Gcc-cvs mailing list