aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2011-02-19 15:03:27 +0000
committerPaul Thomas <pault@gcc.gnu.org>2011-02-19 15:03:27 +0000
commit6c1b5781b4e65ac22a1b176609f548c42f2418b8 (patch)
treee9d23bf03eee0cad9d9e990d7523934bf76c250e /gcc/fortran
parent27f98305d72a39edb648da5b7a891bee29a04f86 (diff)
downloadgcc-6c1b5781b4e65ac22a1b176609f548c42f2418b8.zip
gcc-6c1b5781b4e65ac22a1b176609f548c42f2418b8.tar.gz
gcc-6c1b5781b4e65ac22a1b176609f548c42f2418b8.tar.bz2
re PR fortran/47348 (wrong string length with array constructor)
2011-02-19 Paul Thomas <pault@gcc.gnu.org> PR fortran/47348 * trans-array.c (get_array_ctor_all_strlen): Move up in file. (get_array_ctor_var_strlen): Add block dummy and add call to get_array_ctor_all_strlen instead of giving up on substrings. Call gcc_unreachable for default case. (get_array_ctor_strlen): Add extra argument to in call to get_array_ctor_var_strlen. 2011-02-19 Paul Thomas <pault@gcc.gnu.org> PR fortran/47348 * gfortran.dg/array_constructor_36.f90 : New test. * gfortran.dg/bounds_check_10.f90 : Change dg-output message to allow for comparison between different elements of the array constructor at different levels of optimization. From-SVN: r170317
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog10
-rw-r--r--gcc/fortran/trans-array.c102
2 files changed, 62 insertions, 50 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index d7dff6d..f8aa502 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,13 @@
+2011-02-19 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/47348
+ * trans-array.c (get_array_ctor_all_strlen): Move up in file.
+ (get_array_ctor_var_strlen): Add block dummy and add call to
+ get_array_ctor_all_strlen instead of giving up on substrings.
+ Call gcc_unreachable for default case.
+ (get_array_ctor_strlen): Add extra argument to in call to
+ get_array_ctor_var_strlen.
+
2011-02-18 Janus Weil <janus@gcc.gnu.org>
PR fortran/47789
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 4dc69d2..83f0189 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -1495,11 +1495,55 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
}
+/* A catch-all to obtain the string length for anything that is not a
+ a substring of non-constant length, a constant, array or variable. */
+
+static void
+get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
+{
+ gfc_se se;
+ gfc_ss *ss;
+
+ /* Don't bother if we already know the length is a constant. */
+ if (*len && INTEGER_CST_P (*len))
+ return;
+
+ if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
+ && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
+ {
+ /* This is easy. */
+ gfc_conv_const_charlen (e->ts.u.cl);
+ *len = e->ts.u.cl->backend_decl;
+ }
+ else
+ {
+ /* Otherwise, be brutal even if inefficient. */
+ ss = gfc_walk_expr (e);
+ gfc_init_se (&se, NULL);
+
+ /* No function call, in case of side effects. */
+ se.no_function_call = 1;
+ if (ss == gfc_ss_terminator)
+ gfc_conv_expr (&se, e);
+ else
+ gfc_conv_expr_descriptor (&se, e, ss);
+
+ /* Fix the value. */
+ *len = gfc_evaluate_now (se.string_length, &se.pre);
+
+ gfc_add_block_to_block (block, &se.pre);
+ gfc_add_block_to_block (block, &se.post);
+
+ e->ts.u.cl->backend_decl = *len;
+ }
+}
+
+
/* Figure out the string length of a variable reference expression.
Used by get_array_ctor_strlen. */
static void
-get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
+get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
{
gfc_ref *ref;
gfc_typespec *ts;
@@ -1526,7 +1570,11 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
case REF_SUBSTRING:
if (ref->u.ss.start->expr_type != EXPR_CONSTANT
|| ref->u.ss.end->expr_type != EXPR_CONSTANT)
- break;
+ {
+ /* Note that this might evaluate expr. */
+ get_array_ctor_all_strlen (block, expr, len);
+ return;
+ }
mpz_init_set_ui (char_len, 1);
mpz_add (char_len, char_len, ref->u.ss.end->value.integer);
mpz_sub (char_len, char_len, ref->u.ss.start->value.integer);
@@ -1536,10 +1584,7 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
return;
default:
- /* TODO: Substrings are tricky because we can't evaluate the
- expression more than once. For now we just give up, and hope
- we can figure it out elsewhere. */
- return;
+ gcc_unreachable ();
}
}
@@ -1547,49 +1592,6 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
}
-/* A catch-all to obtain the string length for anything that is not a
- constant, array or variable. */
-static void
-get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
-{
- gfc_se se;
- gfc_ss *ss;
-
- /* Don't bother if we already know the length is a constant. */
- if (*len && INTEGER_CST_P (*len))
- return;
-
- if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
- && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
- {
- /* This is easy. */
- gfc_conv_const_charlen (e->ts.u.cl);
- *len = e->ts.u.cl->backend_decl;
- }
- else
- {
- /* Otherwise, be brutal even if inefficient. */
- ss = gfc_walk_expr (e);
- gfc_init_se (&se, NULL);
-
- /* No function call, in case of side effects. */
- se.no_function_call = 1;
- if (ss == gfc_ss_terminator)
- gfc_conv_expr (&se, e);
- else
- gfc_conv_expr_descriptor (&se, e, ss);
-
- /* Fix the value. */
- *len = gfc_evaluate_now (se.string_length, &se.pre);
-
- gfc_add_block_to_block (block, &se.pre);
- gfc_add_block_to_block (block, &se.post);
-
- e->ts.u.cl->backend_decl = *len;
- }
-}
-
-
/* Figure out the string length of a character array constructor.
If len is NULL, don't calculate the length; this happens for recursive calls
when a sub-array-constructor is an element but not at the first position,
@@ -1633,7 +1635,7 @@ get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len
case EXPR_VARIABLE:
is_const = false;
if (len)
- get_array_ctor_var_strlen (c->expr, len);
+ get_array_ctor_var_strlen (block, c->expr, len);
break;
default: