aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/dependency.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/dependency.cc')
-rw-r--r--gcc/fortran/dependency.cc82
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;
+ }