OSDN Git Service

2011-07-17 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
index 83f0189..4ec892b 100644 (file)
@@ -81,6 +81,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
+#include "gimple.h"
 #include "diagnostic-core.h"   /* For internal_error/fatal_error.  */
 #include "flags.h"
 #include "gfortran.h"
@@ -485,7 +486,7 @@ gfc_free_ss (gfc_ss * ss)
       break;
     }
 
-  gfc_free (ss);
+  free (ss);
 }
 
 
@@ -562,7 +563,7 @@ gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
   tree tmp;
 
   if (as && as->type == AS_EXPLICIT)
-    for (n = 0; n < se->loop->dimen; n++)
+    for (n = 0; n < se->loop->dimen + se->loop->codimen; n++)
       {
        dim = se->ss->data.info.dim[n];
        gcc_assert (dim < as->rank);
@@ -576,18 +577,22 @@ gfc_set_loop_bounds_from_array_spec (gfc_interface_mapping * mapping,
            gfc_add_block_to_block (&se->post, &tmpse.post);
            lower = fold_convert (gfc_array_index_type, tmpse.expr);
 
-           /* ...and the upper bound.  */
-           gfc_init_se (&tmpse, NULL);
-           gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
-           gfc_add_block_to_block (&se->pre, &tmpse.pre);
-           gfc_add_block_to_block (&se->post, &tmpse.post);
-           upper = fold_convert (gfc_array_index_type, tmpse.expr);
-
-           /* Set the upper bound of the loop to UPPER - LOWER.  */
-           tmp = fold_build2_loc (input_location, MINUS_EXPR,
-                                  gfc_array_index_type, upper, lower);
-           tmp = gfc_evaluate_now (tmp, &se->pre);
-           se->loop->to[n] = tmp;
+           if (se->loop->codimen == 0
+               || n < se->loop->dimen + se->loop->codimen - 1)
+             {
+               /* ...and the upper bound.  */
+               gfc_init_se (&tmpse, NULL);
+               gfc_apply_interface_mapping (mapping, &tmpse, as->upper[dim]);
+               gfc_add_block_to_block (&se->pre, &tmpse.pre);
+               gfc_add_block_to_block (&se->post, &tmpse.post);
+               upper = fold_convert (gfc_array_index_type, tmpse.expr);
+
+               /* Set the upper bound of the loop to UPPER - LOWER.  */
+               tmp = fold_build2_loc (input_location, MINUS_EXPR,
+                                      gfc_array_index_type, upper, lower);
+               tmp = gfc_evaluate_now (tmp, &se->pre);
+               se->loop->to[n] = tmp;
+             }
          }
       }
 }
@@ -626,18 +631,27 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
     {
       /* Allocate the temporary.  */
       onstack = !dynamic && initial == NULL_TREE
-                        && gfc_can_put_var_on_stack (size);
+                        && (gfc_option.flag_stack_arrays
+                            || gfc_can_put_var_on_stack (size));
 
       if (onstack)
        {
          /* Make a temporary variable to hold the data.  */
          tmp = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (nelem),
                                 nelem, gfc_index_one_node);
+         tmp = gfc_evaluate_now (tmp, pre);
          tmp = build_range_type (gfc_array_index_type, gfc_index_zero_node,
                                  tmp);
          tmp = build_array_type (gfc_get_element_type (TREE_TYPE (desc)),
                                  tmp);
          tmp = gfc_create_var (tmp, "A");
+         /* If we're here only because of -fstack-arrays we have to
+            emit a DECL_EXPR to make the gimplifier emit alloca calls.  */
+         if (!gfc_can_put_var_on_stack (size))
+           gfc_add_expr_to_block (pre,
+                                  fold_build1_loc (input_location,
+                                                   DECL_EXPR, TREE_TYPE (tmp),
+                                                   tmp));
          tmp = gfc_build_addr_expr (NULL_TREE, tmp);
          gfc_conv_descriptor_data_set (pre, desc, tmp);
        }
@@ -885,6 +899,13 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
                              size, tmp);
       size = gfc_evaluate_now (size, pre);
     }
+  for (n = info->dimen; n < info->dimen + info->codimen; n++)
+    {
+      gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
+                                      gfc_index_zero_node);
+      if (n < info->dimen + info->codimen - 1)
+       gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], loop->to[n]);
+    }
 
   /* Get the size of the array.  */
 
@@ -1343,7 +1364,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                  p = gfc_constructor_next (p);
                }
 
-             bound = build_int_cst (NULL_TREE, n - 1);
+             bound = size_int (n - 1);
               /* Create an array type to hold them.  */
              tmptype = build_range_type (gfc_array_index_type,
                                          gfc_index_zero_node, bound);
@@ -1369,7 +1390,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
              init = gfc_build_addr_expr (NULL_TREE, init);
 
              size = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (type));
-             bound = build_int_cst (NULL_TREE, n * size);
+             bound = build_int_cst (size_type_node, n * size);
              tmp = build_call_expr_loc (input_location,
                                     built_in_decls[BUILT_IN_MEMCPY], 3,
                                     tmp, init, bound);
