OSDN Git Service

gcc/fortran/:
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
index a96a48d..8ece643 100644 (file)
@@ -1,5 +1,5 @@
 /* Array translation routines
-   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Paul Brook <paul@nowt.org>
    and Steven Bosscher <s.bosscher@student.tudelft.nl>
@@ -86,6 +86,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "real.h"
 #include "flags.h"
 #include "gfortran.h"
+#include "constructor.h"
 #include "trans.h"
 #include "trans-stmt.h"
 #include "trans-types.h"
@@ -94,7 +95,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dependency.h"
 
 static gfc_ss *gfc_walk_subexpr (gfc_ss *, gfc_expr *);
-static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor *);
+static bool gfc_get_array_constructor_size (mpz_t *, gfc_constructor_base);
 
 /* The contents of this structure aren't actually used, just the address.  */
 static gfc_ss gfc_ss_terminator_var;
@@ -197,7 +198,7 @@ gfc_conv_descriptor_data_addr (tree desc)
   return gfc_build_addr_expr (NULL_TREE, t);
 }
 
-tree
+static tree
 gfc_conv_descriptor_offset (tree desc)
 {
   tree type;
@@ -214,6 +215,21 @@ gfc_conv_descriptor_offset (tree desc)
 }
 
 tree
+gfc_conv_descriptor_offset_get (tree desc)
+{
+  return gfc_conv_descriptor_offset (desc);
+}
+
+void
+gfc_conv_descriptor_offset_set (stmtblock_t *block, tree desc,
+                               tree value)
+{
+  tree t = gfc_conv_descriptor_offset (desc);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+
+tree
 gfc_conv_descriptor_dtype (tree desc)
 {
   tree field;
@@ -250,7 +266,7 @@ gfc_conv_descriptor_dimension (tree desc, tree dim)
   return tmp;
 }
 
-tree
+static tree
 gfc_conv_descriptor_stride (tree desc, tree dim)
 {
   tree tmp;
@@ -267,6 +283,26 @@ gfc_conv_descriptor_stride (tree desc, tree dim)
 }
 
 tree
+gfc_conv_descriptor_stride_get (tree desc, tree dim)
+{
+  tree type = TREE_TYPE (desc);
+  gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
+  if (integer_zerop (dim)
+      && GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ALLOCATABLE)
+    return gfc_index_one_node;
+
+  return gfc_conv_descriptor_stride (desc, dim);
+}
+
+void
+gfc_conv_descriptor_stride_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_stride (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+static tree
 gfc_conv_descriptor_lbound (tree desc, tree dim)
 {
   tree tmp;
@@ -283,6 +319,20 @@ gfc_conv_descriptor_lbound (tree desc, tree dim)
 }
 
 tree
+gfc_conv_descriptor_lbound_get (tree desc, tree dim)
+{
+  return gfc_conv_descriptor_lbound (desc, dim);
+}
+
+void
+gfc_conv_descriptor_lbound_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_lbound (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
+
+static tree
 gfc_conv_descriptor_ubound (tree desc, tree dim)
 {
   tree tmp;
@@ -298,6 +348,19 @@ gfc_conv_descriptor_ubound (tree desc, tree dim)
   return tmp;
 }
 
+tree
+gfc_conv_descriptor_ubound_get (tree desc, tree dim)
+{
+  return gfc_conv_descriptor_ubound (desc, dim);
+}
+
+void
+gfc_conv_descriptor_ubound_set (stmtblock_t *block, tree desc,
+                               tree dim, tree value)
+{
+  tree t = gfc_conv_descriptor_ubound (desc, dim);
+  gfc_add_modify (block, t, fold_convert (TREE_TYPE (t), value));
+}
 
 /* Build a null array descriptor constructor.  */
 
@@ -558,11 +621,13 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
              gcc_assert (tmp == gfc_get_element_type (TREE_TYPE (desc)));
              packed = gfc_create_var (build_pointer_type (tmp), "data");
 
-             tmp = build_call_expr (gfor_fndecl_in_pack, 1, initial);
+             tmp = build_call_expr_loc (input_location,
+                                    gfor_fndecl_in_pack, 1, initial);
              tmp = fold_convert (TREE_TYPE (packed), tmp);
              gfc_add_modify (pre, packed, tmp);
 
-             tmp = build_fold_indirect_ref (initial);
+             tmp = build_fold_indirect_ref_loc (input_location,
+                                            initial);
              source_data = gfc_conv_descriptor_data_get (tmp);
 
              /* internal_pack may return source->data without any allocation
@@ -579,7 +644,8 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
              was_packed = fold_build2 (EQ_EXPR, boolean_type_node,
                                        packed, source_data);
              tmp = gfc_finish_block (&do_copying);
-             tmp = build3_v (COND_EXPR, was_packed, tmp, build_empty_stmt ());
+             tmp = build3_v (COND_EXPR, was_packed, tmp,
+                             build_empty_stmt (input_location));
              gfc_add_expr_to_block (pre, tmp);
 
              tmp = fold_convert (pvoid_type_node, packed);
@@ -592,8 +658,7 @@ gfc_trans_allocate_array_storage (stmtblock_t * pre, stmtblock_t * post,
 
   /* The offset is zero because we create temporaries with a zero
      lower bound.  */
-  tmp = gfc_conv_descriptor_offset (desc);
-  gfc_add_modify (pre, tmp, gfc_index_zero_node);
+  gfc_conv_descriptor_offset_set (pre, desc, gfc_index_zero_node);
 
   if (dealloc && !onstack)
     {
@@ -660,8 +725,8 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
 
   /* Initialize the descriptor.  */
   type =
-    gfc_get_array_type_bounds (eltype, info->dimen, loop->from, loop->to, 1,
-                              GFC_ARRAY_UNKNOWN);
+    gfc_get_array_type_bounds (eltype, info->dimen, 0, loop->from, loop->to, 1,
+                              GFC_ARRAY_UNKNOWN, true);
   desc = gfc_create_var (type, "atmp");
   GFC_DECL_PACKED_ARRAY (desc) = 1;
 
@@ -704,21 +769,19 @@ gfc_trans_create_temp_array (stmtblock_t * pre, stmtblock_t * post,
             of the descriptor fields.  */
          tmp =
            fold_build2 (MINUS_EXPR, gfc_array_index_type,
-                        gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]),
-                        gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]));
+                        gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[n]),
+                        gfc_conv_descriptor_lbound_get (desc, gfc_rank_cst[n]));
          loop->to[n] = tmp;
          continue;
        }
        
       /* Store the stride and bound components in the descriptor.  */
-      tmp = gfc_conv_descriptor_stride (desc, gfc_rank_cst[n]);
-      gfc_add_modify (pre, tmp, size);
+      gfc_conv_descriptor_stride_set (pre, desc, gfc_rank_cst[n], size);
 
-      tmp = gfc_conv_descriptor_lbound (desc, gfc_rank_cst[n]);
-      gfc_add_modify (pre, tmp, gfc_index_zero_node);
+      gfc_conv_descriptor_lbound_set (pre, desc, gfc_rank_cst[n],
+                                     gfc_index_zero_node);
 
-      tmp = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[n]);
-      gfc_add_modify (pre, tmp, loop->to[n]);
+      gfc_conv_descriptor_ubound_set (pre, desc, gfc_rank_cst[n], loop->to[n]);
 
       tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
                         loop->to[n], gfc_index_one_node);
@@ -775,7 +838,7 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
 {
   tree dest, src, dest_index, src_index;
   gfc_loopinfo *loop;
-  gfc_ss_info *dest_info, *src_info;
+  gfc_ss_info *dest_info;
   gfc_ss *dest_ss, *src_ss;
   gfc_se src_se;
   int n;
@@ -785,10 +848,8 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
   src_ss = gfc_walk_expr (expr);
   dest_ss = se->ss;
 
-  src_info = &src_ss->data.info;
   dest_info = &dest_ss->data.info;
   gcc_assert (dest_info->dimen == 2);
-  gcc_assert (src_info->dimen == 2);
 
   /* Get a descriptor for EXPR.  */
   gfc_init_se (&src_se, NULL);
@@ -820,25 +881,22 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
       dest_index = gfc_rank_cst[n];
       src_index = gfc_rank_cst[1 - n];
 
-      gfc_add_modify (&se->pre,
-                          gfc_conv_descriptor_stride (dest, dest_index),
-                          gfc_conv_descriptor_stride (src, src_index));
+      gfc_conv_descriptor_stride_set (&se->pre, dest, dest_index,
+                          gfc_conv_descriptor_stride_get (src, src_index));
 
-      gfc_add_modify (&se->pre,
-                          gfc_conv_descriptor_lbound (dest, dest_index),
-                          gfc_conv_descriptor_lbound (src, src_index));
+      gfc_conv_descriptor_lbound_set (&se->pre, dest, dest_index,
+                          gfc_conv_descriptor_lbound_get (src, src_index));
 
-      gfc_add_modify (&se->pre,
-                          gfc_conv_descriptor_ubound (dest, dest_index),
-                          gfc_conv_descriptor_ubound (src, src_index));
+      gfc_conv_descriptor_ubound_set (&se->pre, dest, dest_index,
+                          gfc_conv_descriptor_ubound_get (src, src_index));
 
       if (!loop->to[n])
         {
          gcc_assert (integer_zerop (loop->from[n]));
          loop->to[n] =
            fold_build2 (MINUS_EXPR, gfc_array_index_type,
-                        gfc_conv_descriptor_ubound (dest, dest_index),
-                        gfc_conv_descriptor_lbound (dest, dest_index));
+                        gfc_conv_descriptor_ubound_get (dest, dest_index),
+                        gfc_conv_descriptor_lbound_get (dest, dest_index));
         }
     }
 
@@ -850,13 +908,12 @@ gfc_conv_array_transpose (gfc_se * se, gfc_expr * expr)
      element is still at the same offset as before, except where the loop
      starts at zero.  */
   if (!integer_zerop (loop->from[0]))
-    dest_info->offset = gfc_conv_descriptor_offset (src);
+    dest_info->offset = gfc_conv_descriptor_offset_get (src);
   else
     dest_info->offset = gfc_index_zero_node;
 
-  gfc_add_modify (&se->pre,
-                      gfc_conv_descriptor_offset (dest),
-                      dest_info->offset);
+  gfc_conv_descriptor_offset_set (&se->pre, dest,
+                                 dest_info->offset);
          
   if (dest_info->dimen > loop->temp_dim)
     loop->temp_dim = dest_info->dimen;
@@ -894,11 +951,11 @@ gfc_grow_array (stmtblock_t * pblock, tree desc, tree extra)
   if (integer_zerop (extra))
     return;
 
-  ubound = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
+  ubound = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
 
   /* Add EXTRA to the upper bound.  */
   tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type, ubound, extra);
-  gfc_add_modify (pblock, ubound, tmp);
+  gfc_conv_descriptor_ubound_set (pblock, desc, gfc_rank_cst[0], tmp);
 
   /* Get the value of the current data pointer.  */
   arg0 = gfc_conv_descriptor_data_get (desc);
@@ -958,8 +1015,9 @@ gfc_get_array_constructor_element_size (mpz_t * size, gfc_expr * expr)
    of array constructor C.  */
 
 static bool
-gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
+gfc_get_array_constructor_size (mpz_t * size, gfc_constructor_base base)
 {
+  gfc_constructor *c;
   gfc_iterator *i;
   mpz_t val;
   mpz_t len;
@@ -970,7 +1028,7 @@ gfc_get_array_constructor_size (mpz_t * size, gfc_constructor * c)
   mpz_init (val);
 
   dynamic = false;
-  for (; c; c = c->next)
+  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
     {
       i = c->iterator;
       if (i && gfc_iterator_has_dynamic_bounds (i))
@@ -1028,7 +1086,8 @@ gfc_trans_array_ctor_element (stmtblock_t * pblock, tree desc,
   gfc_conv_expr (se, expr);
 
   /* Store the value.  */
-  tmp = build_fold_indirect_ref (gfc_conv_descriptor_data_get (desc));
+  tmp = build_fold_indirect_ref_loc (input_location,
+                                gfc_conv_descriptor_data_get (desc));
   tmp = gfc_build_array_ref (tmp, offset, NULL);
 
   if (expr->ts.type == BT_CHARACTER)
@@ -1174,7 +1233,7 @@ gfc_trans_array_constructor_subarray (stmtblock_t * pblock,
 
 static void
 gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
-                                  tree desc, gfc_constructor * c,
+                                  tree desc, gfc_constructor_base base,
                                   tree * poffset, tree * offsetvar,
                                   bool dynamic)
 {
@@ -1182,12 +1241,13 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
   stmtblock_t body;
   gfc_se se;
   mpz_t size;
+  gfc_constructor *c;
 
   tree shadow_loopvar = NULL_TREE;
   gfc_saved_var saved_loopvar;
 
   mpz_init (size);
-  for (; c; c = c->next)
+  for (c = gfc_constructor_first (base); c; c = gfc_constructor_next (c))
     {
       /* If this is an iterator or an array, the offset must be a variable.  */
       if ((c->iterator || c->expr->rank > 0) && INTEGER_CST_P (*poffset))
@@ -1232,7 +1292,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
          n = 0;
          while (p && !(p->iterator || p->expr->expr_type != EXPR_CONSTANT))
            {
-             p = p->next;
+             p = gfc_constructor_next (p);
              n++;
            }
          if (n < 4)
@@ -1263,10 +1323,11 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                  gfc_init_se (&se, NULL);
                  gfc_conv_constant (&se, p->expr);
 
+                 if (c->expr->ts.type != BT_CHARACTER)
+                   se.expr = fold_convert (type, se.expr);
                  /* For constant character array constructors we build
                     an array of pointers.  */
-                 if (p->expr->ts.type == BT_CHARACTER
-                     && POINTER_TYPE_P (type))
+                 else if (POINTER_TYPE_P (type))
                    se.expr = gfc_build_addr_expr
                                (gfc_get_pchar_type (p->expr->ts.kind),
                                 se.expr);
@@ -1274,7 +1335,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                  list = tree_cons (build_int_cst (gfc_array_index_type,
                                                   idx++), se.expr, list);
                  c = p;
-                 p = p->next;
+                 p = gfc_constructor_next (p);
                }
 
              bound = build_int_cst (NULL_TREE, n - 1);
@@ -1296,14 +1357,16 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
 
              /* Use BUILTIN_MEMCPY to assign the values.  */
              tmp = gfc_conv_descriptor_data_get (desc);
-             tmp = build_fold_indirect_ref (tmp);
+             tmp = build_fold_indirect_ref_loc (input_location,
+                                            tmp);
              tmp = gfc_build_array_ref (tmp, *poffset, NULL);
              tmp = gfc_build_addr_expr (NULL_TREE, tmp);
              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);
-             tmp = build_call_expr (built_in_decls[BUILT_IN_MEMCPY], 3,
+             tmp = build_call_expr_loc (input_location,
+                                    built_in_decls[BUILT_IN_MEMCPY], 3,
                                     tmp, init, bound);
              gfc_add_expr_to_block (&body, tmp);
 
@@ -1392,7 +1455,8 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                                           shadow_loopvar, end));
          tmp = build1_v (GOTO_EXPR, exit_label);
          TREE_USED (exit_label) = 1;
-         tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
+         tmp = build3_v (COND_EXPR, cond, tmp,
+                         build_empty_stmt (input_location));
          gfc_add_expr_to_block (&body, tmp);
 
          /* The main loop body.  */
@@ -1470,7 +1534,7 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
        }
     }
 
-  *len = ts->cl->backend_decl;
+  *len = ts->u.cl->backend_decl;
 }
 
 
@@ -1486,12 +1550,12 @@ get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
   if (*len && INTEGER_CST_P (*len))
     return;
 
-  if (!e->ref && e->ts.cl && e->ts.cl->length
-       && e->ts.cl->length->expr_type == EXPR_CONSTANT)
+  if (!e->ref && e->ts.u.cl && e->ts.u.cl->length
+       && e->ts.u.cl->length->expr_type == EXPR_CONSTANT)
     {
       /* This is easy.  */
-      gfc_conv_const_charlen (e->ts.cl);
-      *len = e->ts.cl->backend_decl;
+      gfc_conv_const_charlen (e->ts.u.cl);
+      *len = e->ts.u.cl->backend_decl;
     }
   else
     {
@@ -1512,7 +1576,7 @@ get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
       gfc_add_block_to_block (block, &se.pre);
       gfc_add_block_to_block (block, &se.post);
 
-      e->ts.cl->backend_decl = *len;
+      e->ts.u.cl->backend_decl = *len;
     }
 }
 
@@ -1524,13 +1588,14 @@ get_array_ctor_all_strlen (stmtblock_t *block, gfc_expr *e, tree *len)
    Returns TRUE if all elements are character constants.  */
 
 bool
-get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
+get_array_ctor_strlen (stmtblock_t *block, gfc_constructor_base base, tree * len)
 {
+  gfc_constructor *c;
   bool is_const;
-  
+
   is_const = TRUE;
 
-  if (c == NULL)
+  if (gfc_constructor_first (base) == NULL)
     {
       if (len)
        *len = build_int_cstu (gfc_charlen_type_node, 0);
@@ -1540,7 +1605,8 @@ get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
   /* Loop over all constructor elements to find out is_const, but in len we
      want to store the length of the first, not the last, element.  We can
      of course exit the loop as soon as is_const is found to be false.  */
-  for (; c && is_const; c = c->next)
+  for (c = gfc_constructor_first (base);
+       c && is_const; c = gfc_constructor_next (c))
     {
       switch (c->expr->expr_type)
        {
@@ -1580,17 +1646,18 @@ get_array_ctor_strlen (stmtblock_t *block, gfc_constructor * c, tree * len)
    return zero.  Note, an empty or NULL array constructor returns zero.  */
 
 unsigned HOST_WIDE_INT
-gfc_constant_array_constructor_p (gfc_constructor * c)
+gfc_constant_array_constructor_p (gfc_constructor_base base)
 {
   unsigned HOST_WIDE_INT nelem = 0;
 
+  gfc_constructor *c = gfc_constructor_first (base);
   while (c)
     {
       if (c->iterator
          || c->expr->rank > 0
          || c->expr->expr_type != EXPR_CONSTANT)
        return 0;
-      c = c->next;
+      c = gfc_constructor_next (c);
       nelem++;
     }
   return nelem;
@@ -1615,17 +1682,19 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
      to tree to build an initializer.  */
   nelem = 0;
   list = NULL_TREE;
-  c = expr->value.constructor;
+  c = gfc_constructor_first (expr->value.constructor);
   while (c)
     {
       gfc_init_se (&se, NULL);
       gfc_conv_constant (&se, c->expr);
-      if (c->expr->ts.type == BT_CHARACTER && POINTER_TYPE_P (type))
+      if (c->expr->ts.type != BT_CHARACTER)
+       se.expr = fold_convert (type, se.expr);
+      else if (POINTER_TYPE_P (type))
        se.expr = gfc_build_addr_expr (gfc_get_pchar_type (c->expr->ts.kind),
                                       se.expr);
       list = tree_cons (build_int_cst (gfc_array_index_type, nelem),
                        se.expr, list);
-      c = c->next;
+      c = gfc_constructor_next (c);
       nelem++;
     }
 
@@ -1639,18 +1708,20 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
   as.type = AS_EXPLICIT;
   if (!expr->shape)
     {
-      as.lower[0] = gfc_int_expr (0);
-      as.upper[0] = gfc_int_expr (nelem - 1);
+      as.lower[0] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
+      as.upper[0] = gfc_get_int_expr (gfc_default_integer_kind,
+                                     NULL, nelem - 1);
     }
   else
     for (i = 0; i < expr->rank; i++)
       {
        int tmp = (int) mpz_get_si (expr->shape[i]);
-       as.lower[i] = gfc_int_expr (0);
-       as.upper[i] = gfc_int_expr (tmp - 1);
+        as.lower[i] = gfc_get_int_expr (gfc_default_integer_kind, NULL, 0);
+        as.upper[i] = gfc_get_int_expr (gfc_default_integer_kind,
+                                       NULL, tmp - 1);
       }
 
-  tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC);
+  tmptype = gfc_get_nodesc_array_type (type, &as, PACKED_STATIC, true);
 
   init = build_constructor_from_list (tmptype, nreverse (list));
 
@@ -1744,7 +1815,7 @@ constant_array_constructor_loop_size (gfc_loopinfo * loop)
 static void
 gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
 {
-  gfc_constructor *c;
+  gfc_constructor_base c;
   tree offset;
   tree offsetvar;
   tree desc;
@@ -1760,8 +1831,8 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
 
   /* Do bounds-checking here and in gfc_trans_array_ctor_element only if no
      typespec was given for the array constructor.  */
-  typespec_chararray_ctor = (ss->expr->ts.cl
-                            && ss->expr->ts.cl->length_from_typespec);
+  typespec_chararray_ctor = (ss->expr->ts.u.cl
+                            && ss->expr->ts.u.cl->length_from_typespec);
 
   if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)
       && ss->expr->ts.type == BT_CHARACTER && !typespec_chararray_ctor)
@@ -1780,14 +1851,14 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
       /* get_array_ctor_strlen walks the elements of the constructor, if a
         typespec was given, we already know the string length and want the one
         specified there.  */
-      if (typespec_chararray_ctor && ss->expr->ts.cl->length
-         && ss->expr->ts.cl->length->expr_type != EXPR_CONSTANT)
+      if (typespec_chararray_ctor && ss->expr->ts.u.cl->length
+         && ss->expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
        {
          gfc_se length_se;
 
          const_string = false;
          gfc_init_se (&length_se, NULL);
-         gfc_conv_expr_type (&length_se, ss->expr->ts.cl->length,
+         gfc_conv_expr_type (&length_se, ss->expr->ts.u.cl->length,
                              gfc_charlen_type_node);
          ss->string_length = length_se.expr;
          gfc_add_block_to_block (&loop->pre, &length_se.pre);
@@ -1801,7 +1872,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
         and not end up here.  */
       gcc_assert (ss->string_length);
 
-      ss->expr->ts.cl->backend_decl = ss->string_length;
+      ss->expr->ts.u.cl->backend_decl = ss->string_length;
 
       type = gfc_get_character_type_len (ss->expr->ts.kind, ss->string_length);
       if (const_string)
@@ -1874,7 +1945,7 @@ gfc_trans_array_constructor (gfc_loopinfo * loop, gfc_ss * ss, locus * where)
   /* If the array grows dynamically, the upper bound of the loop variable
      is determined by the array's final upper bound.  */
   if (dynamic)
-    loop->to[0] = gfc_conv_descriptor_ubound (desc, gfc_rank_cst[0]);
+    loop->to[0] = gfc_conv_descriptor_ubound_get (desc, gfc_rank_cst[0]);
 
   if (TREE_USED (offsetvar))
     pushdecl (offsetvar);
@@ -1928,8 +1999,8 @@ gfc_set_vector_loop_bounds (gfc_loopinfo * loop, gfc_ss_info * info)
          desc = info->subscript[dim]->data.info.descriptor;
          zero = gfc_rank_cst[0];
          tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
-                            gfc_conv_descriptor_ubound (desc, zero),
-                            gfc_conv_descriptor_lbound (desc, zero));
+                            gfc_conv_descriptor_ubound_get (desc, zero),
+                            gfc_conv_descriptor_lbound_get (desc, zero));
          tmp = gfc_evaluate_now (tmp, &loop->pre);
          loop->to[n] = tmp;
        }
@@ -1983,9 +2054,10 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
          break;
 
        case GFC_SS_REFERENCE:
-         /* Scalar reference.  Evaluate this now.  */
+         /* Scalar argument to elemental procedure.  Evaluate this
+            now.  */
          gfc_init_se (&se, NULL);
-         gfc_conv_expr_reference (&se, ss->expr);
+         gfc_conv_expr (&se, ss->expr);
          gfc_add_block_to_block (&loop->pre, &se.pre);
          gfc_add_block_to_block (&loop->post, &se.post);
 
@@ -2031,11 +2103,11 @@ gfc_add_loop_ss_code (gfc_loopinfo * loop, gfc_ss * ss, bool subscript,
        case GFC_SS_CONSTRUCTOR:
          if (ss->expr->ts.type == BT_CHARACTER
                && ss->string_length == NULL
-               && ss->expr->ts.cl
-               && ss->expr->ts.cl->length)
+               && ss->expr->ts.u.cl
+               && ss->expr->ts.u.cl->length)
            {
              gfc_init_se (&se, NULL);
-             gfc_conv_expr_type (&se, ss->expr->ts.cl->length,
+             gfc_conv_expr_type (&se, ss->expr->ts.u.cl->length,
                                  gfc_charlen_type_node);
              ss->string_length = se.expr;
              gfc_add_block_to_block (&loop->pre, &se.pre);
@@ -2157,7 +2229,7 @@ gfc_conv_array_offset (tree descriptor)
   if (GFC_ARRAY_TYPE_P (type))
     return GFC_TYPE_ARRAY_OFFSET (type);
   else
-    return gfc_conv_descriptor_offset (descriptor);
+    return gfc_conv_descriptor_offset_get (descriptor);
 }
 
 
@@ -2176,7 +2248,7 @@ gfc_conv_array_stride (tree descriptor, int dim)
   if (tmp != NULL_TREE)
     return tmp;
 
-  tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[dim]);
+  tmp = gfc_conv_descriptor_stride_get (descriptor, gfc_rank_cst[dim]);
   return tmp;
 }
 
@@ -2195,7 +2267,7 @@ gfc_conv_array_lbound (tree descriptor, int dim)
   if (tmp != NULL_TREE)
     return tmp;
 
-  tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[dim]);
+  tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
   return tmp;
 }
 
@@ -2219,7 +2291,7 @@ gfc_conv_array_ubound (tree descriptor, int dim)
   if (GFC_ARRAY_TYPE_P (TREE_TYPE (descriptor)))
     return gfc_index_zero_node;
 
