OSDN Git Service

* trans-expr.c: Do not include convert.h, ggc.h, real.h, and gimple.h.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / trans-array.c
index 5a371b8..1f6021a 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>
@@ -80,12 +80,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tree.h"
-#include "gimple.h"
-#include "ggc.h"
 #include "toplev.h"
-#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 +92,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;
@@ -284,6 +282,12 @@ 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);
 }
 
@@ -614,11 +618,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
@@ -635,7 +641,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);
@@ -715,8 +722,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;
 
@@ -828,7 +835,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;
@@ -838,10 +845,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);
@@ -1007,8 +1012,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;
@@ -1019,7 +1025,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))
@@ -1077,7 +1083,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)
@@ -1223,7 +1230,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)
 {
@@ -1231,12 +1238,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))
@@ -1281,7 +1289,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)
@@ -1297,14 +1305,13 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
          else
            {
              /* Collect multiple scalar constants into a constructor.  */
-             tree list;
+             VEC(constructor_elt,gc) *v = NULL;
              tree init;
              tree bound;
              tree tmptype;
              HOST_WIDE_INT idx = 0;
 
              p = c;
-             list = NULL_TREE;
               /* Count the number of consecutive scalar constants.  */
              while (p && !(p->iterator
                            || p->expr->expr_type != EXPR_CONSTANT))
@@ -1321,10 +1328,12 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                                (gfc_get_pchar_type (p->expr->ts.kind),
                                 se.expr);
 
-                 list = tree_cons (build_int_cst (gfc_array_index_type,
-                                                  idx++), se.expr, list);
+                  CONSTRUCTOR_APPEND_ELT (v,
+                                          build_int_cst (gfc_array_index_type,
+                                                         idx++),
+                                          se.expr);
                  c = p;
-                 p = p->next;
+                 p = gfc_constructor_next (p);
                }
 
              bound = build_int_cst (NULL_TREE, n - 1);
@@ -1333,7 +1342,7 @@ gfc_trans_array_constructor_value (stmtblock_t * pblock, tree type,
                                          gfc_index_zero_node, bound);
              tmptype = build_array_type (type, tmptype);
 
-             init = build_constructor_from_list (tmptype, nreverse (list));
+             init = build_constructor (tmptype, v);
              TREE_CONSTANT (init) = 1;
              TREE_STATIC (init) = 1;
              /* Create a static variable to hold the data.  */
@@ -1346,14 +1355,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);
 
@@ -1442,7 +1453,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.  */
@@ -1520,7 +1532,7 @@ get_array_ctor_var_strlen (gfc_expr * expr, tree * len)
        }
     }
 
-  *len = ts->cl->backend_decl;
+  *len = ts->u.cl->backend_decl;
 }
 
 
@@ -1536,12 +1548,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
     {
@@ -1562,7 +1574,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;
     }
 }
 
