diff options
-rw-r--r-- | gcc/fortran/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/fortran/array.c | 20 | ||||
-rw-r--r-- | gcc/fortran/gfortran.h | 2 | ||||
-rw-r--r-- | gcc/fortran/resolve.c | 32 | ||||
-rw-r--r-- | gcc/fortran/simplify.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/dependency_32.f90 | 10 |
7 files changed, 76 insertions, 7 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index c6ef130..de7dcaf 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,15 @@ +2010-08-09 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/44235 + * array.c (gfc_ref_dimen_size): Add end argument. + If end is non-NULL, calculate it. + (ref_size): Adjust call to gfc_ref_dimen_size. + (gfc_array_dimen_size): Likewise. + (gfc_array_res_shape): Likewise. + * gfortran.h: Adjust prototype for gfc_ref_dimen_size. + * resolve.c (resolve_array_ref): For stride not equal to -1, + fill in the lowest possible end. + 2010-08-09 Janus Weil <janus@gcc.gnu.org> * intrinsic.texi: Correct documentation of ASINH, ACOSH and ATANH. diff --git a/gcc/fortran/array.c b/gcc/fortran/array.c index 0d92e92..cd261bf 100644 --- a/gcc/fortran/array.c +++ b/gcc/fortran/array.c @@ -1940,10 +1940,11 @@ spec_size (gfc_array_spec *as, mpz_t *result) } -/* Get the number of elements in an array section. */ +/* Get the number of elements in an array section. Optionally, also supply + the end value. */ gfc_try -gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result) +gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result, mpz_t *end) { mpz_t upper, lower, stride; gfc_try t; @@ -2016,6 +2017,15 @@ gfc_ref_dimen_size (gfc_array_ref *ar, int dimen, mpz_t *result) mpz_set_ui (*result, 0); t = SUCCESS; + if (end) + { + mpz_init (*end); + + mpz_sub_ui (*end, *result, 1UL); + mpz_mul (*end, *end, stride); + mpz_add (*end, *end, lower); + } + cleanup: mpz_clear (upper); mpz_clear (lower); @@ -2040,7 +2050,7 @@ ref_size (gfc_array_ref *ar, mpz_t *result) for (d = 0; d < ar->dimen; d++) { - if (gfc_ref_dimen_size (ar, d, &size) == FAILURE) + if (gfc_ref_dimen_size (ar, d, &size, NULL) == FAILURE) { mpz_clear (*result); return FAILURE; @@ -2086,7 +2096,7 @@ gfc_array_dimen_size (gfc_expr *array, int dimen, mpz_t *result) if (ref->u.ar.dimen_type[i] != DIMEN_ELEMENT) dimen--; - return gfc_ref_dimen_size (&ref->u.ar, i - 1, result); + return gfc_ref_dimen_size (&ref->u.ar, i - 1, result, NULL); } } @@ -2222,7 +2232,7 @@ gfc_array_ref_shape (gfc_array_ref *ar, mpz_t *shape) { if (ar->dimen_type[i] != DIMEN_ELEMENT) { - if (gfc_ref_dimen_size (ar, i, &shape[d]) == FAILURE) + if (gfc_ref_dimen_size (ar, i, &shape[d], NULL) == FAILURE) goto cleanup; d++; } diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h index 713533d..898f307 100644 --- a/gcc/fortran/gfortran.h +++ b/gcc/fortran/gfortran.h @@ -2753,7 +2753,7 @@ gfc_try spec_size (gfc_array_spec *, mpz_t *); gfc_try spec_dimen_size (gfc_array_spec *, int, mpz_t *); int gfc_is_compile_time_shape (gfc_array_spec *); -gfc_try gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *); +gfc_try gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *, mpz_t *); /* interface.c -- FIXME: some of these should be in symbol.c */ diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c index 69a0036..9933b5d 100644 --- a/gcc/fortran/resolve.c +++ b/gcc/fortran/resolve.c @@ -4377,6 +4377,38 @@ resolve_array_ref (gfc_array_ref *ar) &ar->c_where[i], e->rank); return FAILURE; } + + /* Fill in the upper bound, which may be lower than the + specified one for something like a(2:10:5), which is + identical to a(2:7:5). Only relevant for strides not equal + to one. */ + if (ar->dimen_type[i] == DIMEN_RANGE + && ar->stride[i] != NULL && ar->stride[i]->expr_type == EXPR_CONSTANT + && mpz_cmp_si (ar->stride[i]->value.integer, 1L) != 0) + { + mpz_t size, end; + + if (gfc_ref_dimen_size (ar, i, &size, &end) == SUCCESS) + { + if (ar->end[i] == NULL) + { + ar->end[i] = + gfc_get_constant_expr (BT_INTEGER, gfc_index_integer_kind, + &ar->where); + mpz_set (ar->end[i]->value.integer, end); + } + else if (ar->end[i]->ts.type == BT_INTEGER + && ar->end[i]->expr_type == EXPR_CONSTANT) + { + mpz_set (ar->end[i]->value.integer, end); + } + else + gcc_unreachable (); + + mpz_clear (size); + mpz_clear (end); + } + } } if (ar->type == AR_FULL && ar->as->rank == 0) diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index a77f6bd..b47f8cc 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -2807,7 +2807,7 @@ simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper, { if (upper) { - if (gfc_ref_dimen_size (&ref->u.ar, d-1, &result->value.integer) + if (gfc_ref_dimen_size (&ref->u.ar, d-1, &result->value.integer, NULL) != SUCCESS) goto returnNull; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 93ed62f..638f3af 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-08-09 Thomas Koenig <tkoenig@gcc.gnu.org> + + PR fortran/44235 + * gfortran.dg/dependency_32.f90: New test. + 2010-08-09 Richard Guenther <rguenther@suse.de> PR middle-end/44632 diff --git a/gcc/testsuite/gfortran.dg/dependency_32.f90 b/gcc/testsuite/gfortran.dg/dependency_32.f90 new file mode 100644 index 0000000..c0a3118 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/dependency_32.f90 @@ -0,0 +1,10 @@ +! { dg-do compile } +! { dg-options "-Warray-temporaries" } +! PR 44235 +! No temporary should be created for this, as the upper bounds +! are effectively identical. +program main + real a(10) + a = 0. + a(1:10:4) = a(1:9:4) +end program main |