-  tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[dim]);
+  tmp = gfc_conv_descriptor_ubound_get (descriptor, gfc_rank_cst[dim]);
   return tmp;
 }
 
@@ -2231,7 +2303,7 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
                             locus * where, bool check_upper)
 {
   tree fault;
-  tree tmp;
+  tree tmp_lo, tmp_up;
   char *msg;
   const char * name = NULL;
 
@@ -2253,10 +2325,6 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
       && se->loop->ss->loop_chain->expr->symtree)
     name = se->loop->ss->loop_chain->expr->symtree->name;
 
-  if (!name && se->loop && se->loop->ss && se->loop->ss->loop_chain
-      && se->loop->ss->loop_chain->expr->symtree)
-    name = se->loop->ss->loop_chain->expr->symtree->name;
-
   if (!name && se->loop && se->loop->ss && se->loop->ss->expr)
     {
       if (se->loop->ss->expr->expr_type == EXPR_FUNCTION
@@ -2268,34 +2336,49 @@ gfc_trans_array_bound_check (gfc_se * se, tree descriptor, tree index, int n,
          name = "unnamed constant";
     }
 
-  /* Check lower bound.  */
-  tmp = gfc_conv_array_lbound (descriptor, n);
-  fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp);
-  if (name)
-    asprintf (&msg, "%s for array '%s', lower bound of dimension %d exceeded"
-             "(%%ld < %%ld)", gfc_msg_fault, name, n+1);
-  else
-    asprintf (&msg, "%s, lower bound of dimension %d exceeded (%%ld < %%ld)",
-             gfc_msg_fault, n+1);
-  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));
-  gfc_free (msg);
-
-  /* Check upper bound.  */
+  if (TREE_CODE (descriptor) == VAR_DECL)
+    name = IDENTIFIER_POINTER (DECL_NAME (descriptor));
+
+  /* If upper bound is present, include both bounds in the error message.  */
   if (check_upper)
     {
-      tmp = gfc_conv_array_ubound (descriptor, n);
-      fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp);
+      tmp_lo = gfc_conv_array_lbound (descriptor, n);
+      tmp_up = gfc_conv_array_ubound (descriptor, n);
+
+      if (name)
+       asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                 "outside of expected range (%%ld:%%ld)", n+1, name);
+      else
+       asprintf (&msg, "Index '%%ld' of dimension %d "
+                 "outside of expected range (%%ld:%%ld)", n+1);
+
+      fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp_lo);
+      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),
+                              fold_convert (long_integer_type_node, tmp_up));
+      fault = fold_build2 (GT_EXPR, boolean_type_node, index, tmp_up);
+      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),
+                              fold_convert (long_integer_type_node, tmp_up));
+      gfc_free (msg);
+    }
+  else
+    {
+      tmp_lo = gfc_conv_array_lbound (descriptor, n);
+
       if (name)
-       asprintf (&msg, "%s for array '%s', upper bound of dimension %d "
-                       " exceeded (%%ld > %%ld)", gfc_msg_fault, name, n+1);
+       asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                 "below lower bound of %%ld", n+1, name);
       else
-       asprintf (&msg, "%s, upper bound of dimension %d exceeded (%%ld > %%ld)",
-                 gfc_msg_fault, n+1);
+       asprintf (&msg, "Index '%%ld' of dimension %d "
+                 "below lower bound of %%ld", n+1);
+
+      fault = fold_build2 (LT_EXPR, boolean_type_node, index, tmp_lo);
       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));
+                              fold_convert (long_integer_type_node, tmp_lo));
       gfc_free (msg);
     }
 
@@ -2329,8 +2412,8 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
 
          index = gfc_trans_array_bound_check (se, info->descriptor,
                        index, dim, &ar->where,
-                       (ar->as->type != AS_ASSUMED_SIZE
-                        && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
+                       ar->as->type != AS_ASSUMED_SIZE
+                       || dim < ar->dimen - 1);
          break;
 
        case DIMEN_VECTOR:
@@ -2348,15 +2431,17 @@ gfc_conv_array_index_offset (gfc_se * se, gfc_ss_info * info, int dim, int i,
                               index, gfc_conv_array_stride (desc, 0));
 
          /* Read the vector to get an index into info->descriptor.  */
-         data = build_fold_indirect_ref (gfc_conv_array_data (desc));
+         data = build_fold_indirect_ref_loc (input_location,
+                                         gfc_conv_array_data (desc));
          index = gfc_build_array_ref (data, index, NULL);
          index = gfc_evaluate_now (index, &se->pre);
+         index = fold_convert (gfc_array_index_type, index);
 
          /* Do any bounds checking on the final info->descriptor index.  */
          index = gfc_trans_array_bound_check (se, info->descriptor,
                        index, dim, &ar->where,
-                       (ar->as->type != AS_ASSUMED_SIZE
-                        && !ar->as->cp_was_assumed) || dim < ar->dimen - 1);
+                       ar->as->type != AS_ASSUMED_SIZE
+                       || dim < ar->dimen - 1);
          break;
 
        case DIMEN_RANGE:
@@ -2422,7 +2507,8 @@ gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar)
   if (se->ss->expr && is_subref_array (se->ss->expr))
     decl = se->ss->expr->symtree->n.sym->backend_decl;
 
-  tmp = build_fold_indirect_ref (info->data);
+  tmp = build_fold_indirect_ref_loc (input_location,
+                                info->data);
   se->expr = gfc_build_array_ref (tmp, index, decl);
 }
 
@@ -2454,6 +2540,9 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
   gfc_se indexse;
   gfc_se tmpse;
 
+  if (ar->dimen == 0)
+    return;
+
   /* Handle scalarized references separately.  */
   if (ar->type != AR_ELEMENT)
     {
@@ -2494,9 +2583,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
 
          cond = fold_build2 (LT_EXPR, boolean_type_node, 
                              indexse.expr, tmp);
-         asprintf (&msg, "%s for array '%s', "
-                   "lower bound of dimension %d exceeded (%%ld < %%ld)",
-                   gfc_msg_fault, sym->name, n+1);
+         asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                   "below lower bound of %%ld", n+1, sym->name);
          gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
                                   fold_convert (long_integer_type_node,
                                                 indexse.expr),
@@ -2505,8 +2593,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
 
          /* Upper bound, but not for the last dimension of assumed-size
             arrays.  */
-         if (n < ar->dimen - 1
-             || (ar->as->type != AS_ASSUMED_SIZE && !ar->as->cp_was_assumed))
+         if (n < ar->dimen - 1 || ar->as->type != AS_ASSUMED_SIZE)
            {
              tmp = gfc_conv_array_ubound (se->expr, n);
              if (sym->attr.temporary)
@@ -2520,9 +2607,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, gfc_symbol * sym,
 
              cond = fold_build2 (GT_EXPR, boolean_type_node, 
                                  indexse.expr, tmp);
-             asprintf (&msg, "%s for array '%s', "
-                       "upper bound of dimension %d exceeded (%%ld > %%ld)",
-                       gfc_msg_fault, sym->name, n+1);
+             asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                       "above upper bound of %%ld", n+1, sym->name);
              gfc_trans_runtime_check (true, false, cond, &se->pre, where, msg,
                                   fold_convert (long_integer_type_node,
                                                 indexse.expr),
@@ -2688,7 +2774,7 @@ gfc_start_scalarized_body (gfc_loopinfo * loop, stmtblock_t * pbody)
 
 /* Generates the actual loop code for a scalarization loop.  */
 
-static void
+void
 gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
                               stmtblock_t * pbody)
 {
@@ -2697,41 +2783,98 @@ gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
   tree tmp;
   tree loopbody;
   tree exit_label;
+  tree stmt;
+  tree init;
+  tree incr;
 
-  loopbody = gfc_finish_block (pbody);
+  if ((ompws_flags & (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS))
+      == (OMPWS_WORKSHARE_FLAG | OMPWS_SCALARIZER_WS)
+      && n == loop->dimen - 1)
+    {
+      /* We create an OMP_FOR construct for the outermost scalarized loop.  */
+      init = make_tree_vec (1);
+      cond = make_tree_vec (1);
+      incr = make_tree_vec (1);
+
+      /* Cycle statement is implemented with a goto.  Exit statement must not
+        be present for this loop.  */
+      exit_label = gfc_build_label_decl (NULL_TREE);
+      TREE_USED (exit_label) = 1;
+
+      /* Label for cycle statements (if needed).  */
+      tmp = build1_v (LABEL_EXPR, exit_label);
+      gfc_add_expr_to_block (pbody, tmp);
+
+      stmt = make_node (OMP_FOR);
+
+      TREE_TYPE (stmt) = void_type_node;
+      OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
+
+      OMP_FOR_CLAUSES (stmt) = build_omp_clause (input_location,
+                                                OMP_CLAUSE_SCHEDULE);
+      OMP_CLAUSE_SCHEDULE_KIND (OMP_FOR_CLAUSES (stmt))
+       = OMP_CLAUSE_SCHEDULE_STATIC;
+      if (ompws_flags & OMPWS_NOWAIT)
+       OMP_CLAUSE_CHAIN (OMP_FOR_CLAUSES (stmt))
+         = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
+
+      /* Initialize the loopvar.  */
+      TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
+                                        loop->from[n]);
+      OMP_FOR_INIT (stmt) = init;
+      /* The exit condition.  */
+      TREE_VEC_ELT (cond, 0) = build2 (LE_EXPR, boolean_type_node,
+                                      loop->loopvar[n], loop->to[n]);
+      OMP_FOR_COND (stmt) = cond;
+      /* Increment the loopvar.  */
+      tmp = build2 (PLUS_EXPR, gfc_array_index_type,
+         loop->loopvar[n], gfc_index_one_node);
+      TREE_VEC_ELT (incr, 0) = fold_build2 (MODIFY_EXPR,
+         void_type_node, loop->loopvar[n], tmp);
+      OMP_FOR_INCR (stmt) = incr;
+
+      ompws_flags &= ~OMPWS_CURR_SINGLEUNIT;
+      gfc_add_expr_to_block (&loop->code[n], stmt);
+    }
+  else
+    {
+      loopbody = gfc_finish_block (pbody);
 
-  /* Initialize the loopvar.  */
-  gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
+      /* Initialize the loopvar.  */
+      if (loop->loopvar[n] != loop->from[n])
+       gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
 
-  exit_label = gfc_build_label_decl (NULL_TREE);
+      exit_label = gfc_build_label_decl (NULL_TREE);
 
-  /* Generate the loop body.  */
-  gfc_init_block (&block);
+      /* Generate the loop body.  */
+      gfc_init_block (&block);
 
-  /* The exit condition.  */
-  cond = fold_build2 (GT_EXPR, boolean_type_node,
-                     loop->loopvar[n], loop->to[n]);
-  tmp = build1_v (GOTO_EXPR, exit_label);
-  TREE_USED (exit_label) = 1;
-  tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt ());
-  gfc_add_expr_to_block (&block, tmp);
+      /* The exit condition.  */
+      cond = fold_build2 (GT_EXPR, boolean_type_node,
+                        loop->loopvar[n], loop->to[n]);
+      tmp = build1_v (GOTO_EXPR, exit_label);
+      TREE_USED (exit_label) = 1;
+      tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
+      gfc_add_expr_to_block (&block, tmp);
 
-  /* The main body.  */
-  gfc_add_expr_to_block (&block, loopbody);
+      /* The main body.  */
+      gfc_add_expr_to_block (&block, loopbody);
 
-  /* Increment the loopvar.  */
-  tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
-                    loop->loopvar[n], gfc_index_one_node);
-  gfc_add_modify (&block, loop->loopvar[n], tmp);
+      /* Increment the loopvar.  */
+      tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+                        loop->loopvar[n], gfc_index_one_node);
+      gfc_add_modify (&block, loop->loopvar[n], tmp);
 
-  /* Build the loop.  */
-  tmp = gfc_finish_block (&block);
-  tmp = build1_v (LOOP_EXPR, tmp);
-  gfc_add_expr_to_block (&loop->code[n], tmp);
+      /* Build the loop.  */
+      tmp = gfc_finish_block (&block);
+      tmp = build1_v (LOOP_EXPR, tmp);
+      gfc_add_expr_to_block (&loop->code[n], tmp);
+
+      /* Add the exit label.  */
+      tmp = build1_v (LABEL_EXPR, exit_label);
+      gfc_add_expr_to_block (&loop->code[n], tmp);
+    }
 
-  /* Add the exit label.  */
-  tmp = build1_v (LABEL_EXPR, exit_label);
-  gfc_add_expr_to_block (&loop->code[n], tmp);
 }
 
 
@@ -3042,7 +3185,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
       tree lbound, ubound;
       tree end;
       tree size[GFC_MAX_DIMENSIONS];
-      tree stride_pos, stride_neg, non_zerosized, tmp2;
+      tree stride_pos, stride_neg, non_zerosized, tmp2, tmp3;
       gfc_ss_info *info;
       char *msg;
       int dim;
