summaryrefslogtreecommitdiffstats
path: root/gcc/fortran/trans-stmt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-stmt.c')
-rw-r--r--gcc/fortran/trans-stmt.c82
1 files changed, 39 insertions, 43 deletions
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index 25a5b3b4ede..9d3197d11bc 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -3992,7 +3992,7 @@ tree
gfc_trans_allocate (gfc_code * code)
{
gfc_alloc *al;
- gfc_expr *expr;
+ gfc_expr *expr, *init_e, *rhs;
gfc_se se;
tree tmp;
tree parm;
@@ -4001,7 +4001,7 @@ gfc_trans_allocate (gfc_code * code)
tree error_label;
stmtblock_t block;
- if (!code->ext.alloc_list)
+ if (!code->ext.alloc.list)
return NULL_TREE;
pstat = stat = error_label = tmp = NULL_TREE;
@@ -4020,7 +4020,7 @@ gfc_trans_allocate (gfc_code * code)
TREE_USED (error_label) = 1;
}
- for (al = code->ext.alloc_list; al != NULL; al = al->next)
+ for (al = code->ext.alloc.list; al != NULL; al = al->next)
{
expr = al->expr;
@@ -4034,7 +4034,24 @@ gfc_trans_allocate (gfc_code * code)
if (!gfc_array_allocate (&se, expr, pstat))
{
/* A scalar or derived type. */
- tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
+
+ /* Determine allocate size. */
+ if (code->expr3 && code->expr3->ts.type == BT_CLASS)
+ {
+ gfc_typespec *ts;
+ /* TODO: Size must be determined at run time, since it must equal
+ the size of the dynamic type of SOURCE, not the declared type. */
+ gfc_warning ("Dynamic size allocation at %L not supported yet, "
+ "using size of declared type", &code->loc);
+ ts = &code->expr3->ts.u.derived->components->ts;
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (ts));
+ }
+ else if (code->expr3 && code->expr3->ts.type != BT_CLASS)
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->expr3->ts));
+ else if (code->ext.alloc.ts.type != BT_UNKNOWN)
+ tmp = TYPE_SIZE_UNIT (gfc_typenode_for_spec (&code->ext.alloc.ts));
+ else
+ tmp = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (se.expr)));
if (expr->ts.type == BT_CHARACTER && tmp == NULL_TREE)
tmp = se.string_length;
@@ -4065,6 +4082,23 @@ gfc_trans_allocate (gfc_code * code)
tmp = gfc_finish_block (&se.pre);
gfc_add_expr_to_block (&block, tmp);
+
+ /* Initialization via SOURCE block. */
+ if (code->expr3)
+ {
+ rhs = gfc_copy_expr (code->expr3);
+ if (rhs->ts.type == BT_CLASS)
+ gfc_add_component_ref (rhs, "$data");
+ tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr), rhs, false);
+ gfc_add_expr_to_block (&block, tmp);
+ }
+ /* Add default initializer for those derived types that need them. */
+ else if (expr->ts.type == BT_DERIVED && (init_e = gfc_default_initializer (&expr->ts)))
+ {
+ tmp = gfc_trans_assignment (gfc_expr_to_initialize (expr), init_e, true);
+ gfc_add_expr_to_block (&block, tmp);
+ }
+
}
/* STAT block. */
@@ -4111,44 +4145,6 @@ gfc_trans_allocate (gfc_code * code)
gfc_add_expr_to_block (&block, tmp);
}
- /* SOURCE block. Note, by C631, we know that code->ext.alloc_list
- has a single entity. */
- if (code->expr3)
- {
- gfc_ref *ref;
- gfc_array_ref *ar;
- int n;
-
- /* If there is a terminating array reference, this is converted
- to a full array, so that gfc_trans_assignment can scalarize the
- expression for the source. */
- for (ref = code->ext.alloc_list->expr->ref; ref; ref = ref->next)
- {
- if (ref->next == NULL)
- {
- if (ref->type != REF_ARRAY)
- break;
-
- ref->u.ar.type = AR_FULL;
- ar = &ref->u.ar;
- ar->dimen = ar->as->rank;
- for (n = 0; n < ar->dimen; n++)
- {
- ar->dimen_type[n] = DIMEN_RANGE;
- gfc_free_expr (ar->start[n]);
- gfc_free_expr (ar->end[n]);
- gfc_free_expr (ar->stride[n]);
- ar->start[n] = NULL;
- ar->end[n] = NULL;
- ar->stride[n] = NULL;
- }
- }
- }
-
- tmp = gfc_trans_assignment (code->ext.alloc_list->expr, code->expr3, false);
- gfc_add_expr_to_block (&block, tmp);
- }
-
return gfc_finish_block (&block);
}
@@ -4186,7 +4182,7 @@ gfc_trans_deallocate (gfc_code *code)
gfc_add_modify (&block, astat, build_int_cst (TREE_TYPE (astat), 0));
}
- for (al = code->ext.alloc_list; al != NULL; al = al->next)
+ for (al = code->ext.alloc.list; al != NULL; al = al->next)
{
expr = al->expr;
gcc_assert (expr->expr_type == EXPR_VARIABLE);
OpenPOWER on IntegriCloud