@@ -1777,7 +1798,7 @@ gfc_trans_constant_array_constructor (gfc_loopinfo * loop,
   info->data = gfc_build_addr_expr (NULL_TREE, tmp);
   info->offset = gfc_index_zero_node;
 
-  for (i = 0; i < info->dimen; i++)
+  for (i = 0; i < info->dimen + info->codimen; i++)
     {
       info->delta[i] = gfc_index_zero_node;
       info->start[i] = gfc_index_zero_node;
@@ -2018,7 +2039,7 @@ gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
   int n;
   int dim;
 
-  for (n = 0; n < loop->dimen; n++)
+  for (n = 0; n < loop->dimen + loop->codimen; n++)
     {
       dim = info->dim[n];
       if (info->ref->u.ar.dimen_type[dim] == DIMEN_VECTOR
@@ -2223,7 +2244,7 @@ gfc_init_loopinfo (gfc_loopinfo * loop)
   for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
     {
       loop->order[n] = n;
-      loop->reverse[n] = GFC_CANNOT_REVERSE;
+      loop->reverse[n] = GFC_INHIBIT_REVERSE;
     }
 
   loop->ss = gfc_ss_terminator;
@@ -2409,7 +2430,7 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
                               fold_convert (long_integer_type_node, index),
                               fold_convert (long_integer_type_node, tmp_lo),
                               fold_convert (long_integer_type_node, tmp_up));
-      gfc_free (msg);
+      free (msg);
     }
   else
     {
@@ -2427,7 +2448,7 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
       gfc_trans_runtime_check (true, false, fault, &se->pre, where, msg,
                               fold_convert (long_integer_type_node, index),
                               fold_convert (long_integer_type_node, tmp_lo));
-      gfc_free (msg);
+      free (msg);
     }
 
   return index;
@@ -2452,6 +2473,9 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
       gcc_assert (ar->type != AR_ELEMENT);
       switch (ar->dimen_type[dim])
        {
+       case DIMEN_THIS_IMAGE:
+         gcc_unreachable ();
+         break;
        case DIMEN_ELEMENT:
          /* Elemental dimension.  */
          gcc_assert (info->subscript[dim]
@@ -2597,7 +2621,24 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
   gfc_se tmpse;
 
   if (ar->dimen == 0)
-    return;
+    {
+      gcc_assert (ar->codimen);
+
+      if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (se->expr)))
+       se->expr = build_fold_indirect_ref (gfc_conv_array_data (se->expr));
+      else
+       {
+         if (GFC_ARRAY_TYPE_P (TREE_TYPE (se->expr))
+             && TREE_CODE (TREE_TYPE (se->expr)) == POINTER_TYPE)
+           se->expr = build_fold_indirect_ref_loc (input_location, se->expr);
+       
+         /* Use the actual tree type and not the wrapped coarray. */
+         se->expr = fold_convert (TYPE_MAIN_VARIANT (TREE_TYPE (se->expr)),
+                                  se->expr);
+       }
+
+      return;
+    }
 
   /* Handle scalarized references separately.  */
   if (ar->type != AR_ELEMENT)
@@ -2645,7 +2686,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
                                   fold_convert (long_integer_type_node,
                                                 indexse.expr),
                                   fold_convert (long_integer_type_node, tmp));
-         gfc_free (msg);
+         free (msg);
 
          /* Upper bound, but not for the last dimension of assumed-size
             arrays.  */
@@ -2669,7 +2710,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
                                   fold_convert (long_integer_type_node,
                                                 indexse.expr),
                                   fold_convert (long_integer_type_node, tmp));
-             gfc_free (msg);
+             free (msg);
            }
        }
 
@@ -2813,7 +2854,7 @@ gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
 
   gcc_assert (!loop->array_parameter);
 
-  for (dim = loop->dimen - 1; dim >= 0; dim--)
+  for (dim = loop->dimen + loop->codimen - 1; dim >= 0; dim--)
     {
       n = loop->order[dim];
 
@@ -2967,7 +3008,7 @@ gfc_trans_scalarizing_loops (gfc_loopinfo * loop, stmtblock_t * body)
 
   pblock = body;
   /* Generate the loops.  */
-  for (dim = 0; dim < loop->dimen; dim++)
+  for (dim = 0; dim < loop->dimen + loop->codimen; dim++)
     {
       n = loop->order[dim];
       gfc_trans_scalarized_loop_end (loop, n, pblock);
@@ -3043,11 +3084,12 @@ gfc_trans_scalarized_loop_boundary (gfc_loopinfo * loop, stmtblock_t * body)
 /* Calculate the lower bound of an array section.  */
 
 static void
-gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
+gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim,
+                             bool coarray, bool coarray_last)
 {
   gfc_expr *start;
   gfc_expr *end;
-  gfc_expr *stride;
+  gfc_expr *stride = NULL;
   tree desc;
   gfc_se se;
   gfc_ss_info *info;
@@ -3060,8 +3102,9 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
     {
       /* We use a zero-based index to access the vector.  */
       info->start[dim] = gfc_index_zero_node;
-      info->stride[dim] = gfc_index_one_node;
       info->end[dim] = NULL;
+      if (!coarray)
+       info->stride[dim] = gfc_index_one_node;
       return;
     }
 
@@ -3069,7 +3112,8 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
   desc = info->descriptor;
   start = info->ref->u.ar.start[dim];
   end = info->ref->u.ar.end[dim];
-  stride = info->ref->u.ar.stride[dim];
+  if (!coarray)
+    stride = info->ref->u.ar.stride[dim];
 
   /* Calculate the start of the range.  For vector subscripts this will
      be the range of the vector.  */
@@ -3091,25 +3135,28 @@ gfc_conv_section_startstride (gfc_loopinfo * loop, gfc_ss * ss, int dim)
   /* Similarly calculate the end.  Although this is not used in the
      scalarizer, it is needed when checking bounds and where the end
      is an expression with side-effects.  */
-  if (end)
-    {
-      /* Specified section start.  */
-      gfc_init_se (&se, NULL);
-      gfc_conv_expr_type (&se, end, gfc_array_index_type);
-      gfc_add_block_to_block (&loop->pre, &se.pre);
-      info->end[dim] = se.expr;
-    }
-  else
+  if (!coarray_last)
     {
-      /* No upper bound specified so use the bound of the array.  */
-      info->end[dim] = gfc_conv_array_ubound (desc, dim);
+      if (end)
+       {
+         /* Specified section start.  */
+         gfc_init_se (&se, NULL);
+         gfc_conv_expr_type (&se, end, gfc_array_index_type);
+         gfc_add_block_to_block (&loop->pre, &se.pre);
+         info->end[dim] = se.expr;
+       }
+      else
+       {
+         /* No upper bound specified so use the bound of the array.  */
+         info->end[dim] = gfc_conv_array_ubound (desc, dim);
+       }
+      info->end[dim] = gfc_evaluate_now (info->end[dim], &loop->pre);
     }
-  info->end[dim] = gfc_evaluate_now (info->end[dim], &loop->pre);
 
   /* Calculate the stride.  */
-  if (stride == NULL)
+  if (!coarray && stride == NULL)
     info->stride[dim] = gfc_index_one_node;
-  else
+  else if (!coarray)
     {
       gfc_init_se (&se, NULL);
       gfc_conv_expr_type (&se, stride, gfc_array_index_type);
@@ -3143,6 +3190,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
        case GFC_SS_FUNCTION:
        case GFC_SS_COMPONENT:
          loop->dimen = ss->data.info.dimen;
+         loop->codimen = ss->data.info.codimen;
          break;
 
        /* As usual, lbound and ubound are exceptions!.  */
@@ -3152,6 +3200,15 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
            case GFC_ISYM_LBOUND:
            case GFC_ISYM_UBOUND:
              loop->dimen = ss->data.info.dimen;
+             loop->codimen = 0;
+             break;
+
+           case GFC_ISYM_LCOBOUND:
+           case GFC_ISYM_UCOBOUND:
+           case GFC_ISYM_THIS_IMAGE:
+             loop->dimen = ss->data.info.dimen;
+             loop->codimen = ss->data.info.codimen;
+             break;
 
            default:
              break;
@@ -3164,7 +3221,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
 
   /* We should have determined the rank of the expression by now.  If
      not, that's bad news.  */
-  gcc_assert (loop->dimen != 0);
+  gcc_assert (loop->dimen + loop->codimen != 0);
 
   /* Loop over all the SS in the chain.  */
   for (ss = loop->ss; ss != gfc_ss_terminator; ss = ss->loop_chain)
@@ -3179,7 +3236,14 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
          gfc_conv_ss_descriptor (&loop->pre, ss, !loop->array_parameter);
 
          for (n = 0; n < ss->data.info.dimen; n++)
-           gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n]);
+           gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n],
+                                         false, false);
+         for (n = ss->data.info.dimen;
+              n < ss->data.info.dimen + ss->data.info.codimen; n++)
+           gfc_conv_section_startstride (loop, ss, ss->data.info.dim[n], true,
+                                         n == ss->data.info.dimen
+                                              + ss->data.info.codimen -1);
+
          break;
 
        case GFC_SS_INTRINSIC:
@@ -3188,7 +3252,11 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
            /* Fall through to supply start and stride.  */
            case GFC_ISYM_LBOUND:
            case GFC_ISYM_UBOUND:
+           case GFC_ISYM_LCOBOUND:
+           case GFC_ISYM_UCOBOUND:
+           case GFC_ISYM_THIS_IMAGE:
              break;
+
            default:
              continue;
            }
@@ -3264,7 +3332,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                        "of array '%s'", dim + 1, ss->expr->symtree->name);
              gfc_trans_runtime_check (true, false, tmp, &inner,
                                       &ss->expr->where, msg);
-             gfc_free (msg);
+             free (msg);
 
              desc = ss->data.info.descriptor;
 
@@ -3331,7 +3399,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                     fold_convert (long_integer_type_node, info->start[dim]),
                     fold_convert (long_integer_type_node, lbound),
                     fold_convert (long_integer_type_node, ubound));
-                 gfc_free (msg);
+                 free (msg);
                }
              else
                {
@@ -3347,7 +3415,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                                           &ss->expr->where, msg,
                     fold_convert (long_integer_type_node, info->start[dim]),
                     fold_convert (long_integer_type_node, lbound));
-                 gfc_free (msg);
+                 free (msg);
                }
              
              /* Compute the last element of the range, which is not
@@ -3385,7 +3453,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                     fold_convert (long_integer_type_node, tmp),
                     fold_convert (long_integer_type_node, ubound), 
                     fold_convert (long_integer_type_node, lbound));
-                 gfc_free (msg);
+                 free (msg);
                }
              else
                {
@@ -3396,7 +3464,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                                           &ss->expr->where, msg,
                     fold_convert (long_integer_type_node, tmp),
                     fold_convert (long_integer_type_node, lbound));
-                 gfc_free (msg);
+                 free (msg);
                }
 
              /* Check the section sizes match.  */
@@ -3427,7 +3495,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                        fold_convert (long_integer_type_node, tmp),
                        fold_convert (long_integer_type_node, size[n]));
 
-                 gfc_free (msg);
+                 free (msg);
                }
              else
                size[n] = gfc_evaluate_now (tmp, &inner);
@@ -3697,6 +3765,7 @@ temporary:
       loop->temp_ss->data.temp.type = base_type;
       loop->temp_ss->string_length = dest->string_length;
       loop->temp_ss->data.temp.dimen = loop->dimen;
+      loop->temp_ss->data.temp.codimen = loop->codimen;
       loop->temp_ss->next = gfc_ss_terminator;
       gfc_add_ss_to_loop (loop, loop->temp_ss);
     }
@@ -3725,7 +3794,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
   mpz_t i;
 
   mpz_init (i);
-  for (n = 0; n < loop->dimen; n++)
+  for (n = 0; n < loop->dimen + loop->codimen; n++)
     {
       loopspec[n] = NULL;
       dynamic[n] = false;
@@ -3807,7 +3876,8 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
             known lower bound
             known upper bound
           */
-         else if (loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
+         else if ((loopspec[n]->type == GFC_SS_CONSTRUCTOR && dynamic[n])
+                  || n >= loop->dimen)
            loopspec[n] = ss;
          else if (integer_onep (info->stride[dim])
                   && !integer_onep (specinfo->stride[spec_dim]))
@@ -3833,7 +3903,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
 
       /* Set the extents of this range.  */
       cshape = loopspec[n]->shape;
-      if (cshape && INTEGER_CST_P (info->start[dim])
+      if (n < loop->dimen && cshape && INTEGER_CST_P (info->start[dim])
          && INTEGER_CST_P (info->stride[dim]))
        {
          loop->from[n] = info->start[dim];
@@ -3877,9 +3947,9 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
        }
 
       /* Transform everything so we have a simple incrementing variable.  */
-      if (integer_onep (info->stride[dim]))
+      if (n < loop->dimen && integer_onep (info->stride[dim]))
        info->delta[dim] = gfc_index_zero_node;
-      else
+      else if (n < loop->dimen)
        {
          /* Set the delta for this section.  */
          info->delta[dim] = gfc_evaluate_now (loop->from[n], &loop->pre);
@@ -4012,17 +4082,17 @@ gfc_conv_array_extent_dim (tree lbound, tree ubound, tree* or_expr)
 
 
 /* For an array descriptor, get the total number of elements.  This is just
-   the product of the extents along all dimensions.  */
+   the product of the extents along from_dim to to_dim.  */
 
-tree
-gfc_conv_descriptor_size (tree desc, int rank)
+static tree
+gfc_conv_descriptor_size_1 (tree desc, int from_dim, int to_dim)
 {
   tree res;
   int dim;
 
   res = gfc_index_one_node;
 
-  for (dim = 0; dim < rank; ++dim)
+  for (dim = from_dim; dim < to_dim; ++dim)
     {
       tree lbound;
       tree ubound;
@@ -4040,21 +4110,24 @@ gfc_conv_descriptor_size (tree desc, int rank)
 }
 
 
-/* Helper function for marking a boolean expression tree as unlikely.  */
+/* Full size of an array.  */
 
-static tree
-gfc_unlikely (tree cond)
+tree
+gfc_conv_descriptor_size (tree desc, int rank)
 {
-  tree tmp;
+  return gfc_conv_descriptor_size_1 (desc, 0, rank);
+}
 
-  cond = fold_convert (long_integer_type_node, cond);
-  tmp = build_zero_cst (long_integer_type_node);
-  cond = build_call_expr_loc (input_location,
-                             built_in_decls[BUILT_IN_EXPECT], 2, cond, tmp);
-  cond = fold_convert (boolean_type_node, cond);
-  return cond;
+
+/* Size of a coarray for all dimensions but the last.  */
+
+tree
+gfc_conv_descriptor_cosize (tree desc, int rank, int corank)
+{
+  return gfc_conv_descriptor_size_1 (desc, rank, rank + corank - 1);
 }
 
+
 /* Fills in an array descriptor, and returns the size of the array.
    The size will be a simple_val, ie a variable or a constant.  Also
    calculates the offset of the base.  The pointer argument overflow,
@@ -4074,7 +4147,11 @@ gfc_unlikely (tree cond)
        overflow += size == 0 ? 0: (MAX/size < stride ? 1: 0);
        stride = stride * size;
       }
+    for (n = rank; n < rank+corank; n++)
+      (Set lcobound/ucobound as above.)
     element_size = sizeof (array element);
+    if (!rank)
+      return element_size
     stride = (size_t) stride;
     overflow += element_size == 0 ? 0: (MAX/element_size < stride ? 1: 0);
     stride = stride * element_size;
@@ -4244,6 +4321,10 @@ gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
   tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
   /* Convert to size_t.  */
   element_size = fold_convert (size_type_node, tmp);
+
+  if (rank == 0)
+    return element_size;
+
   stride = fold_convert (size_type_node, stride);
 
   /* First check for overflow. Since an array of type character can
@@ -4305,18 +4386,18 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
 {
   tree tmp;
   tree pointer;
-  tree offset;
+  tree offset = NULL_TREE;
   tree size;
   tree msg;
-  tree error;
+  tree error = NULL_TREE;
   tree overflow; /* Boolean storing whether size calculation overflows.  */
-  tree var_overflow;
+  tree var_overflow = NULL_TREE;
   tree cond;
   stmtblock_t elseblock;
   gfc_expr **lower;
   gfc_expr **upper;
   gfc_ref *ref, *prev_ref = NULL;
-  bool allocatable_array, coarray;
+  bool allocatable, coarray, dimension;
 
   ref = expr->ref;
 
@@ -4334,22 +4415,19 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
 
   if (!prev_ref)
     {
-      allocatable_array = expr->symtree->n.sym->attr.allocatable;
+      allocatable = expr->symtree->n.sym->attr.allocatable;
       coarray = expr->symtree->n.sym->attr.codimension;
+      dimension = expr->symtree->n.sym->attr.dimension;
     }
   else
     {
-      allocatable_array = prev_ref->u.c.component->attr.allocatable;
+      allocatable = prev_ref->u.c.component->attr.allocatable;
       coarray = prev_ref->u.c.component->attr.codimension;
+      dimension = prev_ref->u.c.component->attr.dimension;
     }
 
-  /* Return if this is a scalar coarray.  */
-  if ((!prev_ref && !expr->symtree->n.sym->attr.dimension)
-      || (prev_ref && !prev_ref->u.c.component->attr.dimension))
-    {
-      gcc_assert (coarray);
-      return false;
-    }
+  if (!dimension)
+    gcc_assert (coarray);
 
   /* Figure out the size of the array.  */
   switch (ref->u.ar.type)
@@ -4384,16 +4462,20 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
   size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
                              ref->u.ar.as->corank, &offset, lower, upper,
                              &se->pre, &overflow);
+  if (dimension)
+    {
 
-  var_overflow = gfc_create_var (integer_type_node, "overflow");
-  gfc_add_modify (&se->pre, var_overflow, overflow);
+      var_overflow = gfc_create_var (integer_type_node, "overflow");
+      gfc_add_modify (&se->pre, var_overflow, overflow);
 
-  /* Generate the block of code handling overflow.  */
-  msg = gfc_build_addr_expr (pchar_type_node, gfc_build_localized_cstring_const
+      /* Generate the block of code handling overflow.  */
+      msg = gfc_build_addr_expr (pchar_type_node,
+               gfc_build_localized_cstring_const
                        ("Integer overflow when calculating the amount of "
                         "memory to allocate"));
-  error = build_call_expr_loc (input_location,
-                          gfor_fndecl_runtime_error, 1, msg);
+      error = build_call_expr_loc (input_location, gfor_fndecl_runtime_error,
+                                  1, msg);
+    }
 
   if (pstat != NULL_TREE && !integer_zerop (pstat))
     {
@@ -4420,23 +4502,30 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
   STRIP_NOPS (pointer);
 
   /* The allocate_array variants take the old pointer as first argument.  */
-  if (allocatable_array)
-    tmp = gfc_allocate_array_with_status (&elseblock, pointer, size, pstat, expr);
+  if (allocatable)
+    tmp = gfc_allocate_allocatable_with_status (&elseblock,
+                                               pointer, size, pstat, expr);
   else
-    tmp = gfc_allocate_with_status (&elseblock, size, pstat);
+    tmp = gfc_allocate_with_status (&elseblock, size, pstat, false);
   tmp = fold_build2_loc (input_location, MODIFY_EXPR, void_type_node, pointer,
                         tmp);
 
   gfc_add_expr_to_block (&elseblock, tmp);
 
-  cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR, boolean_type_node,
-                                       var_overflow, integer_zero_node));
-  tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, 
-                        error, gfc_finish_block (&elseblock));
+  if (dimension)
+    {
+      cond = gfc_unlikely (fold_build2_loc (input_location, NE_EXPR,
+                          boolean_type_node, var_overflow, integer_zero_node));
+      tmp = fold_build3_loc (input_location, COND_EXPR, void_type_node, cond, 
+                            error, gfc_finish_block (&elseblock));
+    }
+  else
+    tmp = gfc_finish_block (&elseblock);
 
   gfc_add_expr_to_block (&se->pre, tmp);
 
-  gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
+  if (dimension)
+    gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
 
   if ((expr->ts.type == BT_DERIVED || expr->ts.type == BT_CLASS)
        && expr->ts.u.derived->attr.alloc_comp)
@@ -4490,7 +4579,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
   gfc_se se;
   HOST_WIDE_INT hi;
   unsigned HOST_WIDE_INT lo;
-  tree index;
+  tree index, range;
   VEC(constructor_elt,gc) *v = NULL;
 
   switch (expr->expr_type)
@@ -4544,28 +4633,56 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
           else
             index = NULL_TREE;
 
+         if (mpz_cmp_si (c->repeat, 1) > 0)
+           {
+             tree tmp1, tmp2;
+             mpz_t maxval;
+
+             mpz_init (maxval);
+             mpz_add (maxval, c->offset, c->repeat);
+             mpz_sub_ui (maxval, maxval, 1);
+             tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
+             if (mpz_cmp_si (c->offset, 0) != 0)
+               {
+                 mpz_add_ui (maxval, c->offset, 1);
+                 tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
+               }
+             else
+               tmp1 = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
+
+             range = fold_build2 (RANGE_EXPR, gfc_array_index_type, tmp1, tmp2);
+             mpz_clear (maxval);
+           }
+         else
+           range = NULL;
+
           gfc_init_se (&se, NULL);
          switch (c->expr->expr_type)
            {
            case EXPR_CONSTANT:
              gfc_conv_constant (&se, c->expr);
-             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
 
            case EXPR_STRUCTURE:
               gfc_conv_structure (&se, c->expr, 1);
-             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
 
-
            default:
              /* Catch those occasional beasts that do not simplify
                 for one reason or another, assuming that if they are
                 standard defying the frontend will catch them.  */
              gfc_conv_expr (&se, c->expr);
-             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
            }
+
+         if (range == NULL_TREE)
+           CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
+         else
+           {
+             if (index != NULL_TREE)
+               CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
+             CONSTRUCTOR_APPEND_ELT (v, range, se.expr);
+           }
         }
       break;
 
@@ -4583,6 +4700,43 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
 }
 
 
+/* Generate code to evaluate non-constant coarray cobounds.  */
+
+void
+gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
+                         const gfc_symbol *sym)
+{
+  int dim;
+  tree ubound;
+  tree lbound;
+  gfc_se se;
+  gfc_array_spec *as;
+
+  as = sym->as;
+
+  for (dim = as->rank; dim < as->rank + as->corank; dim++)
+    {
+      /* Evaluate non-constant array bound expressions.  */
+      lbound = GFC_TYPE_ARRAY_LBOUND (type, dim);
+      if (as->lower[dim] && !INTEGER_CST_P (lbound))
+        {
+          gfc_init_se (&se, NULL);
+          gfc_conv_expr_type (&se, as->lower[dim], gfc_array_index_type);
+          gfc_add_block_to_block (pblock, &se.pre);
+          gfc_add_modify (pblock, lbound, se.expr);
+        }
+      ubound = GFC_TYPE_ARRAY_UBOUND (type, dim);
+      if (as->upper[dim] && !INTEGER_CST_P (ubound))
+        {
+          gfc_init_se (&se, NULL);
+          gfc_conv_expr_type (&se, as->upper[dim], gfc_array_index_type);
+          gfc_add_block_to_block (pblock, &se.pre);
+          gfc_add_modify (pblock, ubound, se.expr);
+        }
+    }
+}
+
+
 /* Generate code to evaluate non-constant array bounds.  Sets *poffset and
    returns the size (in elements) of the array.  */
 
@@ -4664,6 +4818,7 @@ gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
       size = stride;
     }
 
+  gfc_trans_array_cobounds (type, pblock, sym);
   gfc_trans_vla_type_sizes (sym, pblock);
 
   *poffset = offset;
@@ -4679,9 +4834,11 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
 {
   stmtblock_t init;
   tree type;
-  tree tmp;
+  tree tmp = NULL_TREE;
   tree size;
   tree offset;
+  tree space;
+  tree inittree;
   bool onstack;
 
   gcc_assert (!(sym->attr.pointer || sym->attr.allocatable));
@@ -4738,15 +4895,30 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
       return;
     }
 
-  /* The size is the number of elements in the array, so multiply by the
-     size of an element to get the total size.  */
-  tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
-  size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
-                         size, fold_convert (gfc_array_index_type, tmp));
+  if (gfc_option.flag_stack_arrays)
+    {
+      gcc_assert (TREE_CODE (TREE_TYPE (decl)) == POINTER_TYPE);
+      space = build_decl (sym->declared_at.lb->location,
+                         VAR_DECL, create_tmp_var_name ("A"),
+                         TREE_TYPE (TREE_TYPE (decl)));
+      gfc_trans_vla_type_sizes (sym, &init);
+    }
+  else
+    {
+      /* The size is the number of elements in the array, so multiply by the
+        size of an element to get the total size.  */
+      tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
+      size = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                             size, fold_convert (gfc_array_index_type, tmp));
 
