aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/dependency.c
diff options
context:
space:
mode:
authorPaul Thomas <pault@gcc.gnu.org>2006-03-01 22:24:19 +0000
committerPaul Thomas <pault@gcc.gnu.org>2006-03-01 22:24:19 +0000
commit61321991ff5f055015750ddf36444705b9921464 (patch)
tree1fb7018901bd09ec73d55b0ccf66775cd2947e62 /gcc/fortran/dependency.c
parent8acb1b3d1c6369349372f74e815db2375ea8e0c5 (diff)
downloadgcc-61321991ff5f055015750ddf36444705b9921464.zip
gcc-61321991ff5f055015750ddf36444705b9921464.tar.gz
gcc-61321991ff5f055015750ddf36444705b9921464.tar.bz2
re PR fortran/26393 (ICE with function returning variable lenght array)
2006-03-01 Paul Thomas <pault@gcc.gnu.org> * iresolve.c (gfc_resolve_dot_product): Remove any difference in treatment of logical types. * trans-intrinsic.c (gfc_conv_intrinsic_dot_product): New function. PR fortran/26393 * trans-decl.c (gfc_get_symbol_decl): Extend condition that symbols must be referenced to include unreferenced symbols in an interface body. PR fortran/20938 * trans-array.c (gfc_conv_resolve_dependencies): Add call to gfc_are_equivalenced_arrays. * symbol.c (gfc_free_equiv_infos, gfc_free_equiv_lists): New functions. (gfc_free_namespace): Call them. * trans-common.c (copy_equiv_list_to_ns): New function. (add_equivalences): Call it. * gfortran.h: Add equiv_lists to gfc_namespace and define gfc_equiv_list and gfc_equiv_info. * dependency.c (gfc_are_equivalenced_arrays): New function. (gfc_check_dependency): Call it. * dependency.h: Prototype for gfc_are_equivalenced_arrays. 2006-03-01 Paul Thomas <pault@gcc.gnu.org> * gfortran.dg/logical_dot_product.f90: New test. PR fortran/26393 * gfortran.dg/used_interface_ref.f90: New test. PR fortran/20938 * gfortran.dg/dependency_2.f90: New test. * gfortran.fortran-torture/execute/where17.f90: New test. * gfortran.fortran-torture/execute/where18.f90: New test. * gfortran.fortran-torture/execute/where19.f90: New test. * gfortran.fortran-torture/execute/where20.f90: New test. From-SVN: r111616
Diffstat (limited to 'gcc/fortran/dependency.c')
-rw-r--r--gcc/fortran/dependency.c49
1 files changed, 49 insertions, 0 deletions
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index 96da3c31e4..f764873 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -359,6 +359,51 @@ gfc_check_fncall_dependency (gfc_expr * other, sym_intent intent,
}
+/* Return 1 if e1 and e2 are equivalenced arrays, either
+ directly or indirectly; ie. equivalence (a,b) for a and b
+ or equivalence (a,c),(b,c). This function uses the equiv_
+ lists, generated in trans-common(add_equivalences), that are
+ guaranteed to pick up indirect equivalences. A rudimentary
+ use is made of the offset to ensure that cases where the
+ source elements are moved down to the destination are not
+ identified as dependencies. */
+
+int
+gfc_are_equivalenced_arrays (gfc_expr *e1, gfc_expr *e2)
+{
+ gfc_equiv_list *l;
+ gfc_equiv_info *s, *fl1, *fl2;
+
+ gcc_assert (e1->expr_type == EXPR_VARIABLE
+ && e2->expr_type == EXPR_VARIABLE);
+
+ if (!e1->symtree->n.sym->attr.in_equivalence
+ || !e2->symtree->n.sym->attr.in_equivalence
+ || !e1->rank
+ || !e2->rank)
+ return 0;
+
+ /* Go through the equiv_lists and return 1 if the variables
+ e1 and e2 are members of the same group and satisfy the
+ requirement on their relative offsets. */
+ for (l = gfc_current_ns->equiv_lists; l; l = l->next)
+ {
+ fl1 = NULL;
+ fl2 = NULL;
+ for (s = l->equiv; s; s = s->next)
+ {
+ if (s->sym == e1->symtree->n.sym)
+ fl1 = s;
+ if (s->sym == e2->symtree->n.sym)
+ fl2 = s;
+ if (fl1 && fl2 && (fl1->offset > fl2->offset))
+ return 1;
+ }
+ }
+return 0;
+}
+
+
/* Return true if the statement body redefines the condition. Returns
true if expr2 depends on expr1. expr1 should be a single term
suitable for the lhs of an assignment. The IDENTICAL flag indicates
@@ -405,6 +450,10 @@ gfc_check_dependency (gfc_expr * expr1, gfc_expr * expr2, bool identical)
return 1;
}
+ /* Return 1 if expr1 and expr2 are equivalenced arrays. */
+ if (gfc_are_equivalenced_arrays (expr1, expr2))
+ return 1;
+
if (expr1->symtree->n.sym != expr2->symtree->n.sym)
return 0;