aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-array.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-array.cc')
-rw-r--r--gcc/fortran/trans-array.cc519
1 files changed, 406 insertions, 113 deletions
diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 7be2d7b..990aaaf 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -1426,12 +1426,6 @@ get_class_info_from_ss (stmtblock_t * pre, gfc_ss *ss, tree *eltype,
tmp2 = gfc_class_len_get (class_expr);
gfc_add_modify (pre, tmp, tmp2);
}
-
- if (rhs_function)
- {
- tmp = gfc_class_data_get (class_expr);
- gfc_conv_descriptor_offset_set (pre, tmp, gfc_index_zero_node);
- }
}
else if (rhs_ss->info->data.array.descriptor)
{
@@ -3372,18 +3366,51 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
break;
case GFC_SS_FUNCTION:
- /* Array function return value. We call the function and save its
- result in a temporary for use inside the loop. */
- gfc_init_se (&se, NULL);
- se.loop = loop;
- se.ss = ss;
- if (gfc_is_class_array_function (expr))
- expr->must_finalize = 1;
- gfc_conv_expr (&se, expr);
- gfc_add_block_to_block (&outer_loop->pre, &se.pre);
- gfc_add_block_to_block (&outer_loop->post, &se.post);
- gfc_add_block_to_block (&outer_loop->post, &se.finalblock);
- ss_info->string_length = se.string_length;
+ {
+ /* Array function return value. We call the function and save its
+ result in a temporary for use inside the loop. */
+ gfc_init_se (&se, NULL);
+ se.loop = loop;
+ se.ss = ss;
+ bool class_func = gfc_is_class_array_function (expr);
+ if (class_func)
+ expr->must_finalize = 1;
+ gfc_conv_expr (&se, expr);
+ gfc_add_block_to_block (&outer_loop->pre, &se.pre);
+ if (class_func
+ && se.expr
+ && GFC_CLASS_TYPE_P (TREE_TYPE (se.expr)))
+ {
+ tree tmp = gfc_class_data_get (se.expr);
+ info->descriptor = tmp;
+ info->data = gfc_conv_descriptor_data_get (tmp);
+ info->offset = gfc_conv_descriptor_offset_get (tmp);
+ for (gfc_ss *s = ss; s; s = s->parent)
+ for (int n = 0; n < s->dimen; n++)
+ {
+ int dim = s->dim[n];
+ tree tree_dim = gfc_rank_cst[dim];
+
+ tree start;
+ start = gfc_conv_descriptor_lbound_get (tmp, tree_dim);
+ start = gfc_evaluate_now (start, &outer_loop->pre);
+ info->start[dim] = start;
+
+ tree end;
+ end = gfc_conv_descriptor_ubound_get (tmp, tree_dim);
+ end = gfc_evaluate_now (end, &outer_loop->pre);
+ info->end[dim] = end;
+
+ tree stride;
+ stride = gfc_conv_descriptor_stride_get (tmp, tree_dim);
+ stride = gfc_evaluate_now (stride, &outer_loop->pre);
+ info->stride[dim] = stride;
+ }
+ }
+ gfc_add_block_to_block (&outer_loop->post, &se.post);
+ gfc_add_block_to_block (&outer_loop->post, &se.finalblock);
+ ss_info->string_length = se.string_length;
+ }
break;
case GFC_SS_CONSTRUCTOR:
@@ -3420,6 +3447,183 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
}
+/* Given an array descriptor expression DESCR and its data pointer DATA, decide
+ whether to either save the data pointer to a variable and use the variable or
+ use the data pointer expression directly without any intermediary variable.
+ */
+
+static bool
+save_descriptor_data (tree descr, tree data)
+{
+ return !(DECL_P (data)
+ || (TREE_CODE (data) == ADDR_EXPR
+ && DECL_P (TREE_OPERAND (data, 0)))
+ || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (descr))
+ && TREE_CODE (descr) == COMPONENT_REF
+ && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (descr, 0)))));
+}
+
+
+/* Type of the DATA argument passed to walk_tree by substitute_subexpr_in_expr
+ and used by maybe_substitute_expr. */
+
+typedef struct
+{
+ tree target, repl;
+}
+substitute_t;
+
+
+/* Check if the expression in *TP is equal to the substitution target provided
+ in DATA->TARGET and replace it with DATA->REPL in that case. This is a
+ callback function for use with walk_tree. */
+
+static tree
+maybe_substitute_expr (tree *tp, int *walk_subtree, void *data)
+{
+ substitute_t *subst = (substitute_t *) data;
+ if (*tp == subst->target)
+ {
+ *tp = subst->repl;
+ *walk_subtree = 0;
+ }
+
+ return NULL_TREE;
+}
+
+
+/* Substitute in EXPR any occurence of TARGET with REPLACEMENT. */
+
+static void
+substitute_subexpr_in_expr (tree target, tree replacement, tree expr)
+{
+ substitute_t subst;
+ subst.target = target;
+ subst.repl = replacement;
+
+ walk_tree (&expr, maybe_substitute_expr, &subst, nullptr);
+}
+
+
+/* Save REF to a fresh variable in all of REPLACEMENT_ROOTS, appending extra
+ code to CODE. Before returning, add REF to REPLACEMENT_ROOTS and clear
+ REF. */
+
+static void
+save_ref (tree &code, tree &ref, vec<tree> &replacement_roots)
+{
+ stmtblock_t tmp_block;
+ gfc_init_block (&tmp_block);
+ tree var = gfc_evaluate_now (ref, &tmp_block);
+ gfc_add_expr_to_block (&tmp_block, code);
+ code = gfc_finish_block (&tmp_block);
+
+ unsigned i;
+ tree repl_root;
+ FOR_EACH_VEC_ELT (replacement_roots, i, repl_root)
+ substitute_subexpr_in_expr (ref, var, repl_root);
+
+ replacement_roots.safe_push (ref);
+ ref = NULL_TREE;
+}
+
+
+/* Save the descriptor reference VALUE to storage pointed by DESC_PTR. Before
+ that, try to factor subexpressions of VALUE to variables, adding extra code
+ to BLOCK.
+
+ The candidate references to factoring are dereferenced pointers because they
+ are cheap to copy and array descriptors because they are often the base of
+ multiple subreferences. */
+
+static void
+set_factored_descriptor_value (tree *desc_ptr, tree value, stmtblock_t *block)
+{
+ /* As the reference is processed from outer to inner, variable definitions
+ will be generated in reversed order, so can't be put directly in BLOCK.
+ We use TMP_BLOCK instead. */
+ tree accumulated_code = NULL_TREE;
+
+ /* The current candidate to factoring. */
+ tree saveable_ref = NULL_TREE;
+
+ /* The root expressions in which we look for subexpressions to replace with
+ variables. */
+ auto_vec<tree> replacement_roots;
+ replacement_roots.safe_push (value);
+
+ tree data_ref = value;
+ tree next_ref = NULL_TREE;
+
+ /* If the candidate reference is not followed by a subreference, it can't be
+ saved to a variable as it may be reallocatable, and we have to keep the
+ parent reference to be able to store the new pointer value in case of
+ reallocation. */
+ bool maybe_reallocatable = true;
+
+ while (true)
+ {
+ if (!maybe_reallocatable
+ && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (data_ref)))
+ saveable_ref = data_ref;
+
+ if (TREE_CODE (data_ref) == INDIRECT_REF)
+ {
+ next_ref = TREE_OPERAND (data_ref, 0);
+
+ if (!maybe_reallocatable)
+ {
+ if (saveable_ref != NULL_TREE && saveable_ref != data_ref)
+ {
+ /* A reference worth saving has been seen, and now the pointer
+ to the current reference is also worth saving. If the
+ previous reference to save wasn't the current one, do save
+ it now. Otherwise drop it as we prefer saving the
+ pointer. */
+ save_ref (accumulated_code, saveable_ref, replacement_roots);
+ }
+
+ /* Don't evaluate the pointer to a variable yet; do it only if the
+ variable would be significantly more simple than the reference
+ it replaces. That is if the reference contains anything
+ different from NOPs, COMPONENTs and DECLs. */
+ saveable_ref = next_ref;
+ }
+ }
+ else if (TREE_CODE (data_ref) == COMPONENT_REF)
+ {
+ maybe_reallocatable = false;
+ next_ref = TREE_OPERAND (data_ref, 0);
+ }
+ else if (TREE_CODE (data_ref) == NOP_EXPR)
+ next_ref = TREE_OPERAND (data_ref, 0);
+ else
+ {
+ if (DECL_P (data_ref))
+ break;
+
+ if (TREE_CODE (data_ref) == ARRAY_REF)
+ {
+ maybe_reallocatable = false;
+ next_ref = TREE_OPERAND (data_ref, 0);
+ }
+
+ if (saveable_ref != NULL_TREE)
+ /* We have seen a reference worth saving. Do it now. */
+ save_ref (accumulated_code, saveable_ref, replacement_roots);
+
+ if (TREE_CODE (data_ref) != ARRAY_REF)
+ break;
+ }
+
+ data_ref = next_ref;
+ }
+
+ *desc_ptr = value;
+ gfc_add_expr_to_block (block, accumulated_code);
+}
+
+
/* Translate expressions for the descriptor and data pointer of a SS. */
/*GCC ARRAYS*/
@@ -3440,7 +3644,7 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
se.descriptor_only = 1;
gfc_conv_expr_lhs (&se, ss_info->expr);
gfc_add_block_to_block (block, &se.pre);
- info->descriptor = se.expr;
+ set_factored_descriptor_value (&info->descriptor, se.expr, block);
ss_info->string_length = se.string_length;
ss_info->class_container = se.class_container;
@@ -3466,17 +3670,14 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * ss, int base)
Otherwise we must evaluate it now to avoid breaking dependency
analysis by pulling the expressions for elemental array indices
inside the loop. */
- if (!(DECL_P (tmp)
- || (TREE_CODE (tmp) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (tmp, 0)))
- || (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se.expr))
- && TREE_CODE (se.expr) == COMPONENT_REF
- && GFC_CLASS_TYPE_P (TREE_TYPE (TREE_OPERAND (se.expr, 0))))))
+ if (save_descriptor_data (se.expr, tmp) && !ss->is_alloc_lhs)
tmp = gfc_evaluate_now (tmp, block);
info->data = tmp;
tmp = gfc_conv_array_offset (se.expr);
- info->offset = gfc_evaluate_now (tmp, block);
+ if (!ss->is_alloc_lhs)
+ tmp = gfc_evaluate_now (tmp, block);
+ info->offset = tmp;
/* Make absolutely sure that the saved_offset is indeed saved
so that the variable is still accessible after the loops
@@ -4769,13 +4970,12 @@ gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
static void
evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
- tree desc, int dim, bool lbound, bool deferred)
+ tree desc, int dim, bool lbound, bool deferred, bool save_value)
{
gfc_se se;
gfc_expr * input_val = values[dim];
tree *output = &bounds[dim];
-
if (input_val)
{
/* Specified section bound. */
@@ -4801,7 +5001,8 @@ evaluate_bound (stmtblock_t *block, tree *bounds, gfc_expr ** values,
*output = lbound ? gfc_conv_array_lbound (desc, dim) :
gfc_conv_array_ubound (desc, dim);
}
- *output = gfc_evaluate_now (*output, block);
+ if (save_value)
+ *output = gfc_evaluate_now (*output, block);
}
@@ -4834,18 +5035,18 @@ gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
|| ar->dimen_type[dim] == DIMEN_THIS_IMAGE);
desc = info->descriptor;
stride = ar->stride[dim];
-
+ bool save_value = !ss->is_alloc_lhs;
/* Calculate the start of the range. For vector subscripts this will
be the range of the vector. */
evaluate_bound (block, info->start, ar->start, desc, dim, true,
- ar->as->type == AS_DEFERRED);
+ ar->as->type == AS_DEFERRED, save_value);
/* Similarly calculate the end. Although this is not used in the
scalarizer, it is needed when checking bounds and where the end
is an expression with side-effects. */
evaluate_bound (block, info->end, ar->end, desc, dim, false,
- ar->as->type == AS_DEFERRED);
+ ar->as->type == AS_DEFERRED, save_value);
/* Calculate the stride. */
@@ -4856,7 +5057,11 @@ gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
gfc_init_se (&se, NULL);
gfc_conv_expr_type (&se, stride, gfc_array_index_type);
gfc_add_block_to_block (block, &se.pre);
- info->stride[dim] = gfc_evaluate_now (se.expr, block);
+ tree value = se.expr;
+ if (save_value)
+ info->stride[dim] = gfc_evaluate_now (value, block);
+ else
+ info->stride[dim] = value;
}
}
@@ -5205,7 +5410,8 @@ done:
int dim = ss->dim[n];
info->start[dim] = gfc_index_zero_node;
- info->end[dim] = gfc_index_zero_node;
+ if (ss_info->type != GFC_SS_FUNCTION)
+ info->end[dim] = gfc_index_zero_node;
info->stride[dim] = gfc_index_one_node;
}
break;
@@ -5890,6 +6096,46 @@ set_loop_bounds (gfc_loopinfo *loop)
}
+/* Last attempt to set the loop bounds, in case they depend on an allocatable
+ function result. */
+
+static void
+late_set_loop_bounds (gfc_loopinfo *loop)
+{
+ int n, dim;
+ gfc_array_info *info;
+ gfc_ss **loopspec;
+
+ loopspec = loop->specloop;
+
+ for (n = 0; n < loop->dimen; n++)
+ {
+ /* Set the extents of this range. */
+ if (loop->from[n] == NULL_TREE
+ || loop->to[n] == NULL_TREE)
+ {
+ /* We should have found the scalarization loop specifier. If not,
+ that's bad news. */
+ gcc_assert (loopspec[n]);
+
+ info = &loopspec[n]->info->data.array;
+ dim = loopspec[n]->dim[n];
+
+ if (loopspec[n]->info->type == GFC_SS_FUNCTION
+ && info->start[dim]
+ && info->end[dim])
+ {
+ loop->from[n] = info->start[dim];
+ loop->to[n] = info->end[dim];
+ }
+ }
+ }
+
+ for (loop = loop->nested; loop; loop = loop->next)
+ late_set_loop_bounds (loop);
+}
+
+
/* Initialize the scalarization loop. Creates the loop variables. Determines
the range of the loop variables. Creates a temporary if required.
Also generates code for scalar expressions which have been
@@ -5908,6 +6154,8 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
allocating the temporary. */
gfc_add_loop_ss_code (loop, loop->ss, false, where);
+ late_set_loop_bounds (loop);
+
tmp_ss = loop->temp_ss;
/* If we want a temporary then create it. */
if (tmp_ss != NULL)
@@ -5964,9 +6212,11 @@ gfc_set_delta (gfc_loopinfo *loop)
gfc_ss_type ss_type;
ss_type = ss->info->type;
- if (ss_type != GFC_SS_SECTION
- && ss_type != GFC_SS_COMPONENT
- && ss_type != GFC_SS_CONSTRUCTOR)
+ if (!(ss_type == GFC_SS_SECTION
+ || ss_type == GFC_SS_COMPONENT
+ || ss_type == GFC_SS_CONSTRUCTOR
+ || (ss_type == GFC_SS_FUNCTION
+ && gfc_is_class_array_function (ss->info->expr))))
continue;
info = &ss->info->data.array;
@@ -5991,7 +6241,10 @@ gfc_set_delta (gfc_loopinfo *loop)
gfc_array_index_type,
info->start[dim], tmp);
- info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
+ if (ss->is_alloc_lhs)
+ info->delta[dim] = tmp;
+ else
+ info->delta[dim] = gfc_evaluate_now (tmp, &outer_loop->pre);
}
}
}
@@ -6115,8 +6368,8 @@ static tree
gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
gfc_expr ** lower, gfc_expr ** upper, stmtblock_t * pblock,
stmtblock_t * descriptor_block, tree * overflow,
- tree expr3_elem_size, tree *nelems, gfc_expr *expr3,
- tree expr3_desc, bool e3_has_nodescriptor, gfc_expr *expr,
+ tree expr3_elem_size, gfc_expr *expr3, tree expr3_desc,
+ bool e3_has_nodescriptor, gfc_expr *expr,
tree *element_size, bool explicit_ts)
{
tree type;
@@ -6392,7 +6645,6 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
if (rank == 0)
return *element_size;
- *nelems = gfc_evaluate_now (stride, pblock);
stride = fold_convert (size_type_node, stride);
/* First check for overflow. Since an array of type character can
@@ -6481,9 +6733,8 @@ retrieve_last_ref (gfc_ref **ref_in, gfc_ref **prev_ref_in)
bool
gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
tree errlen, tree label_finish, tree expr3_elem_size,
- tree *nelems, gfc_expr *expr3, tree e3_arr_desc,
- bool e3_has_nodescriptor, gfc_omp_namelist *omp_alloc,
- bool explicit_ts)
+ gfc_expr *expr3, tree e3_arr_desc, bool e3_has_nodescriptor,
+ gfc_omp_namelist *omp_alloc, bool explicit_ts)
{
tree tmp;
tree pointer;
@@ -6614,7 +6865,7 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
coarray ? ref->u.ar.as->corank : 0,
&offset, lower, upper,
&se->pre, &set_descriptor_block, &overflow,
- expr3_elem_size, nelems, expr3, e3_arr_desc,
+ expr3_elem_size, expr3, e3_arr_desc,
e3_has_nodescriptor, expr, &element_size,
explicit_ts);
@@ -6779,8 +7030,6 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
else
gfc_add_expr_to_block (&se->pre, set_descriptor);
- expr->symtree->n.sym->allocated_in_scope = 1;
-
return true;
}
@@ -8470,7 +8719,7 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
gcc_assert (n == codim - 1);
evaluate_bound (&loop.pre, info->start, ar->start,
info->descriptor, n + ndim, true,
- ar->as->type == AS_DEFERRED);
+ ar->as->type == AS_DEFERRED, true);
loop.from[n + loop.dimen] = info->start[n + ndim];
}
else
@@ -11206,6 +11455,9 @@ gfc_is_reallocatable_lhs (gfc_expr *expr)
gfc_ref * ref;
gfc_symbol *sym;
+ if (!flag_realloc_lhs)
+ return false;
+
if (!expr->ref)
return false;
@@ -11330,6 +11582,55 @@ concat_str_length (gfc_expr* expr)
}
+/* Among the scalarization chain of LOOP, find the element associated with an
+ allocatable array on the lhs of an assignment and evaluate its fields
+ (bounds, offset, etc) to new variables, putting the new code in BLOCK. This
+ function is to be called after putting the reallocation code in BLOCK and
+ before the beginning of the scalarization loop body.
+
+ The fields to be saved are expected to hold on entry to the function
+ expressions referencing the array descriptor. Especially the expressions
+ shouldn't be already temporary variable references as the value saved before
+ reallocation would be incorrect after reallocation.
+ At the end of the function, the expressions have been replaced with variable
+ references. */
+
+static void
+update_reallocated_descriptor (stmtblock_t *block, gfc_loopinfo *loop)
+{
+ for (gfc_ss *s = loop->ss; s != gfc_ss_terminator; s = s->loop_chain)
+ {
+ if (!s->is_alloc_lhs)
+ continue;
+
+ gcc_assert (s->info->type == GFC_SS_SECTION);
+ gfc_array_info *info = &s->info->data.array;
+
+#define SAVE_VALUE(value) \
+ do \
+ { \
+ value = gfc_evaluate_now (value, block); \
+ } \
+ while (0)
+
+ if (save_descriptor_data (info->descriptor, info->data))
+ SAVE_VALUE (info->data);
+ SAVE_VALUE (info->offset);
+ info->saved_offset = info->offset;
+ for (int i = 0; i < s->dimen; i++)
+ {
+ int dim = s->dim[i];
+ SAVE_VALUE (info->start[dim]);
+ SAVE_VALUE (info->end[dim]);
+ SAVE_VALUE (info->stride[dim]);
+ SAVE_VALUE (info->delta[dim]);
+ }
+
+#undef SAVE_VALUE
+ }
+}
+
+
/* Allocate the lhs of an assignment to an allocatable array, otherwise
reallocate it. */
@@ -11368,7 +11669,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
tree lbd;
tree class_expr2 = NULL_TREE;
int n;
- int dim;
gfc_array_spec * as;
bool coarray = (flag_coarray == GFC_FCOARRAY_LIB
&& gfc_caf_attr (expr1, true).codimension);
@@ -11423,14 +11723,61 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
&& !expr2->value.function.isym)
expr2->ts.u.cl->backend_decl = rss->info->string_length;
- gfc_start_block (&fblock);
-
/* Since the lhs is allocatable, this must be a descriptor type.
Get the data and array size. */
desc = linfo->descriptor;
gcc_assert (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)));
array1 = gfc_conv_descriptor_data_get (desc);
+ /* If the data is null, set the descriptor bounds and offset. This suppresses
+ the maybe used uninitialized warning. Note that the always false variable
+ prevents this block from ever being executed, and makes sure that the
+ optimizers are able to remove it. Component references are not subject to
+ the warnings, so we don't uselessly complicate the generated code for them.
+ */
+ for (ref = expr1->ref; ref; ref = ref->next)
+ if (ref->type == REF_COMPONENT)
+ break;
+
+ if (!ref)
+ {
+ stmtblock_t unalloc_init_block;
+ gfc_init_block (&unalloc_init_block);
+ tree guard = gfc_create_var (logical_type_node, "unallocated_init_guard");
+ gfc_add_modify (&unalloc_init_block, guard, logical_false_node);
+
+ gfc_start_block (&loop_pre_block);
+ for (n = 0; n < expr1->rank; n++)
+ {
+ gfc_conv_descriptor_lbound_set (&loop_pre_block, desc,
+ gfc_rank_cst[n],
+ gfc_index_one_node);
+ gfc_conv_descriptor_ubound_set (&loop_pre_block, desc,
+ gfc_rank_cst[n],
+ gfc_index_zero_node);
+ gfc_conv_descriptor_stride_set (&loop_pre_block, desc,
+ gfc_rank_cst[n],
+ gfc_index_zero_node);
+ }
+
+ tmp = gfc_conv_descriptor_offset (desc);
+ gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node);
+
+ tmp = fold_build2_loc (input_location, EQ_EXPR,
+ logical_type_node, array1,
+ build_int_cst (TREE_TYPE (array1), 0));
+ tmp = fold_build2_loc (input_location, TRUTH_ANDIF_EXPR,
+ logical_type_node, tmp, guard);
+ tmp = build3_v (COND_EXPR, tmp,
+ gfc_finish_block (&loop_pre_block),
+ build_empty_stmt (input_location));
+ gfc_prepend_expr_to_block (&loop->pre, tmp);
+ gfc_prepend_expr_to_block (&loop->pre,
+ gfc_finish_block (&unalloc_init_block));
+ }
+
+ gfc_start_block (&fblock);
+
if (expr2)
desc2 = rss->info->data.array.descriptor;
else
@@ -11543,45 +11890,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
array1, build_int_cst (TREE_TYPE (array1), 0));
cond_null= gfc_evaluate_now (cond_null, &fblock);
- /* If the data is null, set the descriptor bounds and offset. This suppresses
- the maybe used uninitialized warning and forces the use of malloc because
- the size is zero in all dimensions. Note that this block is only executed
- if the lhs is unallocated and is only applied once in any namespace.
- Component references are not subject to the warnings. */
- for (ref = expr1->ref; ref; ref = ref->next)
- if (ref->type == REF_COMPONENT)
- break;
-
- if (!expr1->symtree->n.sym->allocated_in_scope && !ref)
- {
- gfc_start_block (&loop_pre_block);
- for (n = 0; n < expr1->rank; n++)
- {
- gfc_conv_descriptor_lbound_set (&loop_pre_block, desc,
- gfc_rank_cst[n],
- gfc_index_one_node);
- gfc_conv_descriptor_ubound_set (&loop_pre_block, desc,
- gfc_rank_cst[n],
- gfc_index_zero_node);
- gfc_conv_descriptor_stride_set (&loop_pre_block, desc,
- gfc_rank_cst[n],
- gfc_index_zero_node);
- }
-
- tmp = gfc_conv_descriptor_offset (desc);
- gfc_add_modify (&loop_pre_block, tmp, gfc_index_zero_node);
-
- tmp = fold_build2_loc (input_location, EQ_EXPR,
- logical_type_node, array1,
- build_int_cst (TREE_TYPE (array1), 0));
- tmp = build3_v (COND_EXPR, tmp,
- gfc_finish_block (&loop_pre_block),
- build_empty_stmt (input_location));
- gfc_prepend_expr_to_block (&loop->pre, tmp);
-
- expr1->symtree->n.sym->allocated_in_scope = 1;
- }
-
tmp = build3_v (COND_EXPR, cond_null,
build1_v (GOTO_EXPR, jump_label1),
build_empty_stmt (input_location));
@@ -11736,21 +12044,6 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
running offset. Use the saved_offset instead. */
tmp = gfc_conv_descriptor_offset (desc);
gfc_add_modify (&fblock, tmp, offset);
- if (linfo->saved_offset
- && VAR_P (linfo->saved_offset))
- gfc_add_modify (&fblock, linfo->saved_offset, tmp);
-
- /* Now set the deltas for the lhs. */
- for (n = 0; n < expr1->rank; n++)
- {
- tmp = gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]);
- dim = lss->dim[n];
- tmp = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, tmp,
- loop->from[dim]);
- if (linfo->delta[dim] && VAR_P (linfo->delta[dim]))
- gfc_add_modify (&fblock, linfo->delta[dim], tmp);
- }
/* Take into account _len of unlimited polymorphic entities, so that span
for array descriptors and allocation sizes are computed correctly. */
@@ -11972,18 +12265,18 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
tmp = build3_v (COND_EXPR, cond_null, alloc_expr, realloc_expr);
gfc_add_expr_to_block (&fblock, tmp);
- /* Make sure that the scalarizer data pointer is updated. */
- if (linfo->data && VAR_P (linfo->data))
- {
- tmp = gfc_conv_descriptor_data_get (desc);
- gfc_add_modify (&fblock, linfo->data, tmp);
- }
-
/* Add the label for same shape lhs and rhs. */
tmp = build1_v (LABEL_EXPR, jump_label2);
gfc_add_expr_to_block (&fblock, tmp);
- return gfc_finish_block (&fblock);
+ tree realloc_code = gfc_finish_block (&fblock);
+
+ stmtblock_t result_block;
+ gfc_init_block (&result_block);
+ gfc_add_expr_to_block (&result_block, realloc_code);
+ update_reallocated_descriptor (&result_block, loop);
+
+ return gfc_finish_block (&result_block);
}