diff options
Diffstat (limited to 'gcc/fortran/trans-decl.cc')
-rw-r--r-- | gcc/fortran/trans-decl.cc | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc index f7fb6ee..8d4f06a 100644 --- a/gcc/fortran/trans-decl.cc +++ b/gcc/fortran/trans-decl.cc @@ -49,6 +49,7 @@ along with GCC; see the file COPYING3. If not see #include "omp-general.h" #include "attr-fnspec.h" #include "tree-iterator.h" +#include "dependency.h" #define MAX_LABEL_VALUE 99999 @@ -833,6 +834,19 @@ gfc_allocate_lang_decl (tree decl) DECL_LANG_SPECIFIC (decl) = ggc_cleared_alloc<struct lang_decl> (); } + +/* Determine order of two symbol declarations. */ + +static bool +decl_order (gfc_symbol *sym1, gfc_symbol *sym2) +{ + if (sym1->declared_at.lb->location > sym2->declared_at.lb->location) + return true; + else + return false; +} + + /* Remember a symbol to generate initialization/cleanup code at function entry/exit. */ @@ -850,18 +864,34 @@ gfc_defer_symbol_init (gfc_symbol * sym) last = head = sym->ns->proc_name; p = last->tlink; + gfc_function_dependency (sym, head); + /* Make sure that setup code for dummy variables which are used in the setup of other variables is generated first. */ if (sym->attr.dummy) { /* Find the first dummy arg seen after us, or the first non-dummy arg. - This is a circular list, so don't go past the head. */ + This is a circular list, so don't go past the head. */ while (p != head - && (!p->attr.dummy || p->dummy_order > sym->dummy_order)) - { - last = p; - p = p->tlink; - } + && (!p->attr.dummy || decl_order (p, sym))) + { + last = p; + p = p->tlink; + } + } + else if (sym->fn_result_dep) + { + /* In the case of non-dummy symbols with dependencies on an old-fashioned + function result (ie. proc_name = proc_name->result), make sure that the + order in the tlink chain is such that the code appears in declaration + order. This ensures that mutual dependencies between these symbols are + respected. */ + while (p != head + && (!p->attr.result || decl_order (sym, p))) + { + last = p; + p = p->tlink; + } } /* Insert in between last and p. */ last->tlink = sym; @@ -4183,12 +4213,19 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, gfc_wrapped_block * block) stmtblock_t init; tree decl; tree tmp; + bool back; gcc_assert (sym->backend_decl); gcc_assert (sym->ts.u.cl && sym->ts.u.cl->length); gfc_init_block (&init); + /* In the case of non-dummy symbols with dependencies on an old-fashioned + function result (ie. proc_name = proc_name->result), gfc_add_init_cleanup + must be called with the last, optional argument false so that the process + ing of the character length occurs after the processing of the result. */ + back = sym->fn_result_dep; + /* Evaluate the string length expression. */ gfc_conv_string_length (sym->ts.u.cl, NULL, &init); @@ -4201,7 +4238,7 @@ gfc_trans_auto_character_variable (gfc_symbol * sym, gfc_wrapped_block * block) tmp = fold_build1_loc (input_location, DECL_EXPR, TREE_TYPE (decl), decl); gfc_add_expr_to_block (&init, tmp); - gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE); + gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE, back); } /* Set the initial value of ASSIGN statement auxiliary variable explicitly. */ |