https://gcc.gnu.org/g:22ce751b60bba098a6e0c2a75cd4d1e882eaa51a

commit 22ce751b60bba098a6e0c2a75cd4d1e882eaa51a
Author: Mikael Morin <mik...@gcc.gnu.org>
Date:   Mon Apr 14 13:52:49 2025 +0200

    Retour en arrière délinearisation tableaux compil' OK.

Diff:
---
 gcc/fortran/trans-array.cc      | 353 +++++++++++++---------------------------
 gcc/fortran/trans-decl.cc       |  35 +---
 gcc/fortran/trans-descriptor.cc |  33 ----
 gcc/fortran/trans-types.cc      |  60 +++----
 libgfortran/caf/single.c        |   4 +-
 5 files changed, 136 insertions(+), 349 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index fa84f007bee5..41d0a612edf5 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -2169,43 +2169,6 @@ gfc_build_constant_array_constructor (gfc_expr * expr, 
tree type)
       gfc_free_expr (as.upper[i]);
     }
 
-  if (expr->shape && expr->rank > 1)
-    {
-      vec<constructor_elt, va_gc> *vsrc = v;
-
-      for (int r = 0; r < expr->rank - 1; r++)
-       {
-         vec<constructor_elt, va_gc> *vdest = nullptr;
-         unsigned sidx = 0;
-
-         tree type = tmptype;
-         for (int j = expr->rank - 1; j > r; j--)
-           {
-             gcc_assert (TREE_CODE (type) == ARRAY_TYPE); 
-             type = TREE_TYPE (type);
-           }
-
-         int len = (int) mpz_get_si (expr->shape[r]);
-
-         while (sidx != vec_safe_length (vsrc))
-           {
-             vec<constructor_elt, va_gc> *vtmp = nullptr;
-
-             for (int i = 0; i < len; i++)
-               {
-                 append_constructor (vtmp, (*vsrc)[sidx].value);
-                 sidx++;
-               }
-
-             append_constructor (vdest, build_constructor (type, vtmp));
-           }
-
-         vsrc = vdest;
-       }
-
-      v = vsrc;
-    }
-
   init = build_constructor (tmptype, v);
 
   TREE_CONSTANT (init) = 1;
@@ -3007,6 +2970,11 @@ gfc_conv_ss_descriptor (stmtblock_t * block, gfc_ss * 
ss, int base)
       if (!ss->is_alloc_lhs)
        tmp = gfc_evaluate_now (tmp, block);
       info->offset = tmp;
+
+      /* Make absolutely sure that the saved_offset is indeed saved
+        so that the variable is still accessible after the loops
+        are translated.  */
+      info->saved_data = info->data;
     }
 }
 
@@ -3359,82 +3327,6 @@ array_bound_check_elemental (gfc_se * se, gfc_ss * ss, 
gfc_expr * expr)
 }
 
 