@@ -3075,8 +3218,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                continue;
 
              if (dim == info->ref->u.ar.dimen - 1
-                 && (info->ref->u.ar.as->type == AS_ASSUMED_SIZE
-                     || info->ref->u.ar.as->cp_was_assumed))
+                 && info->ref->u.ar.as->type == AS_ASSUMED_SIZE)
                check_upper = false;
              else
                check_upper = true;
@@ -3122,98 +3264,118 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                                           stride_pos, stride_neg);
 
              /* Check the start of the range against the lower and upper
-                bounds of the array, if the range is not empty.  */
-             tmp = fold_build2 (LT_EXPR, boolean_type_node, info->start[n],
-                                lbound);
-             tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                non_zerosized, tmp);
-             asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
-                       " exceeded (%%ld < %%ld)", gfc_msg_fault,
-                       info->dim[n]+1, ss->expr->symtree->name);
-             gfc_trans_runtime_check (true, false, tmp, &inner,
-                                      &ss->expr->where, msg,
-                                      fold_convert (long_integer_type_node,
-                                                    info->start[n]),
-                                      fold_convert (long_integer_type_node,
-                                                    lbound));
-             gfc_free (msg);
-
+                bounds of the array, if the range is not empty. 
+                If upper bound is present, include both bounds in the 
+                error message.  */
              if (check_upper)
                {
-                 tmp = fold_build2 (GT_EXPR, boolean_type_node,
-                                    info->start[n], ubound);
+                 tmp = fold_build2 (LT_EXPR, boolean_type_node, 
+                                    info->start[n], lbound);
+                 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                    non_zerosized, tmp);
+                 tmp2 = fold_build2 (GT_EXPR, boolean_type_node,
+                                     info->start[n], ubound);
+                 tmp2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                     non_zerosized, tmp2);
+                 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                           "outside of expected range (%%ld:%%ld)", 
+                           info->dim[n]+1, ss->expr->symtree->name);
+                 gfc_trans_runtime_check (true, false, tmp, &inner, 
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, info->start[n]),
+                    fold_convert (long_integer_type_node, lbound), 
+                    fold_convert (long_integer_type_node, ubound));
+                 gfc_trans_runtime_check (true, false, tmp2, &inner, 
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, info->start[n]),
+                    fold_convert (long_integer_type_node, lbound), 
+                    fold_convert (long_integer_type_node, ubound));
+                 gfc_free (msg);
+               }
+             else
+               {
+                 tmp = fold_build2 (LT_EXPR, boolean_type_node, 
+                                    info->start[n], lbound);
                  tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
                                     non_zerosized, tmp);
-                 asprintf (&msg, "%s, upper bound of dimension %d of array "
-                           "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
+                 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                           "below lower bound of %%ld", 
                            info->dim[n]+1, ss->expr->symtree->name);
-                 gfc_trans_runtime_check (true, false, tmp, &inner,
-                       &ss->expr->where, msg,
-                       fold_convert (long_integer_type_node, info->start[n]),
-                       fold_convert (long_integer_type_node, ubound));
+                 gfc_trans_runtime_check (true, false, tmp, &inner, 
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, info->start[n]),
+                    fold_convert (long_integer_type_node, lbound));
                  gfc_free (msg);
                }
-
+             
              /* Compute the last element of the range, which is not
                 necessarily "end" (think 0:5:3, which doesn't contain 5)
                 and check it against both lower and upper bounds.  */
-             tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
+
+             tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
                                  info->start[n]);
-             tmp2 = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp2,
+             tmp = fold_build2 (TRUNC_MOD_EXPR, gfc_array_index_type, tmp,
                                  info->stride[n]);
-             tmp2 = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
-                                 tmp2);
-
-             tmp = fold_build2 (LT_EXPR, boolean_type_node, tmp2, lbound);
-             tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                non_zerosized, tmp);
-             asprintf (&msg, "%s, lower bound of dimension %d of array '%s'"
-                       " exceeded (%%ld < %%ld)", gfc_msg_fault,
-                       info->dim[n]+1, ss->expr->symtree->name);
-             gfc_trans_runtime_check (true, false, tmp, &inner,
-                                      &ss->expr->where, msg,
-                                      fold_convert (long_integer_type_node,
-                                                    tmp2),
-                                      fold_convert (long_integer_type_node,
-                                                    lbound));
-             gfc_free (msg);
-
+             tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
+                                 tmp);
+             tmp2 = fold_build2 (LT_EXPR, boolean_type_node, tmp, lbound);
+             tmp2 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                non_zerosized, tmp2);
              if (check_upper)
                {
-                 tmp = fold_build2 (GT_EXPR, boolean_type_node, tmp2, ubound);
-                 tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
-                                    non_zerosized, tmp);
-                 asprintf (&msg, "%s, upper bound of dimension %d of array "
-                           "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
+                 tmp3 = fold_build2 (GT_EXPR, boolean_type_node, tmp, ubound);
+                 tmp3 = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
+                                     non_zerosized, tmp3);
+                 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                           "outside of expected range (%%ld:%%ld)", 
+                           info->dim[n]+1, ss->expr->symtree->name);
+                 gfc_trans_runtime_check (true, false, tmp2, &inner,
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, tmp),
+                    fold_convert (long_integer_type_node, ubound), 
+                    fold_convert (long_integer_type_node, lbound));
+                 gfc_trans_runtime_check (true, false, tmp3, &inner,
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, tmp),
+                    fold_convert (long_integer_type_node, ubound), 
+                    fold_convert (long_integer_type_node, lbound));
+                 gfc_free (msg);
+               }
+             else
+               {
+                 asprintf (&msg, "Index '%%ld' of dimension %d of array '%s' "
+                           "below lower bound of %%ld", 
                            info->dim[n]+1, ss->expr->symtree->name);
-                 gfc_trans_runtime_check (true, false, tmp, &inner,
-                       &ss->expr->where, msg,
-                       fold_convert (long_integer_type_node, tmp2),
-                       fold_convert (long_integer_type_node, ubound));
+                 gfc_trans_runtime_check (true, false, tmp2, &inner,
+                                          &ss->expr->where, msg,
+                    fold_convert (long_integer_type_node, tmp),
+                    fold_convert (long_integer_type_node, lbound));
                  gfc_free (msg);
                }
-
+             
              /* Check the section sizes match.  */
              tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, end,
                                 info->start[n]);
              tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
                                 info->stride[n]);
+             tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+                                gfc_index_one_node, tmp);
              tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
                                 build_int_cst (gfc_array_index_type, 0));
              /* We remember the size of the first section, and check all the
                 others against this.  */
              if (size[n])
                {
-                 tree tmp3;
-
                  tmp3 = fold_build2 (NE_EXPR, boolean_type_node, tmp, size[n]);
-                 asprintf (&msg, "%s, size mismatch for dimension %d "
-                           "of array '%s' (%%ld/%%ld)", gfc_msg_bounds,
+                 asprintf (&msg, "Array bound mismatch for dimension %d "
+                           "of array '%s' (%%ld/%%ld)",
                            info->dim[n]+1, ss->expr->symtree->name);
+
                  gfc_trans_runtime_check (true, false, tmp3, &inner,
                                           &ss->expr->where, msg,
                        fold_convert (long_integer_type_node, tmp),
                        fold_convert (long_integer_type_node, size[n]));
+
                  gfc_free (msg);
                }
              else
@@ -3228,7 +3390,7 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
              || ss->expr->symtree->n.sym->attr.not_always_present)
            tmp = build3_v (COND_EXPR,
                            gfc_conv_expr_present (ss->expr->symtree->n.sym),
-                           tmp, build_empty_stmt ());
+                           tmp, build_empty_stmt (input_location));
 
          gfc_add_expr_to_block (&block, tmp);
 
@@ -3307,13 +3469,9 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
   gfc_ss *ss;
   gfc_ref *lref;
   gfc_ref *rref;
-  gfc_ref *aref;
   int nDepend = 0;
-  int temp_dim = 0;
 
   loop->temp_ss = NULL;
-  aref = dest->data.info.ref;
-  temp_dim = 0;
 
   for (ss = rss; ss != gfc_ss_terminator; ss = ss->next)
     {
@@ -3362,7 +3520,6 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest,
                  if (depends[n])
                  loop->order[dim++] = n;
                }
-             temp_dim = dim;
              for (n = 0; n < loop->dimen; n++)
                {
                  if (! depends[n])
@@ -3405,15 +3562,12 @@ void
 gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
 {
   int n;
-  int dim;
   gfc_ss_info *info;
   gfc_ss_info *specinfo;
   gfc_ss *ss;
   tree tmp;
-  tree len;
   gfc_ss *loopspec[GFC_MAX_DIMENSIONS];
   bool dynamic[GFC_MAX_DIMENSIONS];
-  gfc_constructor *c;
   mpz_t *cshape;
   mpz_t i;
 
@@ -3438,6 +3592,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
 
          if (ss->type == GFC_SS_CONSTRUCTOR)
            {
+             gfc_constructor_base base;
              /* An unknown size constructor will always be rank one.
                 Higher rank constructors will either have known shape,
                 or still be wrapped in a call to reshape.  */
@@ -3447,8 +3602,8 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
                 can be determined at compile time.  Prefer not to otherwise,
                 since the general case involves realloc, and it's better to
                 avoid that overhead if possible.  */
-             c = ss->expr->value.constructor;
-             dynamic[n] = gfc_get_array_constructor_size (&i, c);
+             base = ss->expr->value.constructor;
+             dynamic[n] = gfc_get_array_constructor_size (&i, base);
              if (!dynamic[n] || !loopspec[n])
                loopspec[n] = ss;
              continue;
@@ -3591,7 +3746,6 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
                         loop->temp_ss->string_length);
 
       tmp = loop->temp_ss->data.temp.type;
-      len = loop->temp_ss->string_length;
       n = loop->temp_ss->data.temp.dimen;
       memset (&loop->temp_ss->data.info, 0, sizeof (gfc_ss_info));
       loop->temp_ss->type = GFC_SS_SECTION;
@@ -3623,8 +3777,6 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
 
       for (n = 0; n < info->dimen; n++)
        {
-         dim = info->dim[n];
-
          /* If we are specifying the range the delta is already set.  */
          if (loopspec[n] != ss)
            {
@@ -3667,7 +3819,7 @@ gfc_conv_loop_setup (gfc_loopinfo * loop, locus * where)
 /*GCC ARRAYS*/
 
 static tree
-gfc_array_init_size (tree descriptor, int rank, tree * poffset,
+gfc_array_init_size (tree descriptor, int rank, int corank, tree * poffset,
                     gfc_expr ** lower, gfc_expr ** upper,
                     stmtblock_t * pblock)
 {
@@ -3724,8 +3876,8 @@ gfc_array_init_size (tree descriptor, int rank, tree * poffset,
               ubound = lower[n];
             }
        }
-      tmp = gfc_conv_descriptor_lbound (descriptor, gfc_rank_cst[n]);
-      gfc_add_modify (pblock, tmp, se.expr);
+      gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
+                                     se.expr);
 
       /* Work out the offset for this component.  */
       tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, se.expr, stride);
@@ -3741,12 +3893,10 @@ gfc_array_init_size (tree descriptor, int rank, tree * poffset,
       gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
       gfc_add_block_to_block (pblock, &se.pre);
 
-      tmp = gfc_conv_descriptor_ubound (descriptor, gfc_rank_cst[n]);
-      gfc_add_modify (pblock, tmp, se.expr);
+      gfc_conv_descriptor_ubound_set (pblock, descriptor, gfc_rank_cst[n], se.expr);
 
       /* Store the stride.  */
-      tmp = gfc_conv_descriptor_stride (descriptor, gfc_rank_cst[n]);
-      gfc_add_modify (pblock, tmp, stride);
+      gfc_conv_descriptor_stride_set (pblock, descriptor, gfc_rank_cst[n], stride);
 
       /* Calculate the size of this dimension.  */
       size = fold_build2 (PLUS_EXPR, gfc_array_index_type, se.expr, size);
@@ -3767,6 +3917,43 @@ gfc_array_init_size (tree descriptor, int rank, tree * poffset,
       stride = gfc_evaluate_now (stride, pblock);
     }
 
+  for (n = rank; n < rank + corank; n++)
+    {
+      ubound = upper[n];
+
+      /* Set lower bound.  */
+      gfc_init_se (&se, NULL);
+      if (lower == NULL || lower[n] == NULL)
+       {
+         gcc_assert (n == rank + corank - 1);
+         se.expr = gfc_index_one_node;
+       }
+      else
+       {
+          if (ubound || n == rank + corank - 1)
+            {
+             gfc_conv_expr_type (&se, lower[n], gfc_array_index_type);
+             gfc_add_block_to_block (pblock, &se.pre);
+            }
+          else
+            {
+              se.expr = gfc_index_one_node;
+              ubound = lower[n];
+            }
+       }
+      gfc_conv_descriptor_lbound_set (pblock, descriptor, gfc_rank_cst[n],
+                                     se.expr);
+
+      if (n < rank + corank - 1)
+       {
+         gfc_init_se (&se, NULL);
+         gcc_assert (ubound);
+         gfc_conv_expr_type (&se, ubound, gfc_array_index_type);
+         gfc_add_block_to_block (pblock, &se.pre);
+         gfc_conv_descriptor_ubound_set (pblock, descriptor, gfc_rank_cst[n], se.expr);
+       }
+    }
+
   /* The stride 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));
@@ -3815,14 +4002,15 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
   gfc_expr **lower;
   gfc_expr **upper;
   gfc_ref *ref, *prev_ref = NULL;
-  bool allocatable_array;
+  bool allocatable_array, coarray;
 
   ref = expr->ref;
 
   /* Find the last reference in the chain.  */
   while (ref && ref->next != NULL)
     {
-      gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT);
+      gcc_assert (ref->type != REF_ARRAY || ref->u.ar.type == AR_ELEMENT
+                 || (ref->u.ar.dimen == 0 && ref->u.ar.codimen > 0));
       prev_ref = ref;
       ref = ref->next;
     }
@@ -3831,16 +4019,39 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
     return false;
 
   if (!prev_ref)
-    allocatable_array = expr->symtree->n.sym->attr.allocatable;
+    {
+      allocatable_array = expr->symtree->n.sym->attr.allocatable;
+      coarray = expr->symtree->n.sym->attr.codimension;
+    }
   else
-    allocatable_array = prev_ref->u.c.component->attr.allocatable;
+    {
+      allocatable_array = prev_ref->u.c.component->attr.allocatable;
+      coarray = prev_ref->u.c.component->attr.codimension;
+    }
+
+  /* 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;
+    }
 
   /* Figure out the size of the array.  */
   switch (ref->u.ar.type)
     {
     case AR_ELEMENT:
-      lower = NULL;
-      upper = ref->u.ar.start;
+      if (!coarray)
+       {
+         lower = NULL;
+         upper = ref->u.ar.start;
+         break;
+       }
+      /* Fall through.  */
+
+    case AR_SECTION:
+      lower = ref->u.ar.start;
+      upper = ref->u.ar.end;
       break;
 
     case AR_FULL:
@@ -3850,18 +4061,14 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
       upper = ref->u.ar.as->upper;
       break;
 
-    case AR_SECTION:
-      lower = ref->u.ar.start;
-      upper = ref->u.ar.end;
-      break;
-
     default:
       gcc_unreachable ();
       break;
     }
 
-  size = gfc_array_init_size (se->expr, ref->u.ar.as->rank, &offset,
-                             lower, upper, &se->pre);
+  size = gfc_array_init_size (se->expr, ref->u.ar.as->rank,
+                             ref->u.ar.as->corank, &offset, lower, upper,
+                             &se->pre);
 
   /* Allocate memory to store the data.  */
   pointer = gfc_conv_descriptor_data_get (se->expr);
@@ -3875,13 +4082,12 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
   tmp = fold_build2 (MODIFY_EXPR, void_type_node, pointer, tmp);
   gfc_add_expr_to_block (&se->pre, tmp);
 
-  tmp = gfc_conv_descriptor_offset (se->expr);
-  gfc_add_modify (&se->pre, tmp, offset);
+  gfc_conv_descriptor_offset_set (&se->pre, se->expr, offset);
 
   if (expr->ts.type == BT_DERIVED
-       && expr->ts.derived->attr.alloc_comp)
+       && expr->ts.u.derived->attr.alloc_comp)
     {
-      tmp = gfc_nullify_alloc_comp (expr->ts.derived, se->expr,
+      tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
                                    ref->u.ar.as->rank);
       gfc_add_expr_to_block (&se->pre, tmp);
     }
@@ -3927,11 +4133,10 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
 {
   gfc_constructor *c;
   tree tmp;
-  mpz_t maxval;
   gfc_se se;
   HOST_WIDE_INT hi;
   unsigned HOST_WIDE_INT lo;
-  tree index, range;
+  tree index;
   VEC(constructor_elt,gc) *v = NULL;
 
   switch (expr->expr_type)
@@ -3966,59 +4171,31 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
 
     case EXPR_ARRAY:
       /* Create a vector of all the elements.  */
-      for (c = expr->value.constructor; c; c = c->next)
+      for (c = gfc_constructor_first (expr->value.constructor);
+          c; c = gfc_constructor_next (c))
         {
           if (c->iterator)
             {
               /* Problems occur when we get something like
                  integer :: a(lots) = (/(i, i=1, lots)/)  */
-              gfc_error_now ("The number of elements in the array constructor "
-                            "at %L requires an increase of the allowed %d "
-                            "upper limit.   See -fmax-array-constructor "
-                            "option", &expr->where,
-                            gfc_option.flag_max_array_constructor);
+              gfc_fatal_error ("The number of elements in the array constructor "
+                              "at %L requires an increase of the allowed %d "
+                              "upper limit.   See -fmax-array-constructor "
+                              "option", &expr->where,
+                              gfc_option.flag_max_array_constructor);
              return NULL_TREE;
            }
-          if (mpz_cmp_si (c->n.offset, 0) != 0)
-            index = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
+          if (mpz_cmp_si (c->offset, 0) != 0)
+            index = gfc_conv_mpz_to_tree (c->offset, gfc_index_integer_kind);
           else
             index = NULL_TREE;
-         mpz_init (maxval);
-          if (mpz_cmp_si (c->repeat, 0) != 0)
-            {
-              tree tmp1, tmp2;
-
-              mpz_set (maxval, c->repeat);
-              mpz_add (maxval, c->n.offset, maxval);
-              mpz_sub_ui (maxval, maxval, 1);
-              tmp2 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
-              if (mpz_cmp_si (c->n.offset, 0) != 0)
-                {
-                  mpz_add_ui (maxval, c->n.offset, 1);
-                  tmp1 = gfc_conv_mpz_to_tree (maxval, gfc_index_integer_kind);
-                }
-              else
-                tmp1 = gfc_conv_mpz_to_tree (c->n.offset, gfc_index_integer_kind);
-
-              range = fold_build2 (RANGE_EXPR, integer_type_node, tmp1, tmp2);
-            }
-          else
-            range = NULL;
-         mpz_clear (maxval);
 
           gfc_init_se (&se, NULL);
          switch (c->expr->expr_type)
            {
            case EXPR_CONSTANT:
              gfc_conv_constant (&se, c->expr);
-              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);
-                }
+             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
 
            case EXPR_STRUCTURE:
@@ -4032,14 +4209,7 @@ gfc_conv_array_initializer (tree type, gfc_expr * expr)
                 for one reason or another, assuming that if they are
                 standard defying the frontend will catch them.  */
              gfc_conv_expr (&se, c->expr);
-             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);
-               }
+             CONSTRUCTOR_APPEND_ELT (v, index, se.expr);
              break;
            }
         }
@@ -4167,9 +4337,9 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
 
   /* Evaluate character string length.  */
   if (sym->ts.type == BT_CHARACTER
-      && onstack && !INTEGER_CST_P (sym->ts.cl->backend_decl))
+      && onstack && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
     {
-      gfc_conv_string_length (sym->ts.cl, NULL, &block);
+      gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
 
       gfc_trans_vla_type_sizes (sym, &block);
 
@@ -4192,8 +4362,8 @@ gfc_trans_auto_array_allocation (tree decl, gfc_symbol * sym, tree fnbody)
   gcc_assert (!sym->module);
 
   if (sym->ts.type == BT_CHARACTER
-      && !INTEGER_CST_P (sym->ts.cl->backend_decl))
-    gfc_conv_string_length (sym->ts.cl, NULL, &block);
+      && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
+    gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
 
   size = gfc_trans_array_bounds (type, sym, &offset, &block);
 
@@ -4258,8 +4428,8 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
   gfc_start_block (&block);
 
   if (sym->ts.type == BT_CHARACTER
-      && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
-    gfc_conv_string_length (sym->ts.cl, NULL, &block);
+      && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
+    gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
 
   /* Evaluate the bounds of the array.  */
   gfc_trans_array_bounds (type, sym, &offset, &block);
@@ -4285,7 +4455,7 @@ gfc_trans_g77_array (gfc_symbol * sym, tree body)
   if (sym->attr.optional || sym->attr.not_always_present)
     {
       tmp = gfc_conv_expr_present (sym);
-      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
     }
   
   gfc_add_expr_to_block (&block, stmt);
@@ -4346,12 +4516,13 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
   type = TREE_TYPE (tmpdesc);
   gcc_assert (GFC_ARRAY_TYPE_P (type));
   dumdesc = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
-  dumdesc = build_fold_indirect_ref (dumdesc);
+  dumdesc = build_fold_indirect_ref_loc (input_location,
+                                    dumdesc);
   gfc_start_block (&block);
 
   if (sym->ts.type == BT_CHARACTER
-      && TREE_CODE (sym->ts.cl->backend_decl) == VAR_DECL)
-    gfc_conv_string_length (sym->ts.cl, NULL, &block);
+      && TREE_CODE (sym->ts.u.cl->backend_decl) == VAR_DECL)
+    gfc_conv_string_length (sym->ts.u.cl, NULL, &block);
 
   checkparm = (sym->as->type == AS_EXPLICIT
               && (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS));
@@ -4366,7 +4537,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
          anything as we still don't know the array stride.  */
       partial = gfc_create_var (boolean_type_node, "partial");
       TREE_USED (partial) = 1;
-      tmp = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
+      tmp = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
       tmp = fold_build2 (EQ_EXPR, boolean_type_node, tmp, gfc_index_one_node);
       gfc_add_modify (&block, partial, tmp);
     }
@@ -4380,7 +4551,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
   if (no_repack)
     {
       /* Set the first stride.  */
-      stride = gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[0]);
+      stride = gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[0]);
       stride = gfc_evaluate_now (stride, &block);
 
       tmp = fold_build2 (EQ_EXPR, boolean_type_node,
@@ -4398,7 +4569,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
       gcc_assert (integer_onep (GFC_TYPE_ARRAY_STRIDE (type, 0)));
       /* A library call to repack the array if necessary.  */
       tmp = GFC_DECL_SAVED_DESCRIPTOR (tmpdesc);
-      stmt_unpacked = build_call_expr (gfor_fndecl_in_pack, 1, tmp);
+      stmt_unpacked = build_call_expr_loc (input_location,
+                                      gfor_fndecl_in_pack, 1, tmp);
 
       stride = gfc_index_one_node;
 
@@ -4433,8 +4605,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
       if (checkparm || !sym->as->upper[n])
        {
          /* Get the bounds of the actual parameter.  */
-         dubound = gfc_conv_descriptor_ubound (dumdesc, gfc_rank_cst[n]);
-         dlbound = gfc_conv_descriptor_lbound (dumdesc, gfc_rank_cst[n]);
+         dubound = gfc_conv_descriptor_ubound_get (dumdesc, gfc_rank_cst[n]);
+         dlbound = gfc_conv_descriptor_lbound_get (dumdesc, gfc_rank_cst[n]);
        }
       else
         {
@@ -4471,15 +4643,26 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
            {
              /* Check (ubound(a) - lbound(a) == ubound(b) - lbound(b)).  */
              char * msg;
+             tree temp;
 
-             tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
-                                ubound, lbound);
-              stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
+             temp = fold_build2 (MINUS_EXPR, gfc_array_index_type,
+                                 ubound, lbound);
+             temp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+                                 gfc_index_one_node, temp);
+
+             stride2 = fold_build2 (MINUS_EXPR, gfc_array_index_type,
                                     dubound, dlbound);
-              tmp = fold_build2 (NE_EXPR, gfc_array_index_type, tmp, stride2);
-             asprintf (&msg, "%s for dimension %d of array '%s'",
-                       gfc_msg_bounds, n+1, sym->name);
-             gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg);
+             stride2 = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+                                    gfc_index_one_node, stride2);
+
+              tmp = fold_build2 (NE_EXPR, gfc_array_index_type, temp, stride2);
+             asprintf (&msg, "Dimension %d of array '%s' has extent "
+                       "%%ld instead of %%ld", n+1, sym->name);
+
+             gfc_trans_runtime_check (true, false, tmp, &block, &loc, msg, 
+                       fold_convert (long_integer_type_node, temp),
+                       fold_convert (long_integer_type_node, stride2));
+
              gfc_free (msg);
            }
        }
@@ -4504,7 +4687,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
           if (no_repack || partial != NULL_TREE)
             {
               stmt_unpacked =
-                gfc_conv_descriptor_stride (dumdesc, gfc_rank_cst[n+1]);
+                gfc_conv_descriptor_stride_get (dumdesc, gfc_rank_cst[n+1]);
             }
 
           /* Figure out the stride if not a known constant.  */
@@ -4569,7 +4752,7 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
   if (optional_arg)
     {
       tmp = gfc_conv_expr_present (sym);
-      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
     }
   gfc_add_expr_to_block (&block, stmt);
 
@@ -4584,7 +4767,8 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
       if (sym->attr.intent != INTENT_IN)
        {
          /* Copy the data back.  */
-         tmp = build_call_expr (gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
+         tmp = build_call_expr_loc (input_location,
+                                gfor_fndecl_in_unpack, 2, dumdesc, tmpdesc);
          gfc_add_expr_to_block (&cleanup, tmp);
        }
 
@@ -4595,15 +4779,17 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc, tree body)
       stmt = gfc_finish_block (&cleanup);
        
       /* Only do the cleanup if the array was repacked.  */
