aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-array.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r--gcc/fortran/trans-array.c61
1 files changed, 55 insertions, 6 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 1379426..2bc24d9 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2099,6 +2099,8 @@ get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
{
case REF_ARRAY:
/* Array references don't change the string length. */
+ if (ts->deferred)
+ get_array_ctor_all_strlen (block, expr, len);
break;
case REF_COMPONENT:
@@ -2107,7 +2109,8 @@ get_array_ctor_var_strlen (stmtblock_t *block, gfc_expr * expr, tree * len)
break;
case REF_SUBSTRING:
- if (ref->u.ss.start->expr_type != EXPR_CONSTANT
+ if (ref->u.ss.end == NULL
+ || ref->u.ss.start->expr_type != EXPR_CONSTANT
|| ref->u.ss.end->expr_type != EXPR_CONSTANT)
{
/* Note that this might evaluate expr. */
@@ -2507,7 +2510,6 @@ trans_array_constructor (gfc_ss * ss, locus * where)
ss_info->string_length);
ss_info->string_length = gfc_evaluate_now (ss_info->string_length,
&length_se.pre);
-
gfc_add_block_to_block (&outer_loop->pre, &length_se.pre);
gfc_add_block_to_block (&outer_loop->post, &length_se.post);
}
@@ -3470,6 +3472,9 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
|| expr->expr_type == EXPR_FUNCTION))))
decl = expr->symtree->n.sym->backend_decl;
+ if (decl && GFC_DECL_PTR_ARRAY_P (decl))
+ goto done;
+
/* A pointer array component can be detected from its field decl. Fix
the descriptor, mark the resulting variable decl and pass it to
gfc_build_array_ref. */
@@ -3486,6 +3491,7 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
decl = info->descriptor;
}
+done:
se->expr = gfc_build_array_ref (base, index, decl);
}
@@ -6929,6 +6935,7 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
gfc_formal_arglist *formal;
gfc_actual_arglist *arg;
gfc_se tse;
+ gfc_expr *e;
if (expr->ts.u.cl->length
&& gfc_is_constant_expr (expr->ts.u.cl->length))
@@ -6940,6 +6947,34 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
switch (expr->expr_type)
{
+ case EXPR_ARRAY:
+
+ /* This is somewhat brutal. The expression for the first
+ element of the array is evaluated and assigned to a
+ new string length for the original expression. */
+ e = gfc_constructor_first (expr->value.constructor)->expr;
+
+ gfc_init_se (&tse, NULL);
+ if (e->rank)
+ gfc_conv_expr_descriptor (&tse, e);
+ else
+ gfc_conv_expr (&tse, e);
+
+ gfc_add_block_to_block (&se->pre, &tse.pre);
+ gfc_add_block_to_block (&se->post, &tse.post);
+
+ if (!expr->ts.u.cl->backend_decl || !VAR_P (expr->ts.u.cl->backend_decl))
+ {
+ expr->ts.u.cl = gfc_new_charlen (gfc_current_ns, NULL);
+ expr->ts.u.cl->backend_decl =
+ gfc_create_var (gfc_charlen_type_node, "sln");
+ }
+
+ gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
+ tse.string_length);
+
+ return;
+
case EXPR_OP:
get_array_charlen (expr->value.op.op1, se);
@@ -6947,7 +6982,7 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
if (expr->value.op.op == INTRINSIC_PARENTHESES)
return;
- expr->ts.u.cl->backend_decl =
+ expr->ts.u.cl->backend_decl =
gfc_create_var (gfc_charlen_type_node, "sln");
if (expr->value.op.op2)
@@ -7325,7 +7360,8 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
if (need_tmp)
{
- if (expr->ts.type == BT_CHARACTER && !expr->ts.u.cl->backend_decl)
+ if (expr->ts.type == BT_CHARACTER
+ && (!expr->ts.u.cl->backend_decl || expr->expr_type == EXPR_ARRAY))
get_array_charlen (expr, se);
/* Tell the scalarizer to make a temporary. */
@@ -7447,7 +7483,17 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
/* Set the string_length for a character array. */
if (expr->ts.type == BT_CHARACTER)
- se->string_length = gfc_get_expr_charlen (expr);
+ {
+ se->string_length = gfc_get_expr_charlen (expr);
+ if (VAR_P (se->string_length)
+ && expr->ts.u.cl->backend_decl == se->string_length)
+ tmp = ss_info->string_length;
+ else
+ tmp = se->string_length;
+
+ if (expr->ts.deferred)
+ gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl, tmp);
+ }
/* If we have an array section or are assigning make sure that
the lower bound is 1. References to the full
@@ -7509,7 +7555,10 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
}
/* Set the span field. */
- tmp = gfc_get_array_span (desc, expr);
+ if (expr->ts.type == BT_CHARACTER && ss_info->string_length)
+ tmp = ss_info->string_length;
+ else
+ tmp = gfc_get_array_span (desc, expr);
if (tmp != NULL_TREE)
gfc_conv_descriptor_span_set (&loop.pre, parm, tmp);