aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorFrancois-Xavier Coudert <coudert@clipper.ens.fr>2006-11-16 13:25:11 +0100
committerFrançois-Xavier Coudert <fxcoudert@gcc.gnu.org>2006-11-16 12:25:11 +0000
commit9f1dce5609ca54d2caa87d0ecfece64a7bb58c81 (patch)
treef14cc63483c17ad4c8e486eae4a98c3d88d24e41 /gcc/fortran
parent6c0e51c4fad90d1a93040fe92695890b5715d6f5 (diff)
downloadgcc-9f1dce5609ca54d2caa87d0ecfece64a7bb58c81.zip
gcc-9f1dce5609ca54d2caa87d0ecfece64a7bb58c81.tar.gz
gcc-9f1dce5609ca54d2caa87d0ecfece64a7bb58c81.tar.bz2
re PR fortran/29391 ([4.2/4.1 only] LBOUND and UBOUND are broken)
PR fortran/29391 PR fortran/29489 * simplify.c (simplify_bound): Fix the simplification of LBOUND/UBOUND intrinsics. * trans-intrinsic.c (simplify_bound): Fix the logic, and remove an erroneous assert. * gcc/testsuite/gfortran.dg/bound_2.f90: Add more checks. * gcc/testsuite/gfortran.dg/bound_3.f90: New test. From-SVN: r118888
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog9
-rw-r--r--gcc/fortran/simplify.c45
-rw-r--r--gcc/fortran/trans-intrinsic.c32
3 files changed, 67 insertions, 19 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 3141d72..c26bf0b 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,12 @@
+2006-11-16 Francois-Xavier Coudert <coudert@clipper.ens.fr>
+
+ PR fortran/29391
+ PR fortran/29489
+ * simplify.c (simplify_bound): Fix the simplification of
+ LBOUND/UBOUND intrinsics.
+ * trans-intrinsic.c (simplify_bound): Fix the logic, and
+ remove an erroneous assert.
+
2006-11-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu,org>
* trans-decl.c (gfc_get_symbol_decl): Fix formatting.
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 75e4c3c..8ecabf0 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -1913,12 +1913,9 @@ simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
{
gfc_ref *ref;
gfc_array_spec *as;
- gfc_expr *e;
+ gfc_expr *l, *u, *result;
int d;
- if (array->expr_type != EXPR_VARIABLE)
- return NULL;
-
if (dim == NULL)
/* TODO: Simplify constant multi-dimensional bounds. */
return NULL;
@@ -1926,6 +1923,9 @@ simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
if (dim->expr_type != EXPR_CONSTANT)
return NULL;
+ if (array->expr_type != EXPR_VARIABLE)
+ return NULL;
+
/* Follow any component references. */
as = array->symtree->n.sym->as;
for (ref = array->ref; ref; ref = ref->next)
@@ -1975,12 +1975,43 @@ simplify_bound (gfc_expr * array, gfc_expr * dim, int upper)
return &gfc_bad_expr;
}
- e = upper ? as->upper[d-1] : as->lower[d-1];
+ /* The last dimension of an assumed-size array is special. */
+ if (d == as->rank && as->type == AS_ASSUMED_SIZE && !upper)
+ {
+ if (as->lower[d-1]->expr_type == EXPR_CONSTANT)
+ return gfc_copy_expr (as->lower[d-1]);
+ else
+ return NULL;
+ }
- if (e->expr_type != EXPR_CONSTANT)
+ /* Then, we need to know the extent of the given dimension. */
+ l = as->lower[d-1];
+ u = as->upper[d-1];
+
+ if (l->expr_type != EXPR_CONSTANT || u->expr_type != EXPR_CONSTANT)
return NULL;
- return gfc_copy_expr (e);
+ result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind,
+ &array->where);
+
+ if (mpz_cmp (l->value.integer, u->value.integer) > 0)
+ {
+ /* Zero extent. */
+ if (upper)
+ mpz_set_si (result->value.integer, 0);
+ else
+ mpz_set_si (result->value.integer, 1);
+ }
+ else
+ {
+ /* Nonzero extent. */
+ if (upper)
+ mpz_set (result->value.integer, u->value.integer);
+ else
+ mpz_set (result->value.integer, l->value.integer);
+ }
+
+ return range_check (result, upper ? "UBOUND" : "LBOUND");
}
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index ec857a53..5facd5b 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -712,14 +712,13 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
tree type;
tree bound;
tree tmp;
- tree cond, cond1, cond2, cond3, size;
+ tree cond, cond1, cond2, cond3, cond4, size;
tree ubound;
tree lbound;
gfc_se argse;
gfc_ss *ss;
gfc_array_spec * as;
gfc_ref *ref;
- int i;
arg = expr->value.function.actual;
arg2 = arg->next;
@@ -761,9 +760,14 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
if (INTEGER_CST_P (bound))
{
- gcc_assert (TREE_INT_CST_HIGH (bound) == 0);
- i = TREE_INT_CST_LOW (bound);
- gcc_assert (i >= 0 && i < GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)));
+ int hi, low;
+
+ hi = TREE_INT_CST_HIGH (bound);
+ low = TREE_INT_CST_LOW (bound);
+ if (hi || low < 0 || low >= GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)))
+ gfc_error ("'dim' argument of %s intrinsic at %L is not a valid "
+ "dimension index", upper ? "UBOUND" : "LBOUND",
+ &expr->where);
}
else
{
@@ -842,15 +846,21 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
if (as)
{
tree stride = gfc_conv_descriptor_stride (desc, bound);
+
cond1 = fold_build2 (GE_EXPR, boolean_type_node, ubound, lbound);
cond2 = fold_build2 (LE_EXPR, boolean_type_node, ubound, lbound);
- cond3 = fold_build2 (GT_EXPR, boolean_type_node, stride,
+
+ cond3 = fold_build2 (GE_EXPR, boolean_type_node, stride,
gfc_index_zero_node);
+ cond3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
+
+ cond4 = fold_build2 (LT_EXPR, boolean_type_node, stride,
+ gfc_index_zero_node);
+ cond4 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond4, cond2);
if (upper)
{
- cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
- cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond2);
+ cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,
ubound, gfc_index_zero_node);
@@ -860,13 +870,11 @@ gfc_conv_intrinsic_bound (gfc_se * se, gfc_expr * expr, int upper)
if (as->type == AS_ASSUMED_SIZE)
cond = fold_build2 (EQ_EXPR, boolean_type_node, bound,
build_int_cst (TREE_TYPE (bound),
- arg->expr->rank));
+ arg->expr->rank - 1));
else
cond = boolean_false_node;
- cond1 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, cond3, cond1);
- cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond1, cond2);
-
+ cond1 = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond3, cond4);
cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, cond, cond1);
se->expr = fold_build3 (COND_EXPR, gfc_array_index_type, cond,