aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorThomas Koenig <tkoenig@gcc.gnu.org>2019-12-30 10:34:11 +0000
committerThomas Koenig <tkoenig@gcc.gnu.org>2019-12-30 10:34:11 +0000
commit672511187345d30ccd725214ac4b34b181bd6569 (patch)
tree4dd5ef16a039f4e241f8d2222b19e3661cd794a5 /gcc
parentc3182576ea48f175283e291094298831dd7046e5 (diff)
downloadgcc-672511187345d30ccd725214ac4b34b181bd6569.zip
gcc-672511187345d30ccd725214ac4b34b181bd6569.tar.gz
gcc-672511187345d30ccd725214ac4b34b181bd6569.tar.bz2
Catch division by zero errors in array sizes.
2019-12-30 Thomas Koenig <tkoenig@gcc.gnu.org> 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> PR fortran/92961 * gfortran.dg/arith_divide_2.f90: New test. From-SVN: r279762
Diffstat (limited to 'gcc')
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/arith.c6
-rw-r--r--gcc/fortran/decl.c31
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gfortran.dg/arith_divide_2.f909
6 files changed, 59 insertions, 4 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 63a6de6..5b92597 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2019-12-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ 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-21 Harald Anlauf <anlauf@gmx.de>
PR fortran/92990
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index 7f048da..b7699e4 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 affdbf6..b43dc2c 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -2535,6 +2535,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. */
@@ -2551,7 +2553,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))
{
@@ -2561,7 +2568,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))
{
@@ -2587,7 +2599,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
@@ -2597,7 +2614,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
@@ -2934,6 +2956,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 b38238a..8e414c4 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2995,6 +2995,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/ChangeLog b/gcc/testsuite/ChangeLog
index dcc0ec9..d704451 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-12-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/92961
+ * gfortran.dg/arith_divide_2.f90: New test.
+
2019-12-30 Jakub Jelinek <jakub@redhat.com>
PR c++/92745
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