[PATCH] fortran/30207 -- Fix a WHERE and array section problem

Steve Kargl sgk@troutmask.apl.washington.edu
Thu Dec 14 07:46:00 GMT 2006


The attached patch has been built and tested on i386-*-freebsd.

It short circuits the dependency checking on arrays in a WHERE
statement (and maybe others) when an array section is present.
That is, 

   integer :: z(4) = (/1,1,-1,-1/)
   where (z < 0) z(:) = 1

will lead to an ICE gfc_dep_resolver.  The short circuiting causes
the allocation of temporary array to hold the mask from the z < 0
conditional.  Note the -fdump-tree-original code generated from the
above is quite ugly in comparison to 

   integer :: z(4) = (/1,1,-1,-1/)
   where (z < 0) z = 1

There may be a better way to fix this problem.  Thus, the CC to
Roger, who wrote gfc_dep_resolver.


2006-12-13  Steven G. Kargl  <kargl@gcc.gnu.org>

	PR fortran/30207
	* fortran/dependency.c (gfc_dep_resolver): Short circuit dependency
	checking with an array section.

	* gfortran.fortran-torture/execute/where21.f90: New test.
-- 
Steve
-------------- next part --------------
Index: gcc/testsuite/gfortran.fortran-torture/execute/where21.f90
===================================================================
--- gcc/testsuite/gfortran.fortran-torture/execute/where21.f90	(revision 0)
+++ gcc/testsuite/gfortran.fortran-torture/execute/where21.f90	(revision 0)
@@ -0,0 +1,9 @@
+! { dg-do run }
+! Test fix for PR fortran/30207.
+program a
+  implicit none
+  integer, parameter :: i(4) = (/ 1, 1, 1, 1 /)
+  integer :: z(4) = (/ 1, 1, -1, -1 /)
+  where(z < 0) z(:) = 1
+  if (any(z /= i)) call abort
+end program a
Index: gcc/fortran/dependency.c
===================================================================
--- gcc/fortran/dependency.c	(revision 119854)
+++ gcc/fortran/dependency.c	(working copy)
@@ -1128,7 +1128,7 @@ gfc_dep_resolver (gfc_ref * lref, gfc_re
   while (lref && rref)
     {
       /* We're resolving from the same base symbol, so both refs should be
-	 the same type.  We traverse the reference chain intil we find ranges
+	 the same type.  We traverse the reference chain until we find ranges
 	 that are not equal.  */
       gcc_assert (lref->type == rref->type);
       switch (lref->type)
@@ -1163,6 +1163,15 @@ gfc_dep_resolver (gfc_ref * lref, gfc_re
 		this_dep = gfc_check_element_vs_section (rref, lref, n);
 	      else 
 		{
+		  /* Short circuit "where(z < 0) z(:) = 1" where the array
+		     section notation is causing the problem.  */
+		  if (lref->u.ar.dimen_type[n] == DIMEN_RANGE
+		      && rref->u.ar.dimen_type[n] == 0)
+		    {
+		      this_dep = GFC_DEP_OVERLAP;
+		      break;
+		    }
+
 		  gcc_assert (rref->u.ar.dimen_type[n] == DIMEN_ELEMENT
 			      && lref->u.ar.dimen_type[n] == DIMEN_ELEMENT);
 		  this_dep = gfc_check_element_vs_element (rref, lref, n);


More information about the Fortran mailing list