The  walk_coarray function introduced at
http://gcc.gnu.org/ml/fortran/2011-09/msg00074.html doesn't (like the code it
replaces) support subreferences after the coarray.
These patches are going to change that.

- The first step is, while looking for the coarray reference, to really look for
  it, instead of walking blindly to the last ref (patch 7).
- Then, in the code generated, an offset to the full array has to be added,
  corresponding to the subreference.
  The path taken is to reuse the scalarizer initialization handling for array
  sections subreferences in gfc_walk_variable_expr, and then let the rest
  of the scalarizer do the right thing with that (patch 9).
- For that to work, we need to skip the array ref lookup in
  gfc_walk_variable_expr, which is not valid for coarrays. A new funtion
  gfc_walk_array_ref is introduced, containing all of gfc_walk_variable_expr's 
  code but the array ref lookup (patch 5).
- Then for array elements (like coarray(1,1)), we change them from AR_ELEMENT
  to AR_SECTION so that they get the same treatment as normal arrays in
  gfc_walk_array_ref (patch 8).
- There is a small problem with the latter change; there is an assertion in
  gfc_walk_array_ref that in the AR_SECTION case, rank is non-zero.
  Patch 6 fixes that.

OK?

PS: The patch numbering is odd, because I have tried to reorder patches so that
no regression is introduced.  However, I haven't checked that it is actually the
case.  All I know is at the end, it's fine. ;-)


2011-10-06  Mikael Morin  <mikael.mo...@sfr.fr>

        * trans-array.h (gfc_walk_array_ref): New prototype.
        * trans-array.c (gfc_walk_array_ref): New function, containing
        all but the beginning of gfc_walk_variable_expr's code.
        (gfc_walk_variable_expr): Use gfc_walk_array_ref.
        
diff --git a/trans-array.c b/trans-array.c
index 605b356..1cfe382 100644
--- a/trans-array.c
+++ b/trans-array.c
@@ -7591,14 +7591,22 @@ static gfc_ss *
 gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
 {
   gfc_ref *ref;
-  gfc_array_ref *ar;
-  gfc_ss *newss;
-  int n;
 
   for (ref = expr->ref; ref; ref = ref->next)
     if (ref->type == REF_ARRAY && ref->u.ar.type != AR_ELEMENT)
       break;
 
+  return gfc_walk_array_ref (ss, expr, ref);
+}
+
+
+gfc_ss *
+gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
+{
+  gfc_array_ref *ar;
+  gfc_ss *newss;
+  int n;
+
   for (; ref; ref = ref->next)
     {
       if (ref->type == REF_SUBSTRING)
diff --git a/trans-array.h b/trans-array.h
index 73d8c40..4d737bd 100644
--- a/trans-array.h
+++ b/trans-array.h
@@ -70,6 +70,8 @@ void gfc_trans_static_array_pointer (gfc_symbol *);
 gfc_ss *gfc_walk_expr (gfc_expr *);
 /* Workhorse for gfc_walk_expr.  */
 gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
+/* Workhorse for gfc_walk_variable_expr.  */
+gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref);
 /* Walk the arguments of an elemental function.  */
 gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
 					  gfc_ss_type);
2011-10-06  Mikael Morin  <mikael.mo...@sfr.fr>

        PR fortran/50420
        * trans-array.c (gfc_walk_array_ref): Allow zero rank arrays
        if they are coarrays.
diff --git a/trans-array.c b/trans-array.c
index 1cfe382..4158a32 100644
--- a/trans-array.c
+++ b/trans-array.c
@@ -7688,8 +7688,10 @@ gfc_walk_array_ref (gfc_ss * ss, gfc_expr * expr, gfc_ref * ref)
 		  gcc_unreachable ();
 		}
 	    }
-	  /* We should have at least one non-elemental dimension.  */
-	  gcc_assert (newss->data.info.dimen > 0);
+	  /* We should have at least one non-elemental dimension,
+	     unless we are creating a descriptor for a (scalar) coarray.  */
+	  gcc_assert (newss->data.info.dimen > 0
+		      || newss->data.info.ref->u.ar.as->corank > 0);
 	  ss = newss;
 	  break;
 
2011-10-06  Mikael Morin  <mikael.mo...@sfr.fr>

        PR fortran/50420
        * trans-intrinsic.c (walk_coarray): Allow subreferences after a
        coarray object reference.
diff --git a/trans-intrinsic.c b/trans-intrinsic.c
index c47e678..7d12eb9 100644
--- a/trans-intrinsic.c
+++ b/trans-intrinsic.c
@@ -941,10 +941,16 @@ walk_coarray (gfc_expr *e)
       ss = gfc_get_array_ss (gfc_ss_terminator, e, 0, GFC_SS_SECTION);
 
       ref = e->ref;
-      while (ref->next)
-	ref = ref->next;
+      while (ref)
+	{
+	  if (ref->type == REF_ARRAY
+	      && ref->u.ar.codimen > 0)
+	    break;
+
+	  ref = ref->next;
+	}
 
-      gcc_assert (ref->type == REF_ARRAY && ref->u.ar.codimen > 0);
+      gcc_assert (ref != NULL);
       ref->u.ar.type = AR_FULL;
       ss->data.info.ref = ref;
     }
2011-10-06  Mikael Morin  <mikael.mo...@sfr.fr>

        PR fortran/50420
        * trans-intrinsic.c (walk_coarray): Change AR_ELEMENT to AR_SECTION.
diff --git a/trans-intrinsic.c b/trans-intrinsic.c
index 7d12eb9..e4a8873 100644
--- a/trans-intrinsic.c
+++ b/trans-intrinsic.c
@@ -951,7 +951,8 @@ walk_coarray (gfc_expr *e)
 	}
 
       gcc_assert (ref != NULL);
-      ref->u.ar.type = AR_FULL;
+      if (ref->u.ar.type == AR_ELEMENT)
+	ref->u.ar.type = AR_SECTION;
       ss->data.info.ref = ref;
     }
 
2011-10-06  Mikael Morin  <mikael.mo...@sfr.fr>

        PR fortran/50420
        * trans-intrinsic.c (walk_coarray): Use gfc_walk_array_ref for
        the scalarization chain initialization. 
diff --git a/trans-intrinsic.c b/trans-intrinsic.c
index e4a8873..95f7f0b 100644
--- a/trans-intrinsic.c
+++ b/trans-intrinsic.c
@@ -938,8 +938,6 @@ walk_coarray (gfc_expr *e)
     {
       gfc_ref *ref;
 
-      ss = gfc_get_array_ss (gfc_ss_terminator, e, 0, GFC_SS_SECTION);
-
       ref = e->ref;
       while (ref)
 	{
@@ -953,7 +951,7 @@ walk_coarray (gfc_expr *e)
       gcc_assert (ref != NULL);
       if (ref->u.ar.type == AR_ELEMENT)
 	ref->u.ar.type = AR_SECTION;
-      ss->data.info.ref = ref;
+      ss = gfc_reverse_ss (gfc_walk_array_ref (ss, e, ref));
     }
 
   return ss;

Reply via email to