-      tmp = build_fold_indirect_ref (dumdesc);
+      tmp = build_fold_indirect_ref_loc (input_location,
+                                    dumdesc);
       tmp = gfc_conv_descriptor_data_get (tmp);
       tmp = fold_build2 (NE_EXPR, boolean_type_node, tmp, tmpdesc);
-      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+      stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
 
       if (optional_arg)
         {
           tmp = gfc_conv_expr_present (sym);
-          stmt = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+          stmt = build3_v (COND_EXPR, tmp, stmt,
+                          build_empty_stmt (input_location));
         }
       gfc_add_expr_to_block (&block, stmt);
     }
@@ -4637,7 +4823,8 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
     }
 
   tmp = gfc_conv_array_data (desc);
-  tmp = build_fold_indirect_ref (tmp);
+  tmp = build_fold_indirect_ref_loc (input_location,
+                                tmp);
   tmp = gfc_build_array_ref (tmp, offset, NULL);
 
   /* Offset the data pointer for pointer assignments from arrays with
@@ -4738,11 +4925,11 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
   gfc_actual_arglist *arg;
   gfc_se tse;
 
-  if (expr->ts.cl->length
-       && gfc_is_constant_expr (expr->ts.cl->length))
+  if (expr->ts.u.cl->length
+       && gfc_is_constant_expr (expr->ts.u.cl->length))
     {
-      if (!expr->ts.cl->backend_decl)
-       gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
+      if (!expr->ts.u.cl->backend_decl)
+       gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
       return;
     }
 
@@ -4751,11 +4938,11 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
     case EXPR_OP:
       get_array_charlen (expr->value.op.op1, se);
 
-      /* For parentheses the expression ts.cl is identical.  */
+      /* For parentheses the expression ts.u.cl is identical.  */
       if (expr->value.op.op == INTRINSIC_PARENTHESES)
        return;
 
-     expr->ts.cl->backend_decl =
+     expr->ts.u.cl->backend_decl =
                gfc_create_var (gfc_charlen_type_node, "sln");
 
       if (expr->value.op.op2)
@@ -4766,21 +4953,21 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
 
          /* Add the string lengths and assign them to the expression
             string length backend declaration.  */
-         gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
+         gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
                          fold_build2 (PLUS_EXPR, gfc_charlen_type_node,
-                               expr->value.op.op1->ts.cl->backend_decl,
-                               expr->value.op.op2->ts.cl->backend_decl));
+                               expr->value.op.op1->ts.u.cl->backend_decl,
+                               expr->value.op.op2->ts.u.cl->backend_decl));
        }
       else
-       gfc_add_modify (&se->pre, expr->ts.cl->backend_decl,
-                       expr->value.op.op1->ts.cl->backend_decl);
+       gfc_add_modify (&se->pre, expr->ts.u.cl->backend_decl,
+                       expr->value.op.op1->ts.u.cl->backend_decl);
       break;
 
     case EXPR_FUNCTION:
       if (expr->value.function.esym == NULL
-           || expr->ts.cl->length->expr_type == EXPR_CONSTANT)
+           || expr->ts.u.cl->length->expr_type == EXPR_CONSTANT)
        {
-         gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
+         gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
          break;
        }
 
@@ -4803,19 +4990,19 @@ get_array_charlen (gfc_expr *expr, gfc_se *se)
       gfc_init_se (&tse, NULL);
 
       /* Build the expression for the character length and convert it.  */
-      gfc_apply_interface_mapping (&mapping, &tse, expr->ts.cl->length);
+      gfc_apply_interface_mapping (&mapping, &tse, expr->ts.u.cl->length);
 
       gfc_add_block_to_block (&se->pre, &tse.pre);
       gfc_add_block_to_block (&se->post, &tse.post);
       tse.expr = fold_convert (gfc_charlen_type_node, tse.expr);
       tse.expr = fold_build2 (MAX_EXPR, gfc_charlen_type_node, tse.expr,
                              build_int_cst (gfc_charlen_type_node, 0));
-      expr->ts.cl->backend_decl = tse.expr;
+      expr->ts.u.cl->backend_decl = tse.expr;
       gfc_free_interface_mapping (&mapping);
       break;
 
     default:
-      gfc_conv_string_length (expr->ts.cl, expr, &se->pre);
+      gfc_conv_string_length (expr->ts.u.cl, expr, &se->pre);
       break;
     }
 }
@@ -4898,7 +5085,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
       else if (se->direct_byref)
        full = 0;
       else
-       full = gfc_full_array_ref_p (info->ref);
+       full = gfc_full_array_ref_p (info->ref, NULL);
 
       if (full)
        {
@@ -4956,7 +5143,7 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
          /* Elemental function.  */
          need_tmp = 1;
          if (expr->ts.type == BT_CHARACTER
-               && expr->ts.cl->length->expr_type != EXPR_CONSTANT)
+               && expr->ts.u.cl->length->expr_type != EXPR_CONSTANT)
            get_array_charlen (expr, se);
 
          info = NULL;
@@ -5018,13 +5205,13 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
       loop.temp_ss->next = gfc_ss_terminator;
 
       if (expr->ts.type == BT_CHARACTER
-           && !expr->ts.cl->backend_decl)
+           && !expr->ts.u.cl->backend_decl)
        get_array_charlen (expr, se);
 
       loop.temp_ss->data.temp.type = gfc_typenode_for_spec (&expr->ts);
 
       if (expr->ts.type == BT_CHARACTER)
-       loop.temp_ss->string_length = expr->ts.cl->backend_decl;
+       loop.temp_ss->string_length = expr->ts.u.cl->backend_decl;
       else
        loop.temp_ss->string_length = NULL;
 
@@ -5062,7 +5249,8 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
        {
          gfc_conv_expr (&rse, expr);
          if (POINTER_TYPE_P (TREE_TYPE (rse.expr)))
-           rse.expr = build_fold_indirect_ref (rse.expr);
+           rse.expr = build_fold_indirect_ref_loc (input_location,
+                                               rse.expr);
        }
       else
         gfc_conv_expr_val (&rse, expr);
@@ -5072,7 +5260,7 @@ 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);
+                                    expr->expr_type == EXPR_VARIABLE, true);
       gfc_add_expr_to_block (&block, tmp);
 
       /* Finish the copying loops.  */
@@ -5118,9 +5306,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,
+         parmtype = gfc_get_array_type_bounds (parmtype, loop.dimen, 0,
                                                loop.from, loop.to, 0,
-                                               GFC_ARRAY_UNKNOWN);
+                                               GFC_ARRAY_UNKNOWN, false);
          parm = gfc_create_var (parmtype, "parm");
        }
 
@@ -5206,19 +5394,21 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
              to = fold_build2 (PLUS_EXPR, gfc_array_index_type, to, tmp);
              from = gfc_index_one_node;
            }
-         tmp = gfc_conv_descriptor_lbound (parm, gfc_rank_cst[dim]);
-         gfc_add_modify (&loop.pre, tmp, from);
+         gfc_conv_descriptor_lbound_set (&loop.pre, parm,
+                                         gfc_rank_cst[dim], from);
 
          /* Set the new upper bound.  */
-         tmp = gfc_conv_descriptor_ubound (parm, gfc_rank_cst[dim]);
-         gfc_add_modify (&loop.pre, tmp, to);
+         gfc_conv_descriptor_ubound_set (&loop.pre, parm,
+                                         gfc_rank_cst[dim], to);
 
          /* Multiply the stride by the section stride to get the
             total stride.  */
          stride = fold_build2 (MULT_EXPR, gfc_array_index_type,
                                stride, info->stride[dim]);
 
-         if (se->direct_byref && info->ref && info->ref->u.ar.type != AR_FULL)
+         if (se->direct_byref
+               && info->ref
+               && info->ref->u.ar.type != AR_FULL)
            {
              base = fold_build2 (MINUS_EXPR, TREE_TYPE (base),
                                  base, stride);
@@ -5235,16 +5425,17 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
            }
 
          /* Store the new stride.  */
-         tmp = gfc_conv_descriptor_stride (parm, gfc_rank_cst[dim]);
-         gfc_add_modify (&loop.pre, tmp, stride);
+         gfc_conv_descriptor_stride_set (&loop.pre, parm,
+                                         gfc_rank_cst[dim], stride);
 
          dim++;
        }
 
       if (se->data_not_needed)
-       gfc_conv_descriptor_data_set (&loop.pre, parm, gfc_index_zero_node);
+       gfc_conv_descriptor_data_set (&loop.pre, parm,
+                                     gfc_index_zero_node);
       else
-       /* Point the data pointer at the first element in the section.  */
+       /* Point the data pointer at the 1st element in the section.  */
        gfc_get_dataptr_offset (&loop.pre, parm, desc, offset,
                                subref_array_target, expr);
 
@@ -5252,15 +5443,13 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
          && !se->data_not_needed)
        {
          /* Set the offset.  */
-         tmp = gfc_conv_descriptor_offset (parm);
-         gfc_add_modify (&loop.pre, tmp, base);
+         gfc_conv_descriptor_offset_set (&loop.pre, parm, base);
        }
       else
        {
          /* Only the callee knows what the correct offset it, so just set
             it to zero here.  */
-         tmp = gfc_conv_descriptor_offset (parm);
-         gfc_add_modify (&loop.pre, tmp, gfc_index_zero_node);
+         gfc_conv_descriptor_offset_set (&loop.pre, parm, gfc_index_zero_node);
        }
       desc = parm;
     }
@@ -5281,35 +5470,89 @@ gfc_conv_expr_descriptor (gfc_se * se, gfc_expr * expr, gfc_ss * ss)
   gfc_cleanup_loop (&loop);
 }
 
+/* Helper function for gfc_conv_array_parameter if array size needs to be
+   computed.  */
+
+static void
+array_parameter_size (tree desc, gfc_expr *expr, tree *size)
+{
+  tree elem;
+  if (GFC_ARRAY_TYPE_P (TREE_TYPE (desc)))
+    *size = GFC_TYPE_ARRAY_SIZE (TREE_TYPE (desc));
+  else if (expr->rank > 1)
+    *size = build_call_expr_loc (input_location,
+                            gfor_fndecl_size0, 1,
+                            gfc_build_addr_expr (NULL, desc));
+  else
+    {
+      tree ubound = gfc_conv_descriptor_ubound_get (desc, gfc_index_zero_node);
+      tree lbound = gfc_conv_descriptor_lbound_get (desc, gfc_index_zero_node);
+
+      *size = fold_build2 (MINUS_EXPR, gfc_array_index_type, ubound, lbound);
+      *size = fold_build2 (PLUS_EXPR, gfc_array_index_type, *size,
+                          gfc_index_one_node);
+      *size = fold_build2 (MAX_EXPR, gfc_array_index_type, *size,
+                          gfc_index_zero_node);
+    }
+  elem = TYPE_SIZE_UNIT (gfc_get_element_type (TREE_TYPE (desc)));
+  *size = fold_build2 (MULT_EXPR, gfc_array_index_type, *size,
+                      fold_convert (gfc_array_index_type, elem));
+}
 
 /* Convert an array for passing as an actual parameter.  */
 /* TODO: Optimize passing g77 arrays.  */
 
 void
-gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
-                         const gfc_symbol *fsym, const char *proc_name)
+gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, bool g77,
+                         const gfc_symbol *fsym, const char *proc_name,
+                         tree *size)
 {
   tree ptr;
   tree desc;
   tree tmp = NULL_TREE;
   tree stmt;
   tree parent = DECL_CONTEXT (current_function_decl);
-  bool full_array_var, this_array_result;
+  bool full_array_var;
+  bool this_array_result;
+  bool contiguous;
+  bool no_pack;
+  bool array_constructor;
+  bool good_allocatable;
+  bool ultimate_ptr_comp;
+  bool ultimate_alloc_comp;
   gfc_symbol *sym;
   stmtblock_t block;
+  gfc_ref *ref;
+
+  ultimate_ptr_comp = false;
+  ultimate_alloc_comp = false;
+  for (ref = expr->ref; ref; ref = ref->next)
+    {
+      if (ref->next == NULL)
+        break;
+
+      if (ref->type == REF_COMPONENT)
+       {
+         ultimate_ptr_comp = ref->u.c.component->attr.pointer;
+         ultimate_alloc_comp = ref->u.c.component->attr.allocatable;
+       }
+    }
+
+  full_array_var = false;
+  contiguous = false;
+
+  if (expr->expr_type == EXPR_VARIABLE && ref && !ultimate_ptr_comp)
+    full_array_var = gfc_full_array_ref_p (ref, &contiguous);
 
-  full_array_var = (expr->expr_type == EXPR_VARIABLE
-                   && expr->ref->type == REF_ARRAY
-                   && expr->ref->u.ar.type == AR_FULL);
   sym = full_array_var ? expr->symtree->n.sym : NULL;
 
   /* The symbol should have an array specification.  */
-  gcc_assert (!sym || sym->as);
+  gcc_assert (!sym || sym->as || ref->u.ar.as);
 
   if (expr->expr_type == EXPR_ARRAY && expr->ts.type == BT_CHARACTER)
     {
       get_array_ctor_strlen (&se->pre, expr->value.constructor, &tmp);
-      expr->ts.cl->backend_decl = tmp;
+      expr->ts.u.cl->backend_decl = tmp;
       se->string_length = tmp;
     }
 
@@ -5326,9 +5569,19 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
       tmp = gfc_get_symbol_decl (sym);
 
       if (sym->ts.type == BT_CHARACTER)
-       se->string_length = sym->ts.cl->backend_decl;
-      if (!sym->attr.pointer && sym->as->type != AS_ASSUMED_SHAPE 
-          && !sym->attr.allocatable)
+       se->string_length = sym->ts.u.cl->backend_decl;
+
+      if (sym->ts.type == BT_DERIVED)
+       {
+         gfc_conv_expr_descriptor (se, expr, ss);
+         se->expr = gfc_conv_array_data (se->expr);
+         return;
+       }
+
+      if (!sym->attr.pointer
+           && sym->as
+           && sym->as->type != AS_ASSUMED_SHAPE 
+            && !sym->attr.allocatable)
         {
          /* Some variables are declared directly, others are declared as
             pointers and allocated on the heap.  */
@@ -5336,30 +5589,75 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
             se->expr = tmp;
           else
            se->expr = gfc_build_addr_expr (NULL_TREE, tmp);
+         if (size)
+           array_parameter_size (tmp, expr, size);
          return;
         }
+
       if (sym->attr.allocatable)
         {
          if (sym->attr.dummy || sym->attr.result)
            {
              gfc_conv_expr_descriptor (se, expr, ss);
-             se->expr = gfc_conv_array_data (se->expr);
+             tmp = se->expr;
            }
-         else
-           se->expr = gfc_conv_array_data (tmp);
+         if (size)
+           array_parameter_size (tmp, expr, size);
+         se->expr = gfc_conv_array_data (tmp);
           return;
         }
     }
 
+  /* A convenient reduction in scope.  */
+  contiguous = g77 && !this_array_result && contiguous;
+
+  /* There is no need to pack and unpack the array, if it is contiguous
+     and not deferred or assumed shape.  */
+  no_pack = ((sym && sym->as
+                 && !sym->attr.pointer
+                 && sym->as->type != AS_DEFERRED
+                 && sym->as->type != AS_ASSUMED_SHAPE)
+                     ||
+            (ref && ref->u.ar.as
+                 && ref->u.ar.as->type != AS_DEFERRED
+                 && ref->u.ar.as->type != AS_ASSUMED_SHAPE));
+
+  no_pack = contiguous && no_pack;
+
+  /* Array constructors are always contiguous and do not need packing.  */
+  array_constructor = g77 && !this_array_result && expr->expr_type == EXPR_ARRAY;
+
+  /* Same is true of contiguous sections from allocatable variables.  */
+  good_allocatable = contiguous
+                      && expr->symtree
+                      && expr->symtree->n.sym->attr.allocatable;
+
+  /* Or ultimate allocatable components.  */
+  ultimate_alloc_comp = contiguous && ultimate_alloc_comp; 
+
+  if (no_pack || array_constructor || good_allocatable || ultimate_alloc_comp)
+    {
+      gfc_conv_expr_descriptor (se, expr, ss);
+      if (expr->ts.type == BT_CHARACTER)
+       se->string_length = expr->ts.u.cl->backend_decl;
+      if (size)
+       array_parameter_size (se->expr, expr, size);
+      se->expr = gfc_conv_array_data (se->expr);
+      return;
+    }
+
   if (this_array_result)
     {
       /* Result of the enclosing function.  */
       gfc_conv_expr_descriptor (se, expr, ss);
+      if (size)
+       array_parameter_size (se->expr, expr, size);
       se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
 
       if (g77 && TREE_TYPE (TREE_TYPE (se->expr)) != NULL_TREE
              && GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (TREE_TYPE (se->expr))))
-       se->expr = gfc_conv_array_data (build_fold_indirect_ref (se->expr));
+       se->expr = gfc_conv_array_data (build_fold_indirect_ref_loc (input_location,
+                                                                se->expr));
 
       return;
     }
@@ -5368,16 +5666,21 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
       /* Every other type of array.  */
       se->want_pointer = 1;
       gfc_conv_expr_descriptor (se, expr, ss);
+      if (size)
+       array_parameter_size (build_fold_indirect_ref_loc (input_location,
+                                                      se->expr),
+                                 expr, size);
     }
 
   /* Deallocate the allocatable components of structures that are
      not variable.  */
   if (expr->ts.type == BT_DERIVED
-       && expr->ts.derived->attr.alloc_comp
+       && expr->ts.u.derived->attr.alloc_comp
        && expr->expr_type != EXPR_VARIABLE)
     {
-      tmp = build_fold_indirect_ref (se->expr);
-      tmp = gfc_deallocate_alloc_comp (expr->ts.derived, tmp, expr->rank);
+      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);
     }
 
@@ -5385,7 +5688,6 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
     {
       desc = se->expr;
       /* Repack the array.  */
-
       if (gfc_option.warn_array_temp)
        {
          if (fsym)
@@ -5395,7 +5697,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
            gfc_warning ("Creating array temporary at %L", &expr->where);
        }
 
-      ptr = build_call_expr (gfor_fndecl_in_pack, 1, desc);
+      ptr = build_call_expr_loc (input_location,
+                            gfor_fndecl_in_pack, 1, desc);
 
       if (fsym && fsym->attr.optional && sym && sym->attr.optional)
        {
@@ -5419,7 +5722,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
          else
            asprintf (&msg, "An array temporary was created");
 
-         tmp = build_fold_indirect_ref (desc);
+         tmp = build_fold_indirect_ref_loc (input_location,
+                                        desc);
          tmp = gfc_conv_array_data (tmp);
          tmp = fold_build2 (NE_EXPR, boolean_type_node,
                             fold_convert (TREE_TYPE (tmp), ptr), tmp);
@@ -5438,7 +5742,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
       /* Copy the data back.  */
       if (fsym == NULL || fsym->attr.intent != INTENT_IN)
        {
-         tmp = build_call_expr (gfor_fndecl_in_unpack, 2, desc, ptr);
+         tmp = build_call_expr_loc (input_location,
+                                gfor_fndecl_in_unpack, 2, desc, ptr);
          gfc_add_expr_to_block (&block, tmp);
        }
 
@@ -5451,7 +5756,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
       gfc_init_block (&block);
       /* Only if it was repacked.  This code needs to be executed before the
          loop cleanup code.  */
-      tmp = build_fold_indirect_ref (desc);
+      tmp = build_fold_indirect_ref_loc (input_location,
+                                    desc);
       tmp = gfc_conv_array_data (tmp);
       tmp = fold_build2 (NE_EXPR, boolean_type_node,
                         fold_convert (TREE_TYPE (tmp), ptr), tmp);
@@ -5460,7 +5766,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
        tmp = fold_build2 (TRUTH_AND_EXPR, boolean_type_node,
                           gfc_conv_expr_present (sym), tmp);
 
-      tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt ());
+      tmp = build3_v (COND_EXPR, tmp, stmt, build_empty_stmt (input_location));
 
       gfc_add_expr_to_block (&block, tmp);
       gfc_add_block_to_block (&block, &se->post);
@@ -5509,23 +5815,25 @@ get_full_array_size (stmtblock_t *block, tree decl, int rank)
   tree nelems;
   tree tmp;
   idx = gfc_rank_cst[rank - 1];
-  nelems = gfc_conv_descriptor_ubound (decl, idx);
-  tmp = gfc_conv_descriptor_lbound (decl, idx);
+  nelems = gfc_conv_descriptor_ubound_get (decl, idx);
+  tmp = gfc_conv_descriptor_lbound_get (decl, idx);
   tmp = fold_build2 (MINUS_EXPR, gfc_array_index_type, nelems, tmp);
   tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
                     tmp, gfc_index_one_node);
   tmp = gfc_evaluate_now (tmp, block);
 
-  nelems = gfc_conv_descriptor_stride (decl, idx);
+  nelems = gfc_conv_descriptor_stride_get (decl, idx);
   tmp = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
   return gfc_evaluate_now (tmp, block);
 }
 
 
-/* Allocate dest to the same size as src, and copy src -> dest.  */
+/* Allocate dest to the same size as src, and copy src -> dest.
+   If no_malloc is set, only the copy is done.  */
 
-tree
-gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
+static tree
+duplicate_allocatable(tree dest, tree src, tree type, int rank,
+                     bool no_malloc)
 {
   tree tmp;
   tree size;
@@ -5534,34 +5842,66 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
   tree null_data;
   stmtblock_t block;
 
-  /* If the source is null, set the destination to null.  */
+  /* If the source is null, set the destination to null.  Then,
+     allocate memory to the destination.  */
   gfc_init_block (&block);
-  gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
-  null_data = gfc_finish_block (&block);
 
-  gfc_init_block (&block);
+  if (rank == 0)
+    {
+      tmp = null_pointer_node;
+      tmp = fold_build2 (MODIFY_EXPR, type, dest, tmp);
+      gfc_add_expr_to_block (&block, tmp);
+      null_data = gfc_finish_block (&block);
+
+      gfc_init_block (&block);
+      size = TYPE_SIZE_UNIT (type);
+      if (!no_malloc)
+       {
+         tmp = gfc_call_malloc (&block, type, size);
+         tmp = fold_build2 (MODIFY_EXPR, void_type_node, dest,
+                            fold_convert (type, tmp));
+         gfc_add_expr_to_block (&block, tmp);
+       }
+
+      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = build_call_expr_loc (input_location, tmp, 3,
+                                dest, src, size);
+    }
+  else
+    {
+      gfc_conv_descriptor_data_set (&block, dest, null_pointer_node);
+      null_data = gfc_finish_block (&block);
+
+      gfc_init_block (&block);
+      nelems = get_full_array_size (&block, src, rank);
+      tmp = fold_convert (gfc_array_index_type,
+                         TYPE_SIZE_UNIT (gfc_get_element_type (type)));
+      size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems, tmp);
+      if (!no_malloc)
+       {
+         tmp = TREE_TYPE (gfc_conv_descriptor_data_get (src));
+         tmp = gfc_call_malloc (&block, tmp, size);
+         gfc_conv_descriptor_data_set (&block, dest, tmp);
+       }
+
+      /* We know the temporary and the value will be the same length,
+        so can use memcpy.  */
+      tmp = built_in_decls[BUILT_IN_MEMCPY];
+      tmp = build_call_expr_loc (input_location,
+                       tmp, 3, gfc_conv_descriptor_data_get (dest),
+                       gfc_conv_descriptor_data_get (src), size);
+    }
 
-  nelems = get_full_array_size (&block, src, rank);
-  size = fold_build2 (MULT_EXPR, gfc_array_index_type, nelems,
-                     fold_convert (gfc_array_index_type,
-                                   TYPE_SIZE_UNIT (gfc_get_element_type (type))));
-
-  /* Allocate memory to the destination.  */
-  tmp = gfc_call_malloc (&block, TREE_TYPE (gfc_conv_descriptor_data_get (src)),
-                        size);
-  gfc_conv_descriptor_data_set (&block, dest, tmp);
-
-  /* We know the temporary and the value will be the same length,
-     so can use memcpy.  */
-  tmp = built_in_decls[BUILT_IN_MEMCPY];
-  tmp = build_call_expr (tmp, 3, gfc_conv_descriptor_data_get (dest),
-                        gfc_conv_descriptor_data_get (src), size);
   gfc_add_expr_to_block (&block, tmp);
   tmp = gfc_finish_block (&block);
 
   /* Null the destination if the source is null; otherwise do
      the allocate and copy.  */
-  null_cond = gfc_conv_descriptor_data_get (src);
+  if (rank == 0)
+    null_cond = src;
+  else
+    null_cond = gfc_conv_descriptor_data_get (src);
+
   null_cond = convert (pvoid_type_node, null_cond);
   null_cond = fold_build2 (NE_EXPR, boolean_type_node,
                           null_cond, null_pointer_node);
@@ -5569,11 +5909,30 @@ gfc_duplicate_allocatable(tree dest, tree src, tree type, int rank)
 }
 
 
+/* Allocate dest to the same size as src, and copy data src -> dest.  */
+
+tree
+gfc_duplicate_allocatable (tree dest, tree src, tree type, int rank)
+{
+  return duplicate_allocatable(dest, src, type, rank, false);
+}
+
+
+/* Copy data src -> dest.  */
+
+tree
+gfc_copy_allocatable_data (tree dest, tree src, tree type, int rank)
+{
+  return duplicate_allocatable(dest, src, type, rank, true);
+}
+
+
 /* Recursively traverse an object of derived type, generating code to
    deallocate, nullify or copy allocatable components.  This is the work horse
    function for the functions named in this enum.  */
 
-enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP};
+enum {DEALLOCATE_ALLOC_COMP = 1, NULLIFY_ALLOC_COMP, COPY_ALLOC_COMP,
+      COPY_ONLY_ALLOC_COMP};
 
 static tree
 structure_alloc_comps (gfc_symbol * der_type, tree decl,
@@ -5596,8 +5955,9 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 
   gfc_init_block (&fnblock);
 
-  if (POINTER_TYPE_P (TREE_TYPE (decl)))
-    decl = build_fold_indirect_ref (decl);
+  if (POINTER_TYPE_P (TREE_TYPE (decl)) && rank != 0)
+    decl = build_fold_indirect_ref_loc (input_location,
+                                   decl);
 
   /* If this an array of derived types with allocatable components
      build a loop and recursively call this function.  */
@@ -5605,7 +5965,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
        || GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
     {
       tmp = gfc_conv_array_data (decl);
-      var = build_fold_indirect_ref (tmp);
+      var = build_fold_indirect_ref_loc (input_location,
+                                    tmp);
        
       /* Get the number of elements - 1 and set the counter.  */
       if (GFC_DESCRIPTOR_TYPE_P (TREE_TYPE (decl)))
@@ -5644,10 +6005,19 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
              tmp = gfc_duplicate_allocatable (dest, decl, TREE_TYPE(decl), rank);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
-         tmp = build_fold_indirect_ref (gfc_conv_array_data (dest));
+         tmp = build_fold_indirect_ref_loc (input_location,
+                                        gfc_conv_array_data (dest));
          dref = gfc_build_array_ref (tmp, index, NULL);
          tmp = structure_alloc_comps (der_type, vref, dref, rank, purpose);
        }
+      else if (purpose == COPY_ONLY_ALLOC_COMP)
+        {
+         tmp = build_fold_indirect_ref_loc (input_location,
+                                        gfc_conv_array_data (dest));
+         dref = gfc_build_array_ref (tmp, index, NULL);
+         tmp = structure_alloc_comps (der_type, vref, dref, rank,
+                                      COPY_ALLOC_COMP);
+       }
       else
         tmp = structure_alloc_comps (der_type, vref, NULL_TREE, rank, purpose);
 
@@ -5664,7 +6034,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 
       tmp = gfc_finish_block (&fnblock);
       if (null_cond != NULL_TREE)
-       tmp = build3_v (COND_EXPR, null_cond, tmp, build_empty_stmt ());
+       tmp = build3_v (COND_EXPR, null_cond, tmp,
+                       build_empty_stmt (input_location));
 
       return tmp;
     }
@@ -5674,7 +6045,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
   for (c = der_type->components; c; c = c->next)
     {
       bool cmp_has_alloc_comps = (c->ts.type == BT_DERIVED)
-                                   && c->ts.derived->attr.alloc_comp;
+                                   && c->ts.u.derived->attr.alloc_comp;
       cdecl = c->backend_decl;
       ctype = TREE_TYPE (cdecl);
 
@@ -5688,35 +6059,86 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
              comp = fold_build3 (COMPONENT_REF, ctype,
                                  decl, cdecl, NULL_TREE);
              rank = c->as ? c->as->rank : 0;
-             tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
+             tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
                                           rank, purpose);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
 
-         if (c->attr.allocatable)
+         if (c->attr.allocatable && c->attr.dimension)
            {
              comp = fold_build3 (COMPONENT_REF, ctype,
                                  decl, cdecl, NULL_TREE);
              tmp = gfc_trans_dealloc_allocated (comp);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
+         else if (c->attr.allocatable)
+           {
+             /* Allocatable scalar components.  */
+             comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
+
+             tmp = gfc_deallocate_with_status (comp, NULL_TREE, true, NULL);
+             gfc_add_expr_to_block (&fnblock, tmp);
+
+             tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
+                                build_int_cst (TREE_TYPE (comp), 0));
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
+         else if (c->ts.type == BT_CLASS
+                  && c->ts.u.derived->components->attr.allocatable)
+           {
+             /* Allocatable scalar CLASS components.  */
+             comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
+             
+             /* Add reference to '$data' component.  */
+             tmp = c->ts.u.derived->components->backend_decl;
+             comp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
+                                 comp, tmp, NULL_TREE);
+
+             tmp = gfc_deallocate_with_status (comp, NULL_TREE, true, NULL);
+             gfc_add_expr_to_block (&fnblock, tmp);
+
+             tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
+                                build_int_cst (TREE_TYPE (comp), 0));
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
          break;
 
        case NULLIFY_ALLOC_COMP:
          if (c->attr.pointer)
            continue;
-         else if (c->attr.allocatable)
+         else if (c->attr.allocatable && c->attr.dimension)
            {
              comp = fold_build3 (COMPONENT_REF, ctype,
                                  decl, cdecl, NULL_TREE);
              gfc_conv_descriptor_data_set (&fnblock, comp, null_pointer_node);
            }
+         else if (c->attr.allocatable)
+           {
+             /* Allocatable scalar components.  */
+             comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
+             tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
+                                build_int_cst (TREE_TYPE (comp), 0));
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
+         else if (c->ts.type == BT_CLASS
+                  && c->ts.u.derived->components->attr.allocatable)
+           {
+             /* Allocatable scalar CLASS components.  */
+             comp = fold_build3 (COMPONENT_REF, ctype, decl, cdecl, NULL_TREE);
+             /* Add reference to '$data' component.  */
+             tmp = c->ts.u.derived->components->backend_decl;
+             comp = fold_build3 (COMPONENT_REF, TREE_TYPE (tmp),
+                                 comp, tmp, NULL_TREE);
+             tmp = fold_build2 (MODIFY_EXPR, void_type_node, comp,
+                                build_int_cst (TREE_TYPE (comp), 0));
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
           else if (cmp_has_alloc_comps)
            {
              comp = fold_build3 (COMPONENT_REF, ctype,
                                  decl, cdecl, NULL_TREE);
              rank = c->as ? c->as->rank : 0;
-             tmp = structure_alloc_comps (c->ts.derived, comp, NULL_TREE,
+             tmp = structure_alloc_comps (c->ts.u.derived, comp, NULL_TREE,
                                           rank, purpose);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
@@ -5733,7 +6155,8 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
 
          if (c->attr.allocatable && !cmp_has_alloc_comps)
            {
-             tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, c->as->rank);
+             rank = c->as ? c->as->rank : 0;
+             tmp = gfc_duplicate_allocatable(dcmp, comp, ctype, rank);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
 
@@ -5742,7 +6165,7 @@ structure_alloc_comps (gfc_symbol * der_type, tree decl,
              rank = c->as ? c->as->rank : 0;
              tmp = fold_convert (TREE_TYPE (dcmp), comp);
              gfc_add_modify (&fnblock, dcmp, tmp);
-             tmp = structure_alloc_comps (c->ts.derived, comp, dcmp,
+             tmp = structure_alloc_comps (c->ts.u.derived, comp, dcmp,
                                           rank, purpose);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
@@ -5780,7 +6203,7 @@ gfc_deallocate_alloc_comp (gfc_symbol * der_type, tree decl, int rank)
 
 
 /* Recursively traverse an object of derived type, generating code to
-   copy its allocatable components.  */
+   copy it and its allocatable components.  */
 
 tree
 gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
@@ -5789,6 +6212,35 @@ gfc_copy_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
 }
 
 
+/* Recursively traverse an object of derived type, generating code to
+   copy only its allocatable components.  */
+
+tree
+gfc_copy_only_alloc_comp (gfc_symbol * der_type, tree decl, tree dest, int rank)
+{
+  return structure_alloc_comps (der_type, decl, dest, rank, COPY_ONLY_ALLOC_COMP);
+}
+
+
+/* Check for default initializer; sym->value is not enough as it is also
+   set for EXPR_NULL of allocatables.  */
+
+static bool
+has_default_initializer (gfc_symbol *der)
+{
+  gfc_component *c;
+
+  gcc_assert (der->attr.flavor == FL_DERIVED);
+  for (c = der->components; c; c = c->next)
+    if ((c->ts.type != BT_DERIVED && c->initializer)
+        || (c->ts.type == BT_DERIVED
+            && (!c->attr.pointer && has_default_initializer (c->ts.u.derived))))
+      break;
+
+  return c != NULL;
+}
+
+
 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
    Do likewise, recursively if necessary, with the allocatable components of
    derived types.  */
@@ -5805,7 +6257,7 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
   bool sym_has_alloc_comp;
 
   sym_has_alloc_comp = (sym->ts.type == BT_DERIVED)
-                         && sym->ts.derived->attr.alloc_comp;
+                         && sym->ts.u.derived->attr.alloc_comp;
 
   /* Make sure the frontend gets these right.  */
   if (!(sym->attr.pointer || sym->attr.allocatable || sym_has_alloc_comp))
@@ -5819,9 +6271,9 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
                || TREE_CODE (sym->backend_decl) == PARM_DECL);
 
   if (sym->ts.type == BT_CHARACTER
-      && !INTEGER_CST_P (sym->ts.cl->backend_decl))
+      && !INTEGER_CST_P (sym->ts.u.cl->backend_decl))
     {
-      gfc_conv_string_length (sym->ts.cl, NULL, &fnblock);
+      gfc_conv_string_length (sym->ts.u.cl, NULL, &fnblock);
       gfc_trans_vla_type_sizes (sym, &fnblock);
     }
 
@@ -5849,17 +6301,21 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
 
   /* Get the descriptor type.  */
   type = TREE_TYPE (sym->backend_decl);
-    
+
   if (sym_has_alloc_comp && !(sym->attr.pointer || sym->attr.allocatable))
     {
-      if (!sym->attr.save)
+      if (!sym->attr.save
+         && !(TREE_STATIC (sym->backend_decl) && sym->attr.is_main_program))
        {
-         rank = sym->as ? sym->as->rank : 0;
-         tmp = gfc_nullify_alloc_comp (sym->ts.derived, descriptor, rank);
-         gfc_add_expr_to_block (&fnblock, tmp);
-         if (sym->value)
+         if (sym->value == NULL || !has_default_initializer (sym->ts.u.derived))
            {
-             tmp = gfc_init_default_dt (sym, NULL);
+             rank = sym->as ? sym->as->rank : 0;
+             tmp = gfc_nullify_alloc_comp (sym->ts.u.derived, descriptor, rank);
+             gfc_add_expr_to_block (&fnblock, tmp);
+           }
+         else
+           {
+             tmp = gfc_init_default_dt (sym, NULL, false);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
        }
@@ -5868,7 +6324,8 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
     {
       /* If the backend_decl is not a descriptor, we must have a pointer
         to one.  */
-      descriptor = build_fold_indirect_ref (sym->backend_decl);
+      descriptor = build_fold_indirect_ref_loc (input_location,
+                                           sym->backend_decl);
       type = TREE_TYPE (descriptor);
     }
   
@@ -5887,11 +6344,12 @@ gfc_trans_deferred_array (gfc_symbol * sym, tree body)
     {
       int rank;
       rank = sym->as ? sym->as->rank : 0;
-      tmp = gfc_deallocate_alloc_comp (sym->ts.derived, descriptor, rank);
+      tmp = gfc_deallocate_alloc_comp (sym->ts.u.derived, descriptor, rank);
       gfc_add_expr_to_block (&fnblock, tmp);
     }
 
-  if (sym->attr.allocatable && !sym->attr.save && !sym->attr.result)
+  if (sym->attr.allocatable && sym->attr.dimension
+      && !sym->attr.save && !sym->attr.result)
     {
       tmp = gfc_trans_dealloc_allocated (sym->backend_decl);
       gfc_add_expr_to_block (&fnblock, tmp);
@@ -5921,7 +6379,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
   gfc_ref *ref;
   gfc_array_ref *ar;
   gfc_ss *newss;
-  gfc_ss *head;
   int n;
 
   for (ref = expr->ref; ref; ref = ref->next)
@@ -5950,6 +6407,13 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
        continue;
 
       ar = &ref->u.ar;
+
+      if (ar->as->rank == 0)
+       {
+         /* Scalar coarray.  */
+         continue;
+       }
+
       switch (ar->type)
        {
        case AR_ELEMENT:
@@ -5994,8 +6458,6 @@ gfc_walk_variable_expr (gfc_ss * ss, gfc_expr * expr)
          newss->data.info.dimen = 0;
          newss->data.info.ref = ref;
 
-         head = newss;
-
           /* We add SS chains for all the subscripts in the section.  */
          for (n = 0; n < ar->dimen; n++)
            {
@@ -6199,6 +6661,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
   gfc_ss *newss;
   gfc_intrinsic_sym *isym;
   gfc_symbol *sym;
+  gfc_component *comp = NULL;
 
   isym = expr->value.function.isym;
 
@@ -6211,7 +6674,9 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
       sym = expr->symtree->n.sym;
 
   /* A function that returns arrays.  */
-  if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
+  gfc_is_proc_ptr_comp (expr, &comp);
+  if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
+      || (comp && comp->attr.dimension))
     {
       newss = gfc_get_ss ();
       newss->type = GFC_SS_FUNCTION;