-/* Build a scalarized array reference using the vptr 'size'.  */
-
-static bool
-build_class_array_ref (gfc_se *se, tree base, tree index)
-{
-  tree size;
-  tree decl = NULL_TREE;
-  tree tmp;
-  gfc_expr *expr = se->ss->info->expr;
-  gfc_expr *class_expr;
-  gfc_typespec *ts;
-  gfc_symbol *sym;
-
-  tmp = !VAR_P (base) ? gfc_get_class_from_expr (base) : NULL_TREE;
-
-  if (tmp != NULL_TREE)
-    decl = tmp;
-  else
-    {
-      /* The base expression does not contain a class component, either
-        because it is a temporary array or array descriptor.  Class
-        array functions are correctly resolved above.  */
-      if (!expr
-         || (expr->ts.type != BT_CLASS
-             && !gfc_is_class_array_ref (expr, NULL)))
-       return false;
-
-      /* Obtain the expression for the class entity or component that is
-        followed by an array reference, which is not an element, so that
-        the span of the array can be obtained.  */
-      class_expr = gfc_find_and_cut_at_last_class_ref (expr, false, &ts);
-
-      if (!ts)
-       return false;
-
-      sym = (!class_expr && expr) ? expr->symtree->n.sym : NULL;
-      if (sym && sym->attr.function
-         && sym == sym->result
-         && sym->backend_decl == current_function_decl)
-       /* The temporary is the data field of the class data component
-          of the current function.  */
-       decl = gfc_get_fake_result_decl (sym, 0);
-      else if (sym)
-       {
-         if (decl == NULL_TREE)
-           decl = expr->symtree->n.sym->backend_decl;
-         /* For class arrays the tree containing the class is stored in
-            GFC_DECL_SAVED_DESCRIPTOR of the sym's backend_decl.
-            For all others it's sym's backend_decl directly.  */
-         if (DECL_LANG_SPECIFIC (decl) && GFC_DECL_SAVED_DESCRIPTOR (decl))
-           decl = GFC_DECL_SAVED_DESCRIPTOR (decl);
-       }
-      else
-       decl = gfc_get_class_from_gfc_expr (class_expr);
-
-      if (POINTER_TYPE_P (TREE_TYPE (decl)))
-       decl = build_fold_indirect_ref_loc (input_location, decl);
-
-      if (!GFC_CLASS_TYPE_P (TREE_TYPE (decl)))
-       return false;
-    }
-
-  se->class_vptr = gfc_evaluate_now (gfc_class_vptr_get (decl), &se->pre);
-
-  size = gfc_class_vtab_size_get (decl);
-  /* For unlimited polymorphic entities then _len component needs to be
-     multiplied with the size.  */
-  size = gfc_resize_class_size_with_len (&se->pre, decl, size);
-  size = fold_convert (gfc_array_index_type, size);
-
-  /* Return the element in the se expression.  */
-  se->expr = gfc_build_spanned_array_ref (base, index, size);
-  return true;
-}
-
-
 /* Indicates that the tree EXPR is a reference to an array that can’t
    have any negative stride.  */
 
@@ -3480,49 +3372,16 @@ non_negative_strides_array_p (tree expr)
 }
 
 
-static tree
-build_array_ref (tree array, tree index,
-                bool non_negative_stride, tree lbound, tree spacing,
-                const vec<tree> * array_type_domains)
-{
-  tree elt_type = NULL_TREE;
-  if (!array_type_domains || array_type_domains->is_empty ())
-    elt_type = TREE_TYPE (TREE_TYPE (array));
-  else
-    {
-      tree core_type = TREE_TYPE (array);
-
-      unsigned j;
-      tree *dom_p;
-      FOR_EACH_VEC_ELT (*array_type_domains, j, dom_p)
-       {
-         gcc_assert (TREE_CODE (core_type) == ARRAY_TYPE
-                     && TYPE_DOMAIN (core_type) == *dom_p);
-         core_type = TREE_TYPE (core_type);
-       }
-
-      elt_type = TREE_TYPE (core_type);
-
-      FOR_EACH_VEC_ELT_REVERSE (*array_type_domains, j, dom_p)
-       elt_type = gfc_build_incomplete_array_type (elt_type, *dom_p);
-    }
-
-  return gfc_build_array_ref (elt_type, array, index, non_negative_stride,
-                             lbound, spacing);
-}
-
-
 /* Return the offset for an index.  Performs bound checking for elemental
    dimensions.  Single element references are processed separately.
    DIM is the array dimension, I is the loop dimension.  */
 
 static tree
