@@ -3355,7 +3355,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
gfc_symbol *sym;
gfc_formal_arglist *f;
stmtblock_t tmpblock;
- bool seen_trans_deferred_array = false;
+ bool seen_trans_deferred_array = false, processed_proc = false;
tree tmp = NULL;
gfc_expr *e;
gfc_se se;
@@ -3391,37 +3391,8 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
else if (proc_sym->ts.type == BT_CHARACTER)
{
- if (proc_sym->ts.deferred)
- {
- tmp = NULL;
- gfc_save_backend_locus (&loc);
- gfc_set_backend_locus (&proc_sym->declared_at);
- gfc_start_block (&init);
- /* Zero the string length on entry. */
- gfc_add_modify (&init, proc_sym->ts.u.cl->backend_decl,
- build_int_cst (gfc_charlen_type_node, 0));
- /* Null the pointer. */
- e = gfc_lval_expr_from_sym (proc_sym);
- gfc_init_se (&se, NULL);
- se.want_pointer = 1;
- gfc_conv_expr (&se, e);
- gfc_free_expr (e);
- tmp = se.expr;
- gfc_add_modify (&init, tmp,
- fold_convert (TREE_TYPE (se.expr),
- null_pointer_node));
- gfc_restore_backend_locus (&loc);
-
- /* Pass back the string length on exit. */
- tmp = proc_sym->ts.u.cl->passed_length;
- tmp = build_fold_indirect_ref_loc (input_location, tmp);
- tmp = fold_convert (gfc_charlen_type_node, tmp);
- tmp = fold_build2_loc (input_location, MODIFY_EXPR,
- gfc_charlen_type_node, tmp,
- proc_sym->ts.u.cl->backend_decl);
- gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
- }
- else if (TREE_CODE (proc_sym->ts.u.cl->backend_decl) == VAR_DECL)
+ if (TREE_CODE (proc_sym->ts.u.cl->backend_decl) == VAR_DECL
+ && !proc_sym->ts.deferred)
gfc_trans_dummy_character (proc_sym, proc_sym->ts.u.cl, block);
}
else
@@ -3437,14 +3408,32 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
init_intent_out_dt (proc_sym, block);
gfc_restore_backend_locus (&loc);
- for (sym = proc_sym->tlink; sym != proc_sym; sym = sym->tlink)
+ for (sym = proc_sym->tlink; ; sym = sym->tlink)
{
bool sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
&& sym->ts.u.derived->attr.alloc_comp;
if (sym->assoc)
continue;
- if (sym->attr.dimension)
+ /* Handle sym == proc_sym only once to avoid an endless loop. */
+ if (sym == proc_sym)
+ {
+ if (processed_proc)
+ break;
+ processed_proc = true;
+ }
+
+ /* For function results, which do not need an initialization,
+ end the loop. */
+ if (sym == proc_sym
+ && (sym != proc_sym->result
+ || !(sym->attr.allocatable || sym->ts.deferred
+ || sym_has_alloc_comp
+ || (sym->ts.type == BT_CLASS
+ && CLASS_DATA (sym)->attr.allocatable))))
+ break;
+
+ if (sym->attr.dimension && sym != proc_sym)
{
switch (sym->as->type)
{
@@ -3521,7 +3510,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
if (sym_has_alloc_comp && !seen_trans_deferred_array)
gfc_trans_deferred_array (sym, block);
}
- else if ((!sym->attr.dummy || sym->ts.deferred)
+ else if (! sym->attr.dimension && (!sym->attr.dummy || sym->ts.deferred)
&& (sym->attr.allocatable
|| (sym->ts.type == BT_CLASS
&& CLASS_DATA (sym)->attr.allocatable)))
@@ -3551,9 +3540,9 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
null_pointer_node));
}
- if ((sym->attr.dummy ||sym->attr.result)
- && sym->ts.type == BT_CHARACTER
- && sym->ts.deferred)
+ if ((sym->attr.dummy || sym->attr.result || sym == proc_sym)
+ && sym->ts.type == BT_CHARACTER
+ && sym->ts.deferred)
{
/* Character length passed by reference. */
tmp = sym->ts.u.cl->passed_length;
@@ -3582,7 +3571,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
/* Deallocate when leaving the scope. Nullifying is not
needed. */
- if (!sym->attr.result && !sym->attr.dummy)
+ if (!sym->attr.result && sym != proc_sym && !sym->attr.dummy)
tmp = gfc_deallocate_scalar_with_status (se.expr, NULL, true,
NULL, sym->ts);
@@ -3638,9 +3627,9 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
}
else if (sym->ts.deferred)
gfc_fatal_error ("Deferred type parameter not yet supported");
- else if (sym_has_alloc_comp)
+ else if (sym_has_alloc_comp && proc_sym != sym)
gfc_trans_deferred_array (sym, block);
- else if (sym->ts.type == BT_CHARACTER)
+ else if (sym->ts.type == BT_CHARACTER && sym != proc_sym)
{
gfc_save_backend_locus (&loc);
gfc_set_backend_locus (&sym->declared_at);
@@ -3667,7 +3656,7 @@ gfc_trans_deferred_vars (gfc_symbol * proc_sym, gfc_wrapped_block * block)
gfc_add_init_cleanup (block, gfc_finish_block (&tmpblock),
NULL_TREE);
}
- else
+ else if (proc_sym != sym)
gcc_unreachable ();
}