-  /* Allocate memory to hold the data.  */
-  tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
-  gfc_add_modify (&init, decl, tmp);
+      /* Allocate memory to hold the data.  */
+      tmp = gfc_call_malloc (&init, TREE_TYPE (decl), size);
+      gfc_add_modify (&init, decl, tmp);
+
+      /* Free the temporary.  */
+      tmp = gfc_call_free (convert (pvoid_type_node, decl));
+      space = NULL_TREE;
+    }
 
   /* Set offset of the array.  */
   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
@@ -4755,10 +4927,26 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym,
   /* Automatic arrays should not have initializers.  */
   gcc_assert (!sym->value);
 
-  /* Free the temporary.  */
-  tmp = gfc_call_free (convert (pvoid_type_node, decl));
+  inittree = gfc_finish_block (&init);
 
-  gfc_add_init_cleanup (block, gfc_finish_block (&init), tmp);
+  if (space)
+    {
+      tree addr;
+      pushdecl (space);
+
+      /* Don't create new scope, emit the DECL_EXPR in exactly the scope
+         where also space is located.  */
+      gfc_init_block (&init);
+      tmp = fold_build1_loc (input_location, DECL_EXPR,
+                            TREE_TYPE (space), space);
+      gfc_add_expr_to_block (&init, tmp);
+      addr = fold_build1_loc (sym->declared_at.lb->location,
+                             ADDR_EXPR, TREE_TYPE (decl), space);
+      gfc_add_modify (&init, decl, addr);
+      gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
+      tmp = NULL_TREE;
+    }
+  gfc_add_init_cleanup (block, inittree, tmp);
 }
 
 
@@ -5019,7 +5207,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
                        fold_convert (long_integer_type_node, temp),
                        fold_convert (long_integer_type_node, stride2));
 
-             gfc_free (msg);
+             free (msg);
            }
        }
       else
@@ -5096,6 +5284,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
        }
     }
 
+  gfc_trans_array_cobounds (type, &init, sym);
+
   /* Set the offset.  */
   if (TREE_CODE (GFC_TYPE_ARRAY_OFFSET (type)) == VAR_DECL)
     gfc_add_modify (&init, GFC_TYPE_ARRAY_OFFSET (type), offset);
