aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/simplify.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/simplify.c')
-rw-r--r--gcc/fortran/simplify.c84
1 files changed, 65 insertions, 19 deletions
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 423f3336d8b..a57731a7c1d 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -592,7 +592,7 @@ gfc_simplify_ceiling (gfc_expr * e, gfc_expr * k)
gfc_expr *ceil, *result;
int kind;
- kind = get_kind (BT_REAL, k, "CEILING", gfc_default_real_kind);
+ kind = get_kind (BT_INTEGER, k, "CEILING", gfc_default_integer_kind);
if (kind == -1)
return &gfc_bad_expr;
@@ -967,6 +967,7 @@ gfc_simplify_exp (gfc_expr * x)
gfc_expr *
gfc_simplify_exponent (gfc_expr * x)
{
+ int i;
mpfr_t tmp;
gfc_expr *result;
@@ -991,6 +992,12 @@ gfc_simplify_exponent (gfc_expr * x)
gfc_mpfr_to_mpz (result->value.integer, tmp);
+ /* The model number for tiny(x) is b**(emin - 1) where b is the base and emin
+ is the smallest exponent value. So, we need to add 1 if x is tiny(x). */
+ i = gfc_validate_kind (x->ts.type, x->ts.kind, false);
+ if (mpfr_cmp (x->value.real, gfc_real_kinds[i].tiny) == 0)
+ mpz_add_ui (result->value.integer,result->value.integer, 1);
+
mpfr_clear (tmp);
return range_check (result, "EXPONENT");
@@ -1017,7 +1024,7 @@ gfc_simplify_floor (gfc_expr * e, gfc_expr * k)
mpfr_t floor;
int kind;
- kind = get_kind (BT_REAL, k, "FLOOR", gfc_default_real_kind);
+ kind = get_kind (BT_INTEGER, k, "FLOOR", gfc_default_integer_kind);
if (kind == -1)
gfc_internal_error ("gfc_simplify_floor(): Bad kind");
@@ -1473,7 +1480,7 @@ gfc_simplify_int (gfc_expr * e, gfc_expr * k)
gfc_expr *rpart, *rtrunc, *result;
int kind;
- kind = get_kind (BT_REAL, k, "INT", gfc_default_real_kind);
+ kind = get_kind (BT_INTEGER, k, "INT", gfc_default_integer_kind);
if (kind == -1)
return &gfc_bad_expr;
@@ -1766,16 +1773,18 @@ gfc_simplify_kind (gfc_expr * e)
static gfc_expr *
-gfc_simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
+simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
{
gfc_ref *ref;
gfc_array_spec *as;
- int i;
+ gfc_expr *e;
+ int d;
if (array->expr_type != EXPR_VARIABLE)
return NULL;
if (dim == NULL)
+ /* TODO: Simplify constant multi-dimensional bounds. */
return NULL;
if (dim->expr_type != EXPR_CONSTANT)
@@ -1783,29 +1792,66 @@ gfc_simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
/* Follow any component references. */
as = array->symtree->n.sym->as;
- ref = array->ref;
- while (ref->next != NULL)
+ for (ref = array->ref; ref; ref = ref->next)
{
- if (ref->type == REF_COMPONENT)
- as = ref->u.c.sym->as;
- ref = ref->next;
+ switch (ref->type)
+ {
+ case REF_ARRAY:
+ switch (ref->u.ar.type)
+ {
+ case AR_ELEMENT:
+ as = NULL;
+ continue;
+
+ case AR_FULL:
+ /* We're done because 'as' has already been set in the
+ previous iteration. */
+ goto done;
+
+ case AR_SECTION:
+ case AR_UNKNOWN:
+ return NULL;
+ }
+
+ gcc_unreachable ();
+
+ case REF_COMPONENT:
+ as = ref->u.c.component->as;
+ continue;
+
+ case REF_SUBSTRING:
+ continue;
+ }
}
+
+ gcc_unreachable ();
- if (ref->type != REF_ARRAY || ref->u.ar.type != AR_FULL)
+ done:
+ if (as->type == AS_DEFERRED || as->type == AS_ASSUMED_SHAPE)
return NULL;
-
- i = mpz_get_si (dim->value.integer);
- if (upper)
- return gfc_copy_expr (as->upper[i-1]);
- else
- return gfc_copy_expr (as->lower[i-1]);
+
+ d = mpz_get_si (dim->value.integer);
+
+ if (d < 1 || d > as->rank
+ || (d == as->rank && as->type == AS_ASSUMED_SIZE && upper))
+ {
+ gfc_error ("DIM argument at %L is out of bounds", &dim->where);
+ return &gfc_bad_expr;
+ }
+
+ e = upper ? as->upper[d-1] : as->lower[d-1];
+
+ if (e->expr_type != EXPR_CONSTANT)
+ return NULL;
+
+ return gfc_copy_expr (e);
}
gfc_expr *
gfc_simplify_lbound (gfc_expr * array, gfc_expr * dim)
{
- return gfc_simplify_bound (array, dim, 0);
+ return simplify_bound (array, dim, 0);
}
@@ -3578,7 +3624,7 @@ gfc_simplify_trim (gfc_expr * e)
gfc_expr *
gfc_simplify_ubound (gfc_expr * array, gfc_expr * dim)
{
- return gfc_simplify_bound (array, dim, 1);
+ return simplify_bound (array, dim, 1);
}