@@ -1574,13 +1586,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);
@@ -1590,7 +1603,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)
        {
@@ -1630,17 +1644,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;
@@ -1654,18 +1669,18 @@ gfc_constant_array_constructor_p (gfc_constructor * c)
 tree
 gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
 {
-  tree tmptype, list, init, tmp;
+  tree tmptype, init, tmp;
   HOST_WIDE_INT nelem;
   gfc_constructor *c;
   gfc_array_spec as;
   gfc_se se;
   int i;
+  VEC(constructor_elt,gc) *v = NULL;
 
   /* First traverse the constructor list, converting the constants
      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);
@@ -1675,9 +1690,9 @@ gfc_build_constant_array_constructor (gfc_expr * expr, tree type)
       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;
+      CONSTRUCTOR_APPEND_ELT (v, build_int_cst (gfc_array_index_type, nelem),
+                              se.expr);
+      c = gfc_constructor_next (c);
       nelem++;
     }
 
@@ -1691,20 +1706,22 @@ 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));
+  init = build_constructor (tmptype, v);
 
   TREE_CONSTANT (init) = 1;
   TREE_STATIC (init) = 1;
@@ -1796,7 +1813,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;
@@ -1812,8 +1829,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)
@@ -1832,14 +1849,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);
@@ -1853,7 +1870,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)
@@ -2035,9 +2052,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);
 
@@ -2083,11 +2101,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);
@@ -2283,7 +2301,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;
 
@@ -2305,10 +2323,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
@@ -2320,34 +2334,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);
     }
 
@@ -2381,8 +2410,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:
@@ -2400,15 +2429,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:
@@ -2474,7 +2505,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);
 }
 
@@ -2506,6 +2538,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)
     {
@@ -2546,9 +2581,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),
@@ -2557,8 +2591,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)
@@ -2572,9 +2605,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),
@@ -2740,7 +2772,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)
 {
@@ -2776,12 +2808,13 @@ gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
       TREE_TYPE (stmt) = void_type_node;
       OMP_FOR_BODY (stmt) = loopbody = gfc_finish_block (pbody);
 
-      OMP_FOR_CLAUSES (stmt) = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+      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 (OMP_CLAUSE_NOWAIT);
+         = build_omp_clause (input_location, OMP_CLAUSE_NOWAIT);
 
       /* Initialize the loopvar.  */
       TREE_VEC_ELT (init, 0) = build2_v (MODIFY_EXPR, loop->loopvar[n],
@@ -2806,7 +2839,8 @@ gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
       loopbody = gfc_finish_block (pbody);
 
       /* Initialize the loopvar.  */
-      gfc_add_modify (&loop->code[n], loop->loopvar[n], loop->from[n]);
+      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);
 
@@ -2818,7 +2852,7 @@ gfc_trans_scalarized_loop_end (gfc_loopinfo * loop, int n,
                         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 ());
+      tmp = build3_v (COND_EXPR, cond, tmp, build_empty_stmt (input_location));
       gfc_add_expr_to_block (&block, tmp);
 
       /* The main body.  */
@@ -3149,7 +3183,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;
@@ -3182,8 +3216,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;
@@ -3229,77 +3262,95 @@ 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);
-                 asprintf (&msg, "%s, upper bound of dimension %d of array "
-                           "'%s' exceeded (%%ld > %%ld)", gfc_msg_fault,
+                 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, 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), 
+                    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, "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, 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, 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, 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, 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]);
@@ -3313,16 +3364,16 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
                 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
@@ -3337,7 +3388,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);
 
@@ -3416,13 +3467,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)
     {
@@ -3471,7 +3518,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])
@@ -3514,15 +3560,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;
 
@@ -3547,6 +3590,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.  */
@@ -3556,8 +3600,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;
@@ -3700,7 +3744,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;
@@ -3732,8 +3775,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)
            {
@@ -3776,7 +3817,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)
 {
@@ -3874,6 +3915,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));
@@ -3922,14 +4000,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;
     }
@@ -3938,16 +4017,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:
@@ -3957,18 +4059,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);
@@ -3985,9 +4083,9 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree pstat)
   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);
     }
@@ -4033,11 +4131,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)
@@ -4072,59 +4169,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:
@@ -4138,14 +4207,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;
            }
         }
@@ -4273,9 +4335,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);
 
@@ -4298,8 +4360,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);
 
@@ -4364,8 +4426,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);
@@ -4391,7 +4453,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);
@@ -4452,12 +4514,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));
@@ -4504,7 +4567,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;
 
@@ -4577,15 +4641,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);
            }
        }
@@ -4675,7 +4750,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);
 
@@ -4690,7 +4765,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);
        }
 
@@ -4701,15 +4777,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);
     }
@@ -4743,7 +4821,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
@@ -4844,11 +4923,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;
     }
 
@@ -4857,11 +4936,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)
@@ -4872,21 +4951,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;
        }
 
@@ -4909,19 +4988,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;
     }
 }
@@ -5004,7 +5083,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)
        {
@@ -5062,7 +5141,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;
@@ -5124,13 +5203,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;
 
@@ -5168,7 +5247,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);
@@ -5178,15 +5258,13 @@ 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.  */
       gfc_trans_scalarizing_loops (&loop, &block);
 
       desc = loop.temp_ss->data.info.descriptor;
-
-      gcc_assert (is_gimple_lvalue (desc));
     }
   else if (expr->expr_type == EXPR_FUNCTION)
     {
@@ -5224,9 +5302,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");
        }
 
@@ -5398,7 +5476,8 @@ array_parameter_size (tree desc, gfc_expr *expr, tree *size)
   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 (gfor_fndecl_size0, 1,
+    *size = build_call_expr_loc (input_location,
+                            gfor_fndecl_size0, 1,
                             gfc_build_addr_expr (NULL, desc));
   else
     {
@@ -5420,7 +5499,7 @@ array_parameter_size (tree desc, gfc_expr *expr, tree *size)
 /* TODO: Optimize passing g77 arrays.  */
 
 void
-gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
+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)
 {
@@ -5429,22 +5508,47 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
   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;
     }
 
@@ -5461,9 +5565,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.  */
@@ -5475,6 +5589,7 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
            array_parameter_size (tmp, expr, size);
          return;
         }
+
       if (sym->attr.allocatable)
         {
          if (sym->attr.dummy || sym->attr.result)
@@ -5489,6 +5604,44 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
         }
     }
 
+  /* 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.  */
@@ -5499,7 +5652,8 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
 
       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;
     }
@@ -5509,18 +5663,20 @@ gfc_conv_array_parameter (gfc_se * se, gfc_expr * expr, gfc_ss * ss, int g77,
       se->want_pointer = 1;
       gfc_conv_expr_descriptor (se, expr, ss);
       if (size)
-       array_parameter_size (build_fold_indirect_ref (se->expr),
+       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);
     }
 
@@ -5528,7 +5684,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)
@@ -5538,7 +5693,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)
        {
@@ -5562,7 +5718,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);
@@ -5581,7 +5738,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);
        }
 
@@ -5594,7 +5752,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);
@@ -5603,7 +5762,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);
@@ -5665,10 +5824,12 @@ get_full_array_size (stmtblock_t *block, tree decl, int rank)
 }
 
 
-/* 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;
@@ -5677,34 +5838,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);
@@ -5712,11 +5905,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,
@@ -5739,8 +5951,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.  */
@@ -5748,7 +5961,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)))
@@ -5787,10 +6001,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);
 
@@ -5807,7 +6030,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;
     }
@@ -5817,7 +6041,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);
 
@@ -5831,35 +6055,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);
            }
@@ -5876,7 +6151,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);
            }
 
@@ -5885,7 +6161,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);
            }
@@ -5923,7 +6199,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)
@@ -5932,6 +6208,16 @@ 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);
+}
+
+
 /* NULLIFY an allocatable/pointer array on function entry, free it on exit.
    Do likewise, recursively if necessary, with the allocatable components of
    derived types.  */
@@ -5948,7 +6234,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))
@@ -5962,9 +6248,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);
     }
 
@@ -5992,17 +6278,22 @@ 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
+             || !gfc_has_default_initializer (sym->ts.u.derived))
+           {
+             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);
+             tmp = gfc_init_default_dt (sym, NULL, false);
              gfc_add_expr_to_block (&fnblock, tmp);
            }
        }
@@ -6011,7 +6302,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);
     }
   
@@ -6030,11 +6322,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);
@@ -6064,7 +6357,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)
@@ -6093,6 +6385,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:
@@ -6137,8 +6436,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++)
            {
@@ -6355,7 +6652,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
       sym = expr->symtree->n.sym;
 
   /* A function that returns arrays.  */
-  is_proc_ptr_comp (expr, &comp);
+  gfc_is_proc_ptr_comp (expr, &comp);
   if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
       || (comp && comp->attr.dimension))
     {