-conv_array_index (gfc_se * se, gfc_ss * ss, int dim, int i,
-                 gfc_array_ref * ar)
+conv_array_index (gfc_se * se, gfc_ss * ss, int dim, int i, gfc_array_ref * ar)
 {
   gfc_array_info *info;
   tree index;
-  tree descriptor;
+  tree desc;
   tree data;
 
   info = &ss->info->data.array;
@@ -3553,16 +3412,19 @@ conv_array_index (gfc_se * se, gfc_ss * ss, int dim, 
int i,
          gcc_assert (info->subscript[dim]
                      && info->subscript[dim]->info->type == GFC_SS_VECTOR);
 
-         descriptor = info->subscript[dim]->info->data.array.descriptor; 
+         desc = info->subscript[dim]->info->data.array.descriptor; 
+
+         /* Get a zero-based index into the vector.  */
          index = fold_convert_loc (input_location, gfc_array_index_type,
                                    se->loop->loopvar[i]);
 
          /* Read the vector to get an index into info->descriptor.  */
          data = build_fold_indirect_ref_loc (input_location, 
-                                             gfc_conv_array_data (descriptor));
-         index = gfc_build_array_ref (data, index, false,
-                                      gfc_conv_array_lbound (descriptor, 0),
-                                      gfc_conv_array_spacing (descriptor, 0));
+                                             gfc_conv_array_data (desc));
+         index = gfc_build_array_ref (data, index,
+                                      non_negative_strides_array_p (desc),
+                                      gfc_conv_array_lbound (desc, 0),
+                                      gfc_conv_array_spacing (desc, 0));
          index = gfc_evaluate_now (index, &se->pre);
          index = fold_convert (gfc_array_index_type, index);
 
@@ -3578,6 +3440,10 @@ conv_array_index (gfc_se * se, gfc_ss * ss, int dim, int 
i,
 
          /* Multiply the loop variable by the stride and delta.  */
          index = se->loop->loopvar[i];
+         if (!integer_onep (info->stride[dim]))
+           index = fold_build2_loc (input_location, MULT_EXPR,
+                                    gfc_array_index_type, index,
+                                    info->stride[dim]);
          if (!integer_zerop (info->delta[dim]))
            index = fold_build2_loc (input_location, PLUS_EXPR,
                                     gfc_array_index_type, index,
@@ -3598,24 +3464,55 @@ conv_array_index (gfc_se * se, gfc_ss * ss, int dim, 
int i,
        index = fold_build2_loc (input_location, PLUS_EXPR,
                                 gfc_array_index_type, index, info->delta[dim]);
     }
-
+  
   return index;
 }
 
 
+static tree
+build_ptr_array_ref (tree data, tree offset)
+{
+  tree ptr = data;
+  gcc_assert (TREE_CODE (TREE_TYPE (ptr)) == POINTER_TYPE);
+  if (TREE_CODE (TREE_TYPE (TREE_TYPE (ptr))) == ARRAY_TYPE)
+    {
+      tree elt_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (ptr)));
+      ptr = fold_convert_loc (input_location,
+                             build_pointer_type (elt_type), ptr);
+    }
+
+  tree tmp = fold_build_pointer_plus_loc (input_location, ptr, offset);
+  return build_fold_indirect_ref_loc (input_location, tmp);
+}
+
+
+tree
+build_array_ref_dim (gfc_ss *ss, tree index, tree spacing, bool tmp_array = 
false)
+{
+  gfc_array_info *info = &ss->info->data.array;
+
+  tree base = build_fold_indirect_ref_loc (input_location, info->data);
+
+  gfc_ss_type ss_type = ss->info->type;
+  bool non_negative_stride = ss_type == GFC_SS_FUNCTION
+                            || ss_type == GFC_SS_CONSTRUCTOR
+                            || ss_type == GFC_SS_INTRINSIC
+                            || tmp_array
+                            || non_negative_strides_array_p (info->descriptor);
+  return gfc_build_array_ref (base, index, non_negative_stride,
+                             NULL_TREE, spacing);
+}
+
+
 /* Build a scalarized reference to an array.  */
 
 static void
-gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar,
-                              bool tmp_array = false)
+gfc_conv_scalarized_array_ref (gfc_se * se, gfc_array_ref * ar, bool tmp_array 
= false)
 {
-  gfc_array_info *info;
-  tree base;
   gfc_ss *ss;
   int n;
 
   ss = se->ss;
-  info = &ss->info->data.array;
   if (ar)
     n = se->loop->order[0];
   else
@@ -3623,17 +3520,9 @@ gfc_conv_scalarized_array_ref (gfc_se * se, 
gfc_array_ref * ar,
 
   tree index = conv_array_index (se, ss, ss->dim[n], n, ar);
 
-  base = build_fold_indirect_ref_loc (input_location, info->data);
-
-  /* Use the vptr 'size' field to access the element of a class array.  */
-  if (build_class_array_ref (se, base, index))
-    return;
-
-  bool non_negative_stride = tmp_array
-                            || non_negative_strides_array_p (info->descriptor);
-  se->expr = gfc_build_array_ref (base, index, non_negative_stride,
-                                 info->lbound[ss->dim[0]],
-                                 info->spacing[ss->dim[0]]);
+  se->expr = build_array_ref_dim (ss, index,
+                                 ss->info->data.array.spacing0,
+                                 tmp_array);
 }
 
 
@@ -3648,6 +3537,24 @@ gfc_conv_tmp_array_ref (gfc_se * se)
 }
 
 
+/* Add T to the offset pair *OFFSET, *CST_OFFSET.  */
+
+static void
+add_to_offset (tree *cst_offset, tree *offset, tree t)
+{
+  if (TREE_CODE (t) == INTEGER_CST)
+    *cst_offset = int_const_binop (PLUS_EXPR, *cst_offset, t);
+  else
+    {
+      if (!integer_zerop (*offset))
+       *offset = fold_build2_loc (input_location, PLUS_EXPR,
+                                  gfc_array_index_type, *offset, t);
+      else
+       *offset = t;
+    }
+}
+
+
 /* Build an array reference.  se->expr already holds the array descriptor.
    This should be either a variable, indirect variable reference or component
    reference.  For arrays which do not have a descriptor, se->expr will be
@@ -3659,6 +3566,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
                    locus * where)
 {
   int n;
+  tree offset, cst_offset;
   tree tmp;
   tree decl = NULL_TREE;
   gfc_se indexse;
@@ -3715,8 +3623,8 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
       && ar->as->type != AS_DEFERRED)
     decl = sym->backend_decl;
 
-  tree ptr = gfc_conv_array_data (decl);
-  tree array = build_fold_indirect_ref_loc (input_location, ptr);
+  cst_offset = offset = gfc_index_zero_node;
+  add_to_offset (&cst_offset, &offset, gfc_conv_array_offset (decl));
 
   /* Calculate the offsets from all the dimensions.  Make sure to associate
      the final offset so that we form a chain of loop invariant summands.  */
@@ -3727,8 +3635,6 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
       gfc_conv_expr_type (&indexse, ar->start[n], gfc_array_index_type);
       gfc_add_block_to_block (&se->pre, &indexse.pre);
 
-      tree lbound = gfc_conv_array_lbound (decl, n);
-
       if ((gfc_option.rtcheck & GFC_RTCHECK_BOUNDS) && ! expr->no_bounds_check)
        {
          /* Check array bounds.  */
@@ -3739,7 +3645,7 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
          indexse.expr = save_expr (indexse.expr);
 
          /* Lower bound.  */
-         tmp = lbound;
+         tmp = gfc_conv_array_lbound (decl, n);
          if (sym->attr.temporary)
            {
              gfc_init_se (&tmpse, se);
@@ -3785,26 +3691,31 @@ gfc_conv_array_ref (gfc_se * se, gfc_array_ref * ar, 
gfc_expr *expr,
            }
        }
 
+      /* Multiply the index by the stride.  */
       tree spacing = gfc_conv_array_spacing (decl, n);
-
-      tmp = gfc_build_array_ref (array, indexse.expr,
-                                non_negative_strides_array_p (decl),
-                                lbound, spacing);
-      array = tmp;
+      tmp = fold_build2_loc (input_location, MULT_EXPR, gfc_array_index_type,
+                            indexse.expr, spacing);
+ 
+      /* And add it to the total.  */
+      add_to_offset (&cst_offset, &offset, tmp);
     }
 
   free (var_name);
