This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [Patch, Fortran] PR33745 - fix bound checking at run time (wrong code) and compile time (missing diagnostic)
- From: Tobias Burnus <burnus at net-b dot de>
- To: Tobias Schlüter <tobias dot schlueter at physik dot uni-muenchen dot de>
- Cc: gcc-patches <gcc-patches at gcc dot gnu dot org>, "'fortran at gcc dot gnu dot org'" <fortran at gcc dot gnu dot org>
- Date: Sun, 14 Oct 2007 22:26:37 +0200
- Subject: Re: [Patch, Fortran] PR33745 - fix bound checking at run time (wrong code) and compile time (missing diagnostic)
- References: <4711007E.1010804@net-b.de> <47126563.3050500@physik.uni-muenchen.de>
Tobias Schlüter wrote:
> Tobias Burnus wrote:
>> Build and regression tested on x86-64/Linux. OK for the trunk?
> This is ok. Extra points if you use the brief "(0 < 1)" in the
> runtime message as well. Except cluttering the screen and making the
> message harder to read, I see no benefits in printing "0 is smaller
> than 1", as is done currently.
Thanks. Committed at Rev. 129302.
Tobias
2007-10-14 Tobias Burnus <burnus@net-b.de>
PR fortran/33745
* trans-array.c (gfc_conv_ss_startstride): Fix dimension check.
(gfc_trans_array_bound_check, gfc_conv_array_ref,
gfc_conv_ss_startstride): Simplify error message.
* resolve.c (check_dimension): Fix dimension-type switch;
improve error message.
2007-10-14 Tobias Burnus <burnus@net-b.de>
PR fortran/33745
* gfortran.dg/bounds_check_11.f90: New.
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c (Revision 129284)
+++ gcc/fortran/resolve.c (Arbeitskopie)
@@ -3215,20 +3190,32 @@ check_dimension (int i, gfc_array_ref *a
/* Given start, end and stride values, calculate the minimum and
maximum referenced indexes. */
- switch (ar->type)
+ switch (ar->dimen_type[i])
{
- case AR_FULL:
+ case DIMEN_VECTOR:
break;
- case AR_ELEMENT:
+ case DIMEN_ELEMENT:
if (compare_bound (ar->start[i], as->lower[i]) == CMP_LT)
- goto bound;
+ {
+ gfc_warning ("Array reference at %L is out of bounds "
+ "(%ld < %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (ar->start[i]->value.integer),
+ mpz_get_si (as->lower[i]->value.integer), i+1);
+ return SUCCESS;
+ }
if (compare_bound (ar->start[i], as->upper[i]) == CMP_GT)
- goto bound;
+ {
+ gfc_warning ("Array reference at %L is out of bounds "
+ "(%ld > %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (ar->start[i]->value.integer),
+ mpz_get_si (as->upper[i]->value.integer), i+1);
+ return SUCCESS;
+ }
break;
- case AR_SECTION:
+ case DIMEN_RANGE:
{
#define AR_START (ar->start[i] ? ar->start[i] : as->lower[i])
#define AR_END (ar->end[i] ? ar->end[i] : as->upper[i])
@@ -3253,9 +3240,22 @@ check_dimension (int i, gfc_array_ref *a
|| (compare_bound_int (ar->stride[i], 0) == CMP_LT
&& comp_start_end == CMP_GT))
{
- if (compare_bound (AR_START, as->lower[i]) == CMP_LT
- || compare_bound (AR_START, as->upper[i]) == CMP_GT)
- goto bound;
+ if (compare_bound (AR_START, as->lower[i]) == CMP_LT)
+ {
+ gfc_warning ("Lower array reference at %L is out of bounds "
+ "(%ld < %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (AR_START->value.integer),
+ mpz_get_si (as->lower[i]->value.integer), i+1);
+ return SUCCESS;
+ }
+ if (compare_bound (AR_START, as->upper[i]) == CMP_GT)
+ {
+ gfc_warning ("Lower array reference at %L is out of bounds "
+ "(%ld > %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (AR_START->value.integer),
+ mpz_get_si (as->upper[i]->value.integer), i+1);
+ return SUCCESS;
+ }
}
/* If we can compute the highest index of the array section,
@@ -3264,11 +3264,23 @@ check_dimension (int i, gfc_array_ref *a
if (compute_last_value_for_triplet (AR_START, AR_END, ar->stride[i],
last_value))
{
- if (compare_bound_mpz_t (as->lower[i], last_value) == CMP_GT
- || compare_bound_mpz_t (as->upper[i], last_value) == CMP_LT)
+ if (compare_bound_mpz_t (as->lower[i], last_value) == CMP_GT)
+ {
+ gfc_warning ("Upper array reference at %L is out of bounds "
+ "(%ld < %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (last_value),
+ mpz_get_si (as->lower[i]->value.integer), i+1);
+ mpz_clear (last_value);
+ return SUCCESS;
+ }
+ if (compare_bound_mpz_t (as->upper[i], last_value) == CMP_LT)
{
+ gfc_warning ("Upper array reference at %L is out of bounds "
+ "(%ld > %ld) in dimension %d", &ar->c_where[i],
+ mpz_get_si (last_value),
+ mpz_get_si (as->upper[i]->value.integer), i+1);
mpz_clear (last_value);
- goto bound;
+ return SUCCESS;
}
}
mpz_clear (last_value);
@@ -3283,10 +3295,6 @@ check_dimension (int i, gfc_array_ref *a
}
return SUCCESS;
-
-bound:
- gfc_warning ("Array reference at %L is out of bounds", &ar->c_where[i]);
- return SUCCESS;
}
Index: gcc/testsuite/gfortran.dg/bounds_check_11.f90
===================================================================
--- gcc/testsuite/gfortran.dg/bounds_check_11.f90 (Revision 0)
+++ gcc/testsuite/gfortran.dg/bounds_check_11.f90 (Revision 0)
@@ -0,0 +1,25 @@
+! { dg-do run }
+! { dg-options "-fbounds-check" }
+! { dg-shouldfail "Array bound checking" }
+! PR fortran/33745
+!
+! Don't check upper bound of assumed-size array
+!
+
+program test
+ implicit none
+ integer, parameter :: maxss=7,maxc=8
+ integer :: jp(2,maxc)
+ call findphase(jp)
+contains
+ subroutine findphase(jp)
+ integer, intent(out) :: jp(2,*)
+ jp(2,2:4)=0
+ jp(2,0:4)=0 ! { dg-warning "out of bounds" }
+ jp(3,1:4)=0 ! { dg-warning "out of bounds" }
+ end subroutine
+end program test
+
+! { dg-output "At line 18 of file .*" }
+! { dg-output "Array reference out of bounds, lower bound of dimension 2 of array 'jp' exceeded, 0 is smaller than 1" }
+
Index: gcc/fortran/trans-array.c
===================================================================
--- gcc/fortran/trans-array.c (Revision 129301)
+++ gcc/fortran/trans-array.c (Arbeitskopie)
@@ -2109,11 +2109,11 @@ gfc_trans_array_bound_check (gfc_se * se
tmp = gfc_conv_array_lbound (descriptor, n);
fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
if (name)
- asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded",
- gfc_msg_fault, name, n+1);
+ asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
+ "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
else
- asprintf (&msg, "%s, lower bound of dimension %d exceeded, %%ld is "
- "smaller than %%ld", gfc_msg_fault, n+1);
+ asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
+ gfc_msg_fault, n+1);
gfc_trans_runtime_check (fault, &se->pre, where, msg,
fold_convert (long_integer_type_node, index),
fold_convert (long_integer_type_node, tmp));
@@ -2126,10 +2126,10 @@ gfc_trans_array_bound_check (gfc_se * se
fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
if (name)
asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
- " exceeded", gfc_msg_fault, name, n+1);
+ " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
else
- asprintf (&msg, "%s, upper bound of dimension %d exceeded, %%ld is "
- "larger than %%ld", gfc_msg_fault, n+1);
+ asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
+ gfc_msg_fault, n+1);
gfc_trans_runtime_check (fault, &se->pre, where, msg,
fold_convert (long_integer_type_node, index),
fold_convert (long_integer_type_node, tmp));
@@ -2323,8 +2323,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
cond = fold_build2 (LT_EXPR, boolean_type_node,
indexse.expr, tmp);
asprintf (&msg, "%s for array '%s', "
- "lower bound of dimension %d exceeded, %%ld is smaller "
- "than %%ld", gfc_msg_fault, sym->name, n+1);
+ "lower bound of dimension %d exceeded (%%ld < %%ld)",
+ gfc_msg_fault, sym->name, n+1);
gfc_trans_runtime_check (cond, &se->pre, where, msg,
fold_convert (long_integer_type_node,
indexse.expr),
@@ -2340,8 +2340,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_arr
cond = fold_build2 (GT_EXPR, boolean_type_node,
indexse.expr, tmp);
asprintf (&msg, "%s for array '%s', "
- "upper bound of dimension %d exceeded, %%ld is "
- "greater than %%ld", gfc_msg_fault, sym->name, n+1);
+ "upper bound of dimension %d exceeded (%%ld > %%ld)",
+ gfc_msg_fault, sym->name, n+1);
gfc_trans_runtime_check (cond, &se->pre, where, msg,
fold_convert (long_integer_type_node,
indexse.expr),
@@ -2888,7 +2888,7 @@ gfc_conv_ss_startstride (gfc_loopinfo *
if (info->ref->u.ar.dimen_type[dim] != DIMEN_RANGE)
continue;
- if (n == info->ref->u.ar.dimen - 1
+ if (dim == info->ref->u.ar.dimen - 1
&& (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
|| info->ref->u.ar.as->cp_was_assumed))
check_upper = false;
@@ -2941,7 +2941,7 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
- " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
+ " exceeded (%%ld < %%ld)", gfc_msg_fault,
info->dim[n]+1, ss->expr->symtree->name);
gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
fold_convert (long_integer_type_node,
@@ -2957,9 +2957,8 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, upper bound of dimension %d of array "
- "'%s' exceeded, %%ld is greater than %%ld",
- gfc_msg_fault, info->dim[n]+1,
- ss->expr->symtree->name);
+ "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
+ info->dim[n]+1, ss->expr->symtree->name);
gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
fold_convert (long_integer_type_node, info->start[n]),
fold_convert (long_integer_type_node, ubound));
@@ -2980,7 +2979,7 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
- " exceeded, %%ld is smaller than %%ld", gfc_msg_fault,
+ " exceeded (%%ld < %%ld)", gfc_msg_fault,
info->dim[n]+1, ss->expr->symtree->name);
gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
fold_convert (long_integer_type_node,
@@ -2995,9 +2994,8 @@ gfc_conv_ss_startstride (gfc_loopinfo *
tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
non_zerosized, tmp);
asprintf (&msg, "%s, upper bound of dimension %d of array "
- "'%s' exceeded, %%ld is greater than %%ld",
- gfc_msg_fault, info->dim[n]+1,
- ss->expr->symtree->name);
+ "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
+ info->dim[n]+1, ss->expr->symtree->name);
gfc_trans_runtime_check (tmp, &block, &ss->expr->where, msg,
fold_convert (long_integer_type_node, tmp2),
fold_convert (long_integer_type_node, ubound));