@@ -5626,6 +5816,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
 
       se->string_length = loop.temp_ss->string_length;
       loop.temp_ss->data.temp.dimen = loop.dimen;
+      loop.temp_ss->data.temp.codimen = loop.codimen;
       gfc_add_ss_to_loop (&loop, loop.temp_ss);
     }
 
@@ -5669,7 +5860,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
 
       lse.string_length = rse.string_length;
       tmp = gfc_trans_scalar_assign (&lse, &rse, expr->ts, true,
-                                    expr->expr_type == EXPR_VARIABLE, true);
+                                    expr->expr_type == EXPR_VARIABLE
+                                    || expr->expr_type == EXPR_ARRAY, true);
       gfc_add_expr_to_block (&block, tmp);
 
       /* Finish the copying loops.  */
@@ -5689,7 +5881,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
         limits will be the limits of the section.
         A function may decide to repack the array to speed up access, but
         we're not bothered about that here.  */
-      int dim, ndim;
+      int dim, ndim, codim;
       tree parm;
       tree parmtype;
       tree stride;
@@ -5712,8 +5904,9 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
        {
          /* Otherwise make a new one.  */
          parmtype = gfc_get_element_type (TREE_TYPE (desc));
-         parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
-                                               loop.from, loop.to, 0,
+         parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen,
+                                               loop.codimen, loop.from,
+                                               loop.to, 0,
                                                GFC_ARRAY_UNKNOWN, false);
          parm = gfc_create_var (parmtype, "parm");
        }
@@ -5744,6 +5937,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
        base = NULL_TREE;
 
       ndim = info->ref ? info->ref->u.ar.dimen : info->dimen;
+      codim = info->codimen;
       for (n = 0; n < ndim; n++)
        {
          stride = gfc_conv_array_stride (desc, n);
@@ -5845,6 +6039,26 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
                                          gfc_rank_cst[dim], stride);
        }
 
+      for (n = ndim; n < ndim + codim; n++)
+       {
+         /* look for the corresponding scalarizer dimension: dim.  */
+         for (dim = 0; dim < ndim + codim; dim++)
+           if (info->dim[dim] == n)
+             break;
+
+         /* loop exited early: the DIM being looked for has been found.  */
+         gcc_assert (dim < ndim + codim);
+
+         from = loop.from[dim];
+         to = loop.to[dim];
+         gfc_conv_descriptor_lbound_set (&loop.pre, parm,
+                                         gfc_rank_cst[dim], from);
+         if (n < ndim + codim - 1)
+           gfc_conv_descriptor_ubound_set (&loop.pre, parm,
+                                           gfc_rank_cst[dim], to);
+         dim++;
+       }
+
       if (se->data_not_needed)
        gfc_conv_descriptor_data_set (&loop.pre, parm,
                                      gfc_index_zero_node);
@@ -6097,10 +6311,11 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
        && expr->ts.u.derived->attr.alloc_comp
        && expr->expr_type != EXPR_VARIABLE)
     {
-      tmp = build_fold_indirect_ref_loc (input_location,
-                                    se->expr);
+      tmp = build_fold_indirect_ref_loc (input_location, se->expr);
       tmp = gfc_deallocate_alloc_comp (expr->ts.u.derived, tmp, expr->rank);
-      gfc_add_expr_to_block (&se->post, tmp);
+
+      /* The components shall be deallocated before their containing entity.  */
+      gfc_prepend_expr_to_block (&se->post, tmp);
     }
 
   if (g77 || (fsym && fsym->attr.contiguous
@@ -6178,7 +6393,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
 
          gfc_trans_runtime_check (false, true, tmp, &se->pre,
                                   &expr->where, msg);
-         gfc_free (msg);
+         free (msg);
        }
 
       gfc_start_block (&block);
@@ -6519,18 +6734,22 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
       switch (purpose)
        {
        case DEALLOCATE_ALLOC_COMP:
+         if (cmp_has_alloc_comps && !c->attr.pointer)
+           {
+             /* Do not deallocate the components of ultimate pointer
+                components.  */
+             comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
+                                     decl, cdecl, NULL_TREE);
+             rank = c->as ? c->as->rank : 0;
+             tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
+                                          rank, purpose);
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
+
          if (c->attr.allocatable && c->attr.dimension)
            {
              comp = fold_build3_loc (input_location, COMPONENT_REF, ctype,
                                      decl, cdecl, NULL_TREE);
-             if (cmp_has_alloc_comps && !c->attr.pointer)
-               {
-                 /* Do not deallocate the components of ultimate pointer
-                    components.  */
-                 tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
-                                              c->as->rank, purpose);
-                 gfc_add_expr_to_block (&fnblock, tmp);
-               }
              tmp = gfc_trans_dealloc_allocated (comp);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
@@ -6706,6 +6925,8 @@ get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
   tree stride;
   tree cond, cond1, cond3, cond4;
   tree tmp;
+  gfc_ref *ref;
+
   if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (desc)))
     {
       tmp = gfc_rank_cst[dim];
@@ -6739,6 +6960,14 @@ get_std_lbound (gfc_expr *expr, tree desc, int dim, bool assumed_size)
   else if (expr->expr_type == EXPR_VARIABLE)
     {
       tmp = TREE_TYPE (expr->symtree->n.sym->backend_decl);
+      for (ref = expr->ref; ref; ref = ref->next)
+       {
+         if (ref->type == REF_COMPONENT
+               && ref->u.c.component->as
+               && ref->next
+               && ref->next->u.ar.type == AR_FULL)
+           tmp = TREE_TYPE (ref->u.c.component->backend_decl);
+       }
       return GFC_TYPE_ARRAY_LBOUND(tmp, dim);
     }
   else if (expr->expr_type == EXPR_FUNCTION)
@@ -7156,6 +7385,8 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
                 "allocatable attribute or derived type without allocatable "
                 "components.");
 