-  se->expr = array;
+
+  if (!integer_zerop (cst_offset))
+    offset = fold_build2_loc (input_location, PLUS_EXPR,
+                             gfc_array_index_type, offset, cst_offset);
+
+  se->expr = build_ptr_array_ref (gfc_conv_array_data (decl), offset);
 }
 
 
 /* Add the offset corresponding to array's ARRAY_DIM dimension and loop's
    LOOP_DIM dimension (if any) to array's offset.  */
 
-static tree
-add_array_index (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
-                tree array, gfc_array_ref *ar, int array_dim, int loop_dim,
-                const vec<tree> * array_type_domains)
+static void
+add_array_offset (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
+                 gfc_array_ref *ar, int array_dim, int loop_dim)
 {
   gfc_se se;
   gfc_array_info *info;
@@ -3814,20 +3725,13 @@ add_array_index (stmtblock_t *pblock, gfc_loopinfo 
*loop, gfc_ss *ss,
   gfc_init_se (&se, NULL);
   se.loop = loop;
   se.expr = info->descriptor;
-  tree tmp = conv_array_index (&se, ss, array_dim, loop_dim, ar);
+  tree index = conv_array_index (&se, ss, array_dim, loop_dim, ar);
 
   gfc_add_block_to_block (pblock, &se.pre);
 
-  tree index = fold_convert_loc (input_location, gfc_array_index_type, tmp);
-
-  gfc_ss_type ss_type = ss->info->type;
-  bool non_negative_stride = ss_type == GFC_SS_FUNCTION
-                            || ss_type == GFC_SS_CONSTRUCTOR
-                            || ss_type == GFC_SS_INTRINSIC
-                            || non_negative_strides_array_p (info->descriptor);
-  return build_array_ref (array, index, non_negative_stride,
-                         info->lbound[array_dim], info->spacing[array_dim],
-                         array_type_domains);
+  tree tmp = build_array_ref_dim (ss, index, info->spacing[array_dim]);
+  tmp = gfc_build_addr_expr (NULL_TREE, tmp);
+  info->data = gfc_evaluate_now (tmp, pblock);
 }
 
 
@@ -3894,27 +3798,20 @@ gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, 
int flag,
          gcc_assert (0 == ploop->order[0]);
 
          info->spacing0 = gfc_conv_array_spacing (info->descriptor, 0);
+         /* Calculate the spacing of the innermost loop.  Hopefully this will
+            allow the backend optimizers to do their stuff more effectively.
+          */
          info->spacing0 = gfc_evaluate_now (info->spacing0, pblock);
 
          if (info->ref)
            {
-             auto_vec<tree> domains;
-
-             tree array = build_fold_indirect_ref_loc (input_location, 
info->data);
-             tree array_type = TREE_TYPE (array);
-
              for (int i = ar->dimen - 1; i >= 0; i--)
                {
-                 if (ar->dimen_type[i] == DIMEN_ELEMENT)
-                   array = add_array_index (pblock, ploop, ss, array, ar,
-                                            i, -1 /* unused */, &domains);
-                 else
-                   domains.safe_push (TYPE_DOMAIN (array_type));
+                 if (ar->dimen_type[i] != DIMEN_ELEMENT)
+                   continue;
 
-                 array_type = TREE_TYPE (array_type);
+                 add_array_offset (pblock, ploop, ss, ar, i, -1 /* unused */);
                }
-
-             info->data = gfc_build_addr_expr (NULL_TREE, array);
            }
        }
       else
@@ -3930,13 +3827,8 @@ gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, 
int flag,
          gcc_assert (i == ploop->order[i]);
          i = ploop->order[i];
 
-         tree array = build_fold_indirect_ref_loc (input_location,
-                                                   info->data);
          /* Add the offset for the previous loop dimension.  */
-         array = add_array_index (pblock, ploop, ss, array, ar, pss->dim[i], i,
-                                  nullptr);
-
-         info->data = gfc_build_addr_expr (NULL_TREE, array);
+         add_array_offset (pblock, ploop, ss, ar, pss->dim[i], i);
        }
 
       /* Remember this offset for the second loop.  */
@@ -4336,20 +4228,6 @@ gfc_conv_section_startstride (stmtblock_t * block, 
gfc_ss * ss, int dim)
 }
 
 
-static void
-conv_evaluate_lbound (stmtblock_t * block, gfc_ss * ss, int dim)
-{
-  gcc_assert (ss->info->type == GFC_SS_SECTION);
-
-  gfc_array_info *info = &ss->info->data.array;
-  gfc_array_ref *ar = &info->ref->u.ar;
-  tree desc = info->descriptor;
-
-  evaluate_bound (block, info->lbound, nullptr, desc, dim, true,
-                 ar->as->type == AS_DEFERRED, !ss->is_alloc_lhs);
-}
-
-
 /* Generate in INNER the bounds checking code along the dimension DIM for
    the array associated with SS_INFO.  */
 
@@ -4601,16 +4479,12 @@ done:
            {
              gfc_conv_section_startstride (&outer_loop->pre, ss, ss->dim[n]);
              conv_array_spacing (&outer_loop->pre, ss, ss->dim[n]);
-             conv_evaluate_lbound (&outer_loop->pre, ss, ss->dim[n]);
            }
          if (loop->parent == nullptr)
            for (n = 0; n < GFC_MAX_DIMENSIONS; n++)
              if (info->subscript[n]
                  && info->subscript[n]->info->type == GFC_SS_SCALAR)
-               {
-                 conv_array_spacing (&outer_loop->pre, ss, n);
-                 conv_evaluate_lbound (&outer_loop->pre, ss, n);
-               }
+               conv_array_spacing (&outer_loop->pre, ss, n);
          break;
 
        case GFC_SS_INTRINSIC:
