diff options
Diffstat (limited to 'gcc/fortran/dependency.cc')
-rw-r--r-- | gcc/fortran/dependency.cc | 82 |
1 files changed, 82 insertions, 0 deletions
diff --git a/gcc/fortran/dependency.cc b/gcc/fortran/dependency.cc index bafe8cb..15edf1a 100644 --- a/gcc/fortran/dependency.cc +++ b/gcc/fortran/dependency.cc @@ -2497,3 +2497,85 @@ gfc_omp_expr_prefix_same (gfc_expr *lexpr, gfc_expr *rexpr) return true; } + + +/* gfc_function_dependency returns true for non-dummy symbols with dependencies + on an old-fashioned function result (ie. proc_name = proc_name->result). + This is used to ensure that initialization code appears after the function + result is treated and that any mutual dependencies between these symbols are + respected. */ + +static bool +dependency_fcn (gfc_expr *e, gfc_symbol *sym, + int *f ATTRIBUTE_UNUSED) +{ + if (e == NULL) + return false; + + if (e && e->expr_type == EXPR_VARIABLE) + { + if (e->symtree && e->symtree->n.sym == sym) + return true; + /* Recurse to see if this symbol is dependent on the function result. If + so an indirect dependence exists, which should be handled in the same + way as a direct dependence. The recursion is prevented from being + infinite by statement order. */ + else if (e->symtree && e->symtree->n.sym) + return gfc_function_dependency (e->symtree->n.sym, sym); + } + + return false; +} + + +bool +gfc_function_dependency (gfc_symbol *sym, gfc_symbol *proc_name) +{ + bool dep = false; + + if (proc_name && proc_name->attr.function + && proc_name == proc_name->result + && !(sym->attr.dummy || sym->attr.result)) + { + if (sym->fn_result_dep) + return true; + + if (sym->as && sym->as->type == AS_EXPLICIT) + { + for (int dim = 0; dim < sym->as->rank; dim++) + { + if (sym->as->lower[dim] + && sym->as->lower[dim]->expr_type != EXPR_CONSTANT) + dep = gfc_traverse_expr (sym->as->lower[dim], proc_name, + dependency_fcn, 0); + if (dep) + { + sym->fn_result_dep = 1; + return true; + } + if (sym->as->upper[dim] + && sym->as->upper[dim]->expr_type != EXPR_CONSTANT) + dep = gfc_traverse_expr (sym->as->upper[dim], proc_name, + dependency_fcn, 0); + if (dep) + { + sym->fn_result_dep = 1; + return true; + } + } + } + + if (sym->ts.type == BT_CHARACTER + && sym->ts.u.cl && sym->ts.u.cl->length + && sym->ts.u.cl->length->expr_type != EXPR_CONSTANT) + dep = gfc_traverse_expr (sym->ts.u.cl->length, proc_name, + dependency_fcn, 0); + if (dep) + { + sym->fn_result_dep = 1; + return true; + } + } + + return false; + } |