+  gfc_save_backend_locus (&loc);
+  gfc_set_backend_locus (&sym->declared_at);
   gfc_init_block (&init);
 
   gcc_assert (TREE_CODE (sym->backend_decl) == VAR_DECL
@@ -7172,11 +7403,10 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
   if (sym->attr.dummy || sym->attr.use_assoc || sym->attr.result)
     {
       gfc_add_init_cleanup (block, gfc_finish_block (&init), NULL_TREE);
+      gfc_restore_backend_locus (&loc);
       return;
     }
 
-  gfc_save_backend_locus (&loc);
-  gfc_set_backend_locus (&sym->declared_at);
   descriptor = sym->backend_decl;
 
   /* Although static, derived types with default initializers and
@@ -7225,8 +7455,8 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
   if (GFC_DESCRIPTOR_TYPE_P (type) && !sym->attr.save)
     gfc_conv_descriptor_data_set (&init, descriptor, null_pointer_node);
 
-  gfc_init_block (&cleanup);
   gfc_restore_backend_locus (&loc);
+  gfc_init_block (&cleanup);
 
   /* Allocatable arrays need to be freed when they go out of scope.
      The allocatable components of pointers must not be touched.  */
@@ -7239,7 +7469,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, gfc_wrapped_block * block)
       gfc_add_expr_to_block (&cleanup, tmp);
     }
 
-  if (sym->attr.allocatable && sym->attr.dimension
+  if (sym->attr.allocatable && (sym->attr.dimension || sym->attr.codimension)
       && !sym->attr.save && !sym->attr.result)
     {
       tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
@@ -7300,7 +7530,7 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
 
       ar = &ref->u.ar;
 
-      if (ar->as->rank == 0)
+      if (ar->as->rank == 0 && ref->next != NULL)
        {
          /* Scalar coarray.  */
          continue;
@@ -7309,7 +7539,7 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
       switch (ar->type)
        {
        case AR_ELEMENT:
-         for (n = 0; n < ar->dimen; n++)
+         for (n = 0; n < ar->dimen + ar->codimen; n++)
            {
              newss = gfc_get_ss ();
              newss->type = GFC_SS_SCALAR;
@@ -7325,11 +7555,13 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
          newss->expr = expr;
          newss->next = ss;
          newss->data.info.dimen = ar->as->rank;
+         newss->data.info.codimen = 0;
          newss->data.info.ref = ref;
 
          /* Make sure array is the same as array(:,:), this way
             we don't need to special case all the time.  */
          ar->dimen = ar->as->rank;
+         ar->codimen = 0;
          for (n = 0; n < ar->dimen; n++)
            {
              newss->data.info.dim[n] = n;
@@ -7339,6 +7571,14 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
              gcc_assert (ar->end[n] == NULL);
              gcc_assert (ar->stride[n] == NULL);
            }
+         for (n = ar->dimen; n < ar->dimen + ar->as->corank; n++)
+           {
+             newss->data.info.dim[n] = n;
+             ar->dimen_type[n] = DIMEN_RANGE;
+
+             gcc_assert (ar->start[n] == NULL);
+             gcc_assert (ar->end[n] == NULL);
+           }
          ss = newss;
          break;
 
@@ -7348,15 +7588,18 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
          newss->expr = expr;
          newss->next = ss;
          newss->data.info.dimen = 0;
+         newss->data.info.codimen = 0;
          newss->data.info.ref = ref;
 
           /* We add SS chains for all the subscripts in the section.  */
-         for (n = 0; n < ar->dimen; n++)
+         for (n = 0; n < ar->dimen + ar->codimen; n++)
            {
              gfc_ss *indexss;
 
              switch (ar->dimen_type[n])
                {
+               case DIMEN_THIS_IMAGE:
+                 continue;
                case DIMEN_ELEMENT:
                  /* Add SS for elemental (scalar) subscripts.  */
                  gcc_assert (ar->start[n]);
@@ -7371,8 +7614,10 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
                case DIMEN_RANGE:
                   /* We don't add anything for sections, just remember this
                      dimension for later.  */
-                 newss->data.info.dim[newss->data.info.dimen] = n;
-                 newss->data.info.dimen++;
+                 newss->data.info.dim[newss->data.info.dimen
+                                      + newss->data.info.codimen] = n;
+                 if (n < ar->dimen)
+                   newss->data.info.dimen++;
                  break;
 
                case DIMEN_VECTOR:
@@ -7384,8 +7629,10 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
                  indexss->next = gfc_ss_terminator;
                  indexss->loop_chain = gfc_ss_terminator;
                  newss->data.info.subscript[n] = indexss;
-                 newss->data.info.dim[newss->data.info.dimen] = n;
-                 newss->data.info.dimen++;
+                 newss->data.info.dim[newss->data.info.dimen
+                                      + newss->data.info.codimen] = n;
+                 if (n < ar->dimen)
+                   newss->data.info.dimen++;
                  break;
 
                default: