aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/simplify.c
diff options
context:
space:
mode:
authorTobias Burnus <burnus@net-b.de>2013-05-02 18:29:14 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2013-05-02 18:29:14 +0200
commit1634e53f83e6867eee8a0e88ac8869bec5af1f82 (patch)
treedcebcda3ff1e099bc1aa359f0760d729e1c1f185 /gcc/fortran/simplify.c
parent9f8e7a96c2d45daf5ee6e0ce9a1cbe4c80cbf96b (diff)
downloadgcc-1634e53f83e6867eee8a0e88ac8869bec5af1f82.zip
gcc-1634e53f83e6867eee8a0e88ac8869bec5af1f82.tar.gz
gcc-1634e53f83e6867eee8a0e88ac8869bec5af1f82.tar.bz2
re PR fortran/57142 (SIZE/SHAPE overflow despite kind=8)
2013-05-02 Tobias Burnus <burnus@net-b.de> PR fortran/57142 * simplify.c (gfc_simplify_size): Renamed from simplify_size; fix kind=8 handling. (gfc_simplify_size): New function. (gfc_simplify_shape): Add range check. * resolve.c (resolve_function): Fix handling for ISYM_SIZE. 2013-05-02 Tobias Burnus <burnus@net-b.de> PR fortran/57142 * gfortran.dg/size_kind_2.f90: New. * gfortran.dg/size_kind_3.f90: New. From-SVN: r198549
Diffstat (limited to 'gcc/fortran/simplify.c')
-rw-r--r--gcc/fortran/simplify.c74
1 files changed, 51 insertions, 23 deletions
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 02505db..815043b 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -33,6 +33,8 @@ along with GCC; see the file COPYING3. If not see
gfc_expr gfc_bad_expr;
+static gfc_expr *simplify_size (gfc_expr *, gfc_expr *, int);
+
/* Note that 'simplification' is not just transforming expressions.
For functions that are not simplified at compile time, range
@@ -3248,7 +3250,7 @@ simplify_bound_dim (gfc_expr *array, gfc_expr *kind, int d, int upper,
gfc_expr* dim = result;
mpz_set_si (dim->value.integer, d);
- result = gfc_simplify_size (array, dim, kind);
+ result = simplify_size (array, dim, k);
gfc_free_expr (dim);
if (!result)
goto returnNull;
@@ -5538,15 +5540,12 @@ gfc_simplify_shape (gfc_expr *source, gfc_expr *kind)
e = gfc_get_constant_expr (BT_INTEGER, k, &source->where);
if (t)
- {
- mpz_set (e->value.integer, shape[n]);
- mpz_clear (shape[n]);
- }
+ mpz_set (e->value.integer, shape[n]);
else
{
mpz_set_ui (e->value.integer, n + 1);
- f = gfc_simplify_size (source, e, NULL);
+ f = simplify_size (source, e, k);
gfc_free_expr (e);
if (f == NULL)
{
@@ -5557,23 +5556,30 @@ gfc_simplify_shape (gfc_expr *source, gfc_expr *kind)
e = f;
}
+ if (e == &gfc_bad_expr || range_check (e, "SHAPE") == &gfc_bad_expr)
+ {
+ gfc_free_expr (result);
+ if (t)
+ gfc_clear_shape (shape, source->rank);
+ return &gfc_bad_expr;
+ }
+
gfc_constructor_append_expr (&result->value.constructor, e, NULL);
}
+ if (t)
+ gfc_clear_shape (shape, source->rank);
+
return result;
}
-gfc_expr *
-gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
+static gfc_expr *
+simplify_size (gfc_expr *array, gfc_expr *dim, int k)
{
mpz_t size;
gfc_expr *return_value;
int d;
- int k = get_kind (BT_INTEGER, kind, "SIZE", gfc_default_integer_kind);
-
- if (k == -1)
- return &gfc_bad_expr;
/* For unary operations, the size of the result is given by the size
of the operand. For binary ones, it's the size of the first operand
@@ -5603,7 +5609,7 @@ gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
replacement = array->value.op.op1;
else
{
- simplified = gfc_simplify_size (array->value.op.op1, dim, kind);
+ simplified = simplify_size (array->value.op.op1, dim, k);
if (simplified)
return simplified;
@@ -5613,18 +5619,20 @@ gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
}
/* Try to reduce it directly if possible. */
- simplified = gfc_simplify_size (replacement, dim, kind);
+ simplified = simplify_size (replacement, dim, k);
/* Otherwise, we build a new SIZE call. This is hopefully at least
simpler than the original one. */
if (!simplified)
- simplified = gfc_build_intrinsic_call (gfc_current_ns,
- GFC_ISYM_SIZE, "size",
- array->where, 3,
- gfc_copy_expr (replacement),
- gfc_copy_expr (dim),
- gfc_copy_expr (kind));
-
+ {
+ gfc_expr *kind = gfc_get_int_expr (gfc_default_integer_kind, NULL, k);
+ simplified = gfc_build_intrinsic_call (gfc_current_ns,
+ GFC_ISYM_SIZE, "size",
+ array->where, 3,
+ gfc_copy_expr (replacement),
+ gfc_copy_expr (dim),
+ kind);
+ }
return simplified;
}
@@ -5643,12 +5651,31 @@ gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
return NULL;
}
- return_value = gfc_get_int_expr (k, &array->where, mpz_get_si (size));
+ return_value = gfc_get_constant_expr (BT_INTEGER, k, &array->where);
+ mpz_set (return_value->value.integer, size);
mpz_clear (size);
+
return return_value;
}
+gfc_expr *
+gfc_simplify_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
+{
+ gfc_expr *result;
+ int k = get_kind (BT_INTEGER, kind, "SIZE", gfc_default_integer_kind);
+
+ if (k == -1)
+ return &gfc_bad_expr;
+
+ result = simplify_size (array, dim, k);
+ if (result == NULL || result == &gfc_bad_expr)
+ return result;
+
+ return range_check (result, "SIZE");
+}
+
+
/* SIZEOF and C_SIZEOF return the size in bytes of an array element
multiplied by the array size. */
@@ -5705,7 +5732,8 @@ gfc_simplify_storage_size (gfc_expr *x,
mpz_set_si (result->value.integer, gfc_element_size (x));
mpz_mul_ui (result->value.integer, result->value.integer, BITS_PER_UNIT);
- return result;
+
+ return range_check (result, "STORAGE_SIZE");
}