@@ -6205,7 +6079,7 @@ gfc_trans_array_cobounds (tree type, stmtblock_t * pblock,
 
 
 /* Generate code to evaluate non-constant array bounds.  Sets *poffset and
-   returns the size (in align units) of the array.  */
+   returns the size (in bytes) of the array.  */
 
 tree
 gfc_trans_array_bounds (tree type, gfc_symbol * sym, tree * poffset,
@@ -6886,13 +6760,8 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, 
tree desc,
   tree tmp = gfc_conv_array_data (desc);
   tree array = build_fold_indirect_ref_loc (input_location, tmp);
 
-  for (int i = GFC_TYPE_ARRAY_RANK (TREE_TYPE (desc)) - 1; i >= 0; i--)
-    {
-      array = build_array_ref (array, gfc_index_zero_node,
-                              non_negative_strides, gfc_index_zero_node,
-                              gfc_conv_array_spacing (desc, i), nullptr);
-    }
-  tmp = array;
+  tmp = gfc_build_array_ref (array, gfc_index_zero_node, non_negative_strides,
+                            gfc_index_zero_node, NULL_TREE);
 
   /* Offset the data pointer for pointer assignments from arrays with
      subreferences; e.g. my_integer => my_type(:)%integer_component.  */
diff --git a/gcc/fortran/trans-decl.cc b/gcc/fortran/trans-decl.cc
index 39886b66ec09..b154cb3161c2 100644
--- a/gcc/fortran/trans-decl.cc
+++ b/gcc/fortran/trans-decl.cc
@@ -1033,39 +1033,7 @@ update_type_bounds (tree type, tree 
lbound[GFC_MAX_DIMENSIONS],
                    tree ubound[GFC_MAX_DIMENSIONS],
                    tree spacing[GFC_MAX_DIMENSIONS], tree root_type, int dim)
 {
-  tree elt_type;
-  if (dim == 0)
-    elt_type = TREE_TYPE (type);
-  else
-    elt_type = update_type_bounds (TREE_TYPE (type), lbound, ubound, spacing,
-                                  root_type, dim - 1);
-
   tree current_lbound = lbound[dim];
-  tree current_ubound = ubound[dim];
-  if (current_lbound != NULL_TREE
-      || current_ubound != NULL_TREE
-      || elt_type != TREE_TYPE (type))
-    {
-      tree new_type = build_distinct_type_copy (type);
-      TREE_TYPE (new_type) = elt_type;
-      TYPE_DOMAIN (new_type) = build_distinct_type_copy (TYPE_DOMAIN (type));
-
-      tree new_lbound = current_lbound;
-      if (new_lbound == NULL_TREE)
-       new_lbound = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
-      TYPE_MIN_VALUE (TYPE_DOMAIN (new_type)) = new_lbound;
-
-      tree new_ubound = current_ubound;
-      if (new_ubound == NULL_TREE)
-       new_ubound = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
-      TYPE_MAX_VALUE (TYPE_DOMAIN (new_type)) = new_ubound;
-
-      layout_type (TYPE_DOMAIN (new_type));
-      layout_type (new_type);
-
-      type = new_type;
-    }
-
   if (current_lbound != NULL_TREE)
     {
       GFC_TYPE_ARRAY_LBOUND (root_type, dim) = current_lbound;
@@ -1080,6 +1048,8 @@ update_type_bounds (tree type, tree 
lbound[GFC_MAX_DIMENSIONS],
            DECL_NAMELESS (current_lbound) = 1;
        }
     }
+
+  tree current_ubound = ubound[dim];
   if (current_ubound != NULL_TREE)
     {
       GFC_TYPE_ARRAY_UBOUND (root_type, dim) = current_ubound;
@@ -1094,6 +1064,7 @@ update_type_bounds (tree type, tree 
lbound[GFC_MAX_DIMENSIONS],
            DECL_NAMELESS (current_ubound) = 1;
        }
     }
+
   tree current_spacing = spacing[dim];
   if (current_spacing != NULL_TREE)
     {
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index 190311675198..3ae5a2a2dea3 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -956,39 +956,6 @@ gfc_conv_descriptor_stride_get (tree desc, tree dim)
 }
 
 
-tree
-gfc_build_desc_array_type (tree desc_type, tree etype, int dimen, tree * 
lbound,
-                          tree * ubound)
-{
-  tree type = etype;
-
-  for (int i = 0; i < dimen; i++)
-    {
-      tree lower = lbound[i];
-      if (!lower)
-       {
-         tree root = build0 (PLACEHOLDER_EXPR, desc_type);
-         tree dim = build_int_cst (integer_type_node, i);
-         lower = gfc_descriptor::get_lbound (root, dim);
-       }
-
-      tree upper = ubound[i];
-      if (!upper)
-       {
-         tree root = build0 (PLACEHOLDER_EXPR, desc_type);
-         tree dim = build_int_cst (integer_type_node, i);
-         upper = gfc_descriptor::get_ubound (root, dim);
-       }
-
-      tree index_type = build_range_type (gfc_array_index_type, lower, upper);
-
-      type = gfc_build_incomplete_array_type (type, index_type);
-    }
-
-  return type;
-}
-
-
 static bt
 get_type_info (const bt &type)
 {
diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 2eed2f010819..c8d56ec55999 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -1445,14 +1445,8 @@ gfc_get_element_type (tree type)
        }
       else
        {
-         int rank = GFC_TYPE_ARRAY_RANK (type);
-         for (int i = 0; i < rank; i++)
-           {
-             gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
-             type = TREE_TYPE (type);
-           }
-
-         element = type;
+         gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
+         element = TREE_TYPE (type);
        }
     }
   else
@@ -1465,14 +1459,7 @@ gfc_get_element_type (tree type)
 
       /* For arrays, which are not scalar coarrays.  */
       if (TREE_CODE (element) == ARRAY_TYPE && !TYPE_STRING_FLAG (element))
-       {
-         int rank = GFC_TYPE_ARRAY_RANK (type);
-         for (int i = 0; i < rank; i++)
-           {
-             gcc_assert (TREE_CODE (element) == ARRAY_TYPE);
-             element = TREE_TYPE (element);
-           }
-       }
+       element = TREE_TYPE (element);
     }
 
   return element;
@@ -1854,27 +1841,6 @@ gfc_get_dtype (tree type, int * rank)
 }
 
 
-static tree
-build_nested_array_types (tree etype, tree lbound[GFC_MAX_DIMENSIONS],
-                         tree ubound[GFC_MAX_DIMENSIONS], int rank)
-{
-  tree type = etype;
-
-  for (int i = 0; i < rank; i++)
-    {
-      tree idx_type;
-      if (lbound[i])
-       idx_type = build_range_type (gfc_array_index_type, lbound[i], 
ubound[i]);
-      else
-       idx_type = gfc_array_index_type;
-      type = build_array_type (type, idx_type);
-      layout_type (type);
-    }
-
-  return build_variant_type_copy (type);
-}
-
-
 /* Build an array type for use without a descriptor, packed according
    to the value of PACKED.  */
 
@@ -1975,7 +1941,13 @@ gfc_get_nodesc_array_type (tree etype, gfc_array_spec * 
as, gfc_packed packed,
        }
     }
 
-  type = build_nested_array_types (etype, lbound, ubound, as->rank);
+  /* We don't use build_array_type because this does not include
+     lang-specific information (i.e. the bounds of the array) when checking
+     for duplicates.  */
+  if (as->rank != 0)
+    type = make_node (ARRAY_TYPE);
+  else
+    type = build_variant_type_copy (etype);
 
   GFC_ARRAY_TYPE_P (type) = 1;
   TYPE_LANG_SPECIFIC (type) = ggc_cleared_alloc<struct lang_type> ();
@@ -2156,7 +2128,7 @@ gfc_get_array_type_bounds (tree etype, int dimen, int 
codimen, tree * lbound,
                           enum gfc_array_kind akind, bool restricted)
 {
   char name[8 + 2*GFC_RANK_DIGITS + 1 + GFC_MAX_SYMBOL_LEN];
-  tree fat_type, base_type, arraytype, lower, upper, stride, tmp;
+  tree fat_type, base_type, arraytype, lower, upper, stride, tmp, rtype;
   const char *type_name;
   int n;
 
@@ -2286,7 +2258,15 @@ gfc_get_array_type_bounds (tree etype, int dimen, int 
codimen, tree * lbound,
       return fat_type;
     }
 
-  arraytype = gfc_build_desc_array_type (fat_type, etype, dimen, lbound, 
ubound);
+  /* We define data as an array with the correct size if possible.
+     Much better than doing pointer arithmetic.  */
+  if (stride)
+    rtype = build_range_type (gfc_array_index_type, gfc_index_zero_node,
+                             int_const_binop (MINUS_EXPR, stride,
+                                              build_int_cst (TREE_TYPE 
(stride), 1)));
+  else
+    rtype = gfc_array_range_type;
+  arraytype = build_array_type (etype, rtype);
   arraytype = build_pointer_type (arraytype);
   if (restricted)
     arraytype = build_qualified_type (arraytype, TYPE_QUAL_RESTRICT);
diff --git a/libgfortran/caf/single.c b/libgfortran/caf/single.c
index 2f05a4decadc..455ffad5743c 100644
--- a/libgfortran/caf/single.c
+++ b/libgfortran/caf/single.c
@@ -380,7 +380,7 @@ _gfortran_caf_failed_images (gfc_descriptor_t *array,
       indicate an empty array.  */
   array->dim[0].lower_bound = 0;
   array->dim[0]._ubound = -1;
-  array->dim[0].spacing = 1;
+  array->dim[0].spacing = local_kind;
   array->offset = 0;
 }
 
@@ -402,7 +402,7 @@ _gfortran_caf_stopped_images (gfc_descriptor_t *array,
      indicate an empty array.  */
   array->dim[0].lower_bound = 0;
   array->dim[0]._ubound = -1;
-  array->dim[0].spacing = 1;
+  array->dim[0].spacing = local_kind;
   array->offset = 0;
 }

Reply via email to