diff options
author | Harald Anlauf <anlauf@gmx.de> | 2023-09-15 19:13:38 +0200 |
---|---|---|
committer | Harald Anlauf <anlauf@gmx.de> | 2023-09-15 19:13:38 +0200 |
commit | 1cbf18978aa384bd0ed2dc29b107fc3423cf8e62 (patch) | |
tree | f90422ce7e613be7a4dfd27daa5313c208b252de | |
parent | b975c0dc3be285655800180260c985bc97886f2e (diff) | |
download | gcc-1cbf18978aa384bd0ed2dc29b107fc3423cf8e62.zip gcc-1cbf18978aa384bd0ed2dc29b107fc3423cf8e62.tar.gz gcc-1cbf18978aa384bd0ed2dc29b107fc3423cf8e62.tar.bz2 |
Fortran: improve bounds-checking for array sections [PR30802]
gcc/fortran/ChangeLog:
PR fortran/30802
* trans-array.cc (trans_array_bound_check): Add optional argument
COMPNAME for explicit specification of array component name.
(array_bound_check_elemental): Helper function for generating
bounds-checking code for elemental dimensions.
(gfc_conv_expr_descriptor): Use bounds-checking also for elemental
dimensions, i.e. those not handled by the scalarizer.
gcc/testsuite/ChangeLog:
PR fortran/30802
* gfortran.dg/bounds_check_fail_6.f90: New test.
-rw-r--r-- | gcc/fortran/trans-array.cc | 69 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/bounds_check_fail_6.f90 | 29 |
2 files changed, 97 insertions, 1 deletions
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc index 6ca58e9..1640587 100644 --- a/gcc/fortran/trans-array.cc +++ b/gcc/fortran/trans-array.cc @@ -3452,7 +3452,8 @@ gfc_conv_array_ubound (tree descriptor, int dim) static tree trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n, - locus * where, bool check_upper) + locus * where, bool check_upper, + const char *compname = NULL) { tree fault; tree tmp_lo, tmp_up; @@ -3474,6 +3475,10 @@ trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n, if (VAR_P (descriptor)) name = IDENTIFIER_POINTER (DECL_NAME (descriptor)); + /* Use given (array component) name. */ + if (compname) + name = compname; + /* If upper bound is present, include both bounds in the error message. */ if (check_upper) { @@ -3524,6 +3529,64 @@ trans_array_bound_check (gfc_se * se, gfc_ss *ss, tree index, int n, } +/* Generate code for bounds checking for elemental dimensions. */ + +static void +array_bound_check_elemental (gfc_se * se, gfc_ss * ss, gfc_expr * expr) +{ + gfc_array_ref *ar; + gfc_ref *ref; + gfc_symbol *sym; + char *var_name = NULL; + size_t len; + int dim; + + if (expr->expr_type == EXPR_VARIABLE) + { + sym = expr->symtree->n.sym; + len = strlen (sym->name) + 1; + + for (ref = expr->ref; ref; ref = ref->next) + if (ref->type == REF_COMPONENT) + len += 2 + strlen (ref->u.c.component->name); + + var_name = XALLOCAVEC (char, len); + strcpy (var_name, sym->name); + + for (ref = expr->ref; ref; ref = ref->next) + { + /* Append component name. */ + if (ref->type == REF_COMPONENT) + { + strcat (var_name, "%%"); + strcat (var_name, ref->u.c.component->name); + continue; + } + + if (ref->type == REF_ARRAY && ref->u.ar.dimen > 0) + { + ar = &ref->u.ar; + for (dim = 0; dim < ar->dimen; dim++) + { + if (ar->dimen_type[dim] == DIMEN_ELEMENT) + { + gfc_se indexse; + gfc_init_se (&indexse, NULL); + gfc_conv_expr_type (&indexse, ar->start[dim], + gfc_array_index_type); + trans_array_bound_check (se, ss, indexse.expr, dim, + &ar->where, + ar->as->type != AS_ASSUMED_SIZE + || dim < ar->dimen - 1, + var_name); + } + } + } + } + } +} + + /* Return the offset for an index. Performs bound checking for elemental dimensions. Single element references are processed separately. DIM is the array dimension, I is the loop dimension. */ @@ -7823,6 +7886,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr) /* Setup the scalarizing loops and bounds. */ gfc_conv_ss_startstride (&loop); + /* Add bounds-checking for elemental dimensions. */ + if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && !expr->no_bounds_check) + array_bound_check_elemental (se, ss, expr); + if (need_tmp) { if (expr->ts.type == BT_CHARACTER diff --git a/gcc/testsuite/gfortran.dg/bounds_check_fail_6.f90 b/gcc/testsuite/gfortran.dg/bounds_check_fail_6.f90 new file mode 100644 index 0000000..9032913 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/bounds_check_fail_6.f90 @@ -0,0 +1,29 @@ +! { dg-do run } +! { dg-additional-options "-fcheck=bounds -g -fdump-tree-original" } +! { dg-output "At line 18 .*" } +! { dg-shouldfail "dimension 3 of array 'u%z' outside of expected range" } +! +! PR fortran/30802 - improve bounds-checking for array sections + +program test + implicit none + integer :: k = 0 + integer, dimension(10,20,30) :: x = 42 + type t + real, dimension(10,20,30) :: z = 23 + end type t + type(t) :: u + + ! pr30802 + print *, u% z(1,:,k) ! runtime check only for dimension 3 + + ! pr97039 + call foo (x(k,:,k+1)) ! runtime checks for dimensions 1,3 +contains + subroutine foo (a) + integer, intent(in) :: a(:) + end subroutine foo +end program test + +! { dg-final { scan-tree-dump-times "'u%%z.' outside of expected range" 2 "original" } } +! { dg-final { scan-tree-dump-times "'x.' outside of expected range" 4 "original" } } |