aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-array.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2018-07-12 16:50:41 +0000
committerJakub Jelinek <jakub@redhat.com>2018-07-12 16:50:41 +0000
commit1ed159550621e4b1cf35ab868e0a7d51e2837724 (patch)
tree9bad8e165e1df1b26197b4700f9f51566152a405 /gcc/fortran/trans-array.c
parentc1e7aa1d88a3110f71b740fc8ea11f3274cae433 (diff)
parentf7d3a6a6300a4c330afca4d8772ac80ab09ac21c (diff)
svn merge -r258208:262569 svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-7-branchredhat/gcc-7-branch
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/redhat/gcc-7-branch@262599 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/fortran/trans-array.c')
-rw-r--r--gcc/fortran/trans-array.c89
1 files changed, 78 insertions, 11 deletions
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 96fe8d431a3..8c566e85769 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -2652,6 +2652,8 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
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);
@@ -3071,7 +3073,7 @@ conv_array_index_offset (gfc_se * se, gfc_ss * ss, int dim, int i,
}
/* Multiply by the stride. */
- if (!integer_onep (stride))
+ if (stride != NULL && !integer_onep (stride))
index = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
index, stride);
@@ -3102,7 +3104,7 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
{
if (expr == NULL
|| (expr->ts.type != BT_CLASS
- && !gfc_is_alloc_class_array_function (expr)
+ && !gfc_is_class_array_function (expr)
&& !gfc_is_class_array_ref (expr, NULL)))
return false;
@@ -3132,12 +3134,12 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
}
if (class_ref == NULL && expr && expr->symtree->n.sym->attr.function
- && expr->symtree->n.sym == expr->symtree->n.sym->result)
+ && expr->symtree->n.sym == expr->symtree->n.sym->result
+ && expr->symtree->n.sym->backend_decl == current_function_decl)
{
- gcc_assert (expr->symtree->n.sym->backend_decl == current_function_decl);
decl = gfc_get_fake_result_decl (expr->symtree->n.sym, 0);
}
- else if (expr && gfc_is_alloc_class_array_function (expr))
+ else if (expr && gfc_is_class_array_function (expr))
{
size = NULL_TREE;
decl = NULL_TREE;
@@ -3160,6 +3162,8 @@ build_class_array_ref (gfc_se *se, tree base, tree index)
if (decl == NULL_TREE)
return false;
+
+ se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
}
else if (class_ref == NULL)
{
@@ -3334,7 +3338,10 @@ build_array_ref (tree desc, tree offset, tree decl, tree vptr)
{
type = gfc_get_element_type (type);
tmp = TREE_OPERAND (cdecl, 0);
- tmp = gfc_get_class_array_ref (offset, tmp, NULL_TREE);
+ /* Note that the fourth argument in this call has been set false.
+ should any character dynamic types come this way, the 'len'
+ field of the unlimited object will not be used. */
+ tmp = gfc_get_class_array_ref (offset, tmp, NULL_TREE, false);
tmp = fold_convert (build_pointer_type (type), tmp);
tmp = build_fold_indirect_ref_loc (input_location, tmp);
return tmp;
@@ -7125,7 +7132,11 @@ gfc_conv_expr_descriptor (gfc_se *se, gfc_expr *expr)
else
{
/* Otherwise make a new one. */
- parmtype = gfc_get_element_type (TREE_TYPE (desc));
+ if (expr->ts.type == BT_CHARACTER && expr->ts.deferred)
+ parmtype = gfc_typenode_for_spec (&expr->ts);
+ else
+ parmtype = gfc_get_element_type (TREE_TYPE (desc));
+
parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, codim,
loop.from, loop.to, 0,
GFC_ARRAY_UNKNOWN, false);
@@ -8598,7 +8609,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
break;
case COPY_ALLOC_COMP:
- if (c->attr.pointer)
+ if (c->attr.pointer || c->attr.proc_pointer)
continue;
/* We need source and destination components. */
@@ -8642,6 +8653,31 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
gfc_init_block (&tmpblock);
+ gfc_add_modify (&tmpblock, gfc_class_vptr_get (dcmp),
+ gfc_class_vptr_get (comp));
+
+ /* Copy the unlimited '_len' field. If it is greater than zero
+ (ie. a character(_len)), multiply it by size and use this
+ for the malloc call. */
+ if (UNLIMITED_POLY (c))
+ {
+ tree ctmp;
+ gfc_add_modify (&tmpblock, gfc_class_len_get (dcmp),
+ gfc_class_len_get (comp));
+
+ size = gfc_evaluate_now (size, &tmpblock);
+ tmp = gfc_class_len_get (comp);
+ ctmp = fold_build2_loc (input_location, MULT_EXPR,
+ size_type_node, size,
+ fold_convert (size_type_node, tmp));
+ tmp = fold_build2_loc (input_location, GT_EXPR,
+ logical_type_node, tmp,
+ build_zero_cst (TREE_TYPE (tmp)));
+ size = fold_build3_loc (input_location, COND_EXPR,
+ size_type_node, tmp, ctmp, size);
+ size = gfc_evaluate_now (size, &tmpblock);
+ }
+
/* Coarray component have to have the same allocation status and
shape/type-parameter/effective-type on the LHS and RHS of an
intrinsic assignment. Hence, we did not deallocated them - and
@@ -9096,6 +9132,12 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
if (expr2 && rss == gfc_ss_terminator)
return NULL_TREE;
+ /* Ensure that the string length from the current scope is used. */
+ if (expr2->ts.type == BT_CHARACTER
+ && expr2->expr_type == EXPR_FUNCTION
+ && !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.
@@ -9340,6 +9382,8 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_array_index_type, tmp,
expr1->ts.u.cl->backend_decl);
}
+ else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr2->ts));
else
tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&expr1->ts));
tmp = fold_convert (gfc_array_index_type, tmp);
@@ -9366,6 +9410,28 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
gfc_add_modify (&fblock, tmp,
gfc_get_dtype_rank_type (expr1->rank,type));
}
+ else if (UNLIMITED_POLY (expr1) && expr2->ts.type != BT_CLASS)
+ {
+ tree type;
+ tmp = gfc_conv_descriptor_dtype (desc);
+ type = gfc_typenode_for_spec (&expr2->ts);
+ gfc_add_modify (&fblock, tmp,
+ gfc_get_dtype_rank_type (expr2->rank,type));
+ /* Set the _len field as well... */
+ tmp = gfc_class_len_get (TREE_OPERAND (desc, 0));
+ if (expr2->ts.type == BT_CHARACTER)
+ gfc_add_modify (&fblock, tmp,
+ fold_convert (TREE_TYPE (tmp),
+ TYPE_SIZE_UNIT (type)));
+ else
+ gfc_add_modify (&fblock, tmp,
+ build_int_cst (TREE_TYPE (tmp), 0));
+ /* ...and the vptr. */
+ tmp = gfc_class_vptr_get (TREE_OPERAND (desc, 0));
+ tmp2 = gfc_get_symbol_decl (gfc_find_vtab (&expr2->ts));
+ tmp2 = gfc_build_addr_expr (TREE_TYPE (tmp), tmp2);
+ gfc_add_modify (&fblock, tmp, tmp2);
+ }
else if (coarray && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
{
gfc_add_modify (&fblock, gfc_conv_descriptor_dtype (desc),
@@ -9471,10 +9537,11 @@ gfc_alloc_allocatable_for_assignment (gfc_loopinfo *loop,
/* We already set the dtype in the case of deferred character
- length arrays. */
+ length arrays and unlimited polymorphic arrays. */
if (!(GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc))
&& ((expr1->ts.type == BT_CHARACTER && expr1->ts.deferred)
- || coarray)))
+ || coarray))
+ && !UNLIMITED_POLY (expr1))
{
tmp = gfc_conv_descriptor_dtype (desc);
gfc_add_modify (&alloc_block, tmp, gfc_get_dtype (TREE_TYPE (desc)));
@@ -10007,7 +10074,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
if (!sym)
sym = expr->symtree->n.sym;
- if (gfc_is_alloc_class_array_function (expr))
+ if (gfc_is_class_array_function (expr))
return gfc_get_array_ss (ss, expr,
CLASS_DATA (expr->value.function.esym->result)->as->rank,
GFC_SS_FUNCTION);