[gcc(refs/users/mikael/heads/refactor_descriptor_v05)] Correction ICEs PR95331

Mikael Morin mikael@gcc.gnu.org
Fri Jun 13 14:54:26 GMT 2025


https://gcc.gnu.org/g:d2ed7a3f46445687c309219e54cde0908bfd9b9b

commit d2ed7a3f46445687c309219e54cde0908bfd9b9b
Author: Mikael Morin <mikael@gcc.gnu.org>
Date:   Fri Apr 11 10:32:11 2025 +0200

    Correction ICEs PR95331

Diff:
---
 gcc/fortran/trans-array.cc      | 125 +++++++++++++++++++++++-----------------
 gcc/fortran/trans-array.h       |   2 +-
 gcc/fortran/trans-descriptor.cc |   6 +-
 gcc/fortran/trans-expr.cc       |   2 +-
 gcc/fortran/trans-types.cc      |  10 +++-
 gcc/fortran/trans.cc            |  26 ++++-----
 6 files changed, 97 insertions(+), 74 deletions(-)

diff --git a/gcc/fortran/trans-array.cc b/gcc/fortran/trans-array.cc
index 6fb4e8236909..022940f3f482 100644
--- a/gcc/fortran/trans-array.cc
+++ b/gcc/fortran/trans-array.cc
@@ -3092,7 +3092,8 @@ gfc_conv_array_spacing (tree descriptor, int dim)
 
   /* For descriptorless arrays use the array size.  */
   tmp = GFC_TYPE_ARRAY_SPACING (type, dim);
-  if (tmp != NULL_TREE)
+  if (tmp != NULL_TREE
+      && !contains_placeholder_p (tmp))
     return tmp;
 
   tmp = gfc_conv_descriptor_spacing_get (descriptor, gfc_rank_cst[dim]);
@@ -3111,7 +3112,8 @@ gfc_conv_array_lbound (tree descriptor, int dim)
   type = TREE_TYPE (descriptor);
 
   tmp = GFC_TYPE_ARRAY_LBOUND (type, dim);
-  if (tmp != NULL_TREE)
+  if (tmp != NULL_TREE
+      && !contains_placeholder_p (tmp))
     return tmp;
 
   tmp = gfc_conv_descriptor_lbound_get (descriptor, gfc_rank_cst[dim]);
@@ -3130,7 +3132,8 @@ gfc_conv_array_ubound (tree descriptor, int dim)
   type = TREE_TYPE (descriptor);
 
   tmp = GFC_TYPE_ARRAY_UBOUND (type, dim);
-  if (tmp != NULL_TREE)
+  if (tmp != NULL_TREE
+      && !contains_placeholder_p (tmp))
     return tmp;
 
   /* This should only ever happen when passing an assumed shape array
@@ -3477,15 +3480,37 @@ non_negative_strides_array_p (tree expr)
 
 
 static tree
-build_array_ref (tree desc, tree offset)
+build_array_ref (tree descriptor, tree array, tree index,
+		 bool non_negative_stride, tree lbound, tree spacing,
+		 const vec<tree> * array_type_domains)
 {
-  tree tmp;
+  tree elt_type = NULL_TREE;
+  if (!array_type_domains || array_type_domains->is_empty ())
+    elt_type = TREE_TYPE (TREE_TYPE (array));
+  else
+    {
+      tree desc_type = TREE_TYPE (descriptor);
+      tree core_type = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (desc_type));
 
-  tmp = gfc_conv_array_data (desc);
-  tmp = build_fold_indirect_ref_loc (input_location, tmp);
+      unsigned j;
+      tree *dom_p;
+      FOR_EACH_VEC_ELT (*array_type_domains, j, dom_p)
+	{
+	  gcc_assert (GFC_ARRAY_TYPE_P (core_type)
+		      && TYPE_DOMAIN (core_type) == *dom_p);
+	  core_type = TREE_TYPE (core_type);
+	}
 
-  tmp = gfc_build_array_ref (tmp, offset, non_negative_strides_array_p (desc));
-  return tmp;
+      core_type = TREE_TYPE (core_type);
+
+      tree elt_type = core_type;
+
+      FOR_EACH_VEC_ELT_REVERSE (*array_type_domains, j, dom_p)
+	elt_type = build_array_type (elt_type, *dom_p);
+    }
+
+  return gfc_build_array_ref (elt_type, array, index, non_negative_stride,
+			      lbound, spacing);
 }
 
 
@@ -3797,39 +3822,14 @@ add_array_index (stmtblock_t *pblock, gfc_loopinfo *loop, gfc_ss *ss,
 
   tree index = fold_convert_loc (input_location, gfc_array_index_type, tmp);
 
-  tree elt_type = NULL_TREE;
-  if (!array_type_domains || array_type_domains->is_empty ())
-    elt_type = TREE_TYPE (array);
-  else
-    {
-      tree desc_type = TREE_TYPE (info->descriptor);
-      tree core_type = TREE_TYPE (GFC_TYPE_ARRAY_DATAPTR_TYPE (desc_type));
-
-      unsigned j;
-      tree *dom_p;
-      FOR_EACH_VEC_ELT (*array_type_domains, j, dom_p)
-	{
-	  gcc_assert (GFC_ARRAY_TYPE_P (core_type)
-		      && TYPE_DOMAIN (core_type) == *dom_p);
-	  core_type = TREE_TYPE (core_type);
-	}
-
-      core_type = TREE_TYPE (core_type);
-
-      tree elt_type = core_type;
-
-      FOR_EACH_VEC_ELT_REVERSE (*array_type_domains, j, dom_p)
-	elt_type = build_array_type (elt_type, *dom_p);
-    }
-
   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 gfc_build_array_ref (elt_type, array, index,
-			      non_negative_stride, info->lbound[array_dim],
-			      info->spacing[array_dim]);
+  return build_array_ref (info->descriptor, array, index, non_negative_stride,
+			  info->lbound[array_dim], info->spacing[array_dim],
+			  array_type_domains);
 }
 
 
@@ -3896,7 +3896,7 @@ 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);
-	  info->spacing0 = gfc_evaluate_now (info->spacing0, &loop->pre);
+	  info->spacing0 = gfc_evaluate_now (info->spacing0, pblock);
 
 	  if (info->ref)
 	    {
@@ -3909,7 +3909,7 @@ gfc_trans_preloop_setup (gfc_loopinfo * loop, int dim, int flag,
 		{
 		  if (ar->dimen_type[i] == DIMEN_ELEMENT)
 		    array = add_array_index (pblock, ploop, ss, array, ar,
-					     pss->dim[i], i, &domains);
+					     i, -1 /* unused */, &domains);
 		  else
 		    domains.safe_push (TYPE_DOMAIN (array_type));
 
@@ -4321,9 +4321,6 @@ gfc_conv_section_startstride (stmtblock_t * block, gfc_ss * ss, int dim)
   evaluate_bound (block, info->end, ar->end, desc, dim, false,
 		  ar->as->type == AS_DEFERRED, save_value);
 
-  evaluate_bound (block, info->lbound, nullptr, desc, dim, true,
-		  ar->as->type == AS_DEFERRED, save_value);
-
   /* Calculate the stride.  */
   if (stride == NULL)
     info->stride[dim] = gfc_index_one_node;
@@ -4341,6 +4338,20 @@ 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.  */
 
@@ -4592,7 +4603,13 @@ 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_evaluate_lbound (&outer_loop->pre, ss, n);
 	  break;
 
 	case GFC_SS_INTRINSIC:
@@ -6844,10 +6861,9 @@ gfc_trans_dummy_array_bias (gfc_symbol * sym, tree tmpdesc,
 
 /* Calculate the overall offset, including subreferences.  */
 void
-gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
+gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc,
 			bool subref, gfc_expr *expr)
 {
-  tree tmp;
   tree field;
   tree stride;
   tree index;
@@ -6855,17 +6871,20 @@ gfc_get_dataptr_offset (stmtblock_t *block, tree parm, tree desc, tree offset,
   gfc_se start;
   int n;
 
-  /* If offset is NULL and this is not a subreferenced array, there is
-     nothing to do.  */
-  if (offset == NULL_TREE)
+  tree offset = gfc_index_zero_node;
+
+  bool non_negative_strides = non_negative_strides_array_p (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--)
     {
-      if (subref)
-	offset = gfc_index_zero_node;
-      else
-	return;
+      array = build_array_ref (desc, array, gfc_index_zero_node,
+			       non_negative_strides, gfc_index_zero_node,
+			       NULL_TREE, nullptr);
     }
-
-  tmp = build_array_ref (desc, offset);
+  tmp = array;
 
   /* 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-array.h b/gcc/fortran/trans-array.h
index d52c1a859459..73322a227a5f 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -147,7 +147,7 @@ void gfc_conv_array_ref (gfc_se *, gfc_array_ref *, gfc_expr *, locus *);
 void gfc_conv_tmp_array_ref (gfc_se * se);
 
 /* Calculate the overall offset, including subreferences.  */
-void gfc_get_dataptr_offset (stmtblock_t*, tree, tree, tree, bool, gfc_expr*);
+void gfc_get_dataptr_offset (stmtblock_t*, tree, tree, bool, gfc_expr*);
 /* Obtain the span of an array.  */
 tree gfc_get_array_span (tree, gfc_expr *);
 /* Evaluate an array expression.  */
diff --git a/gcc/fortran/trans-descriptor.cc b/gcc/fortran/trans-descriptor.cc
index 699f29cd6137..4bbc05be7a4e 100644
--- a/gcc/fortran/trans-descriptor.cc
+++ b/gcc/fortran/trans-descriptor.cc
@@ -2514,7 +2514,8 @@ gfc_copy_descriptor (stmtblock_t *block, tree dest, tree src,
   gfc_add_modify (block, dest, tmp1);
 
   /* Add any offsets from subreferences.  */
-  gfc_get_dataptr_offset (block, dest, src, NULL_TREE, subref, src_expr);
+  if (subref)
+    gfc_get_dataptr_offset (block, dest, src, subref, src_expr);
 
   /* ....and set the span field.  */
   tree tmp2;
@@ -3183,8 +3184,7 @@ gfc_set_descriptor (stmtblock_t *block, tree dest, tree src, gfc_expr *src_expr,
 
   if (data_needed)
     /* Point the data pointer at the 1st element in the section.  */
-    gfc_get_dataptr_offset (block, dest, src, gfc_index_zero_node,
-			    subref, src_expr);
+    gfc_get_dataptr_offset (block, dest, src, subref, src_expr);
   else
     gfc_conv_descriptor_data_set (block, dest,
 				  gfc_index_zero_node);
diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 9836bdfb2207..1830ebaa5ce7 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -5956,7 +5956,7 @@ gfc_conv_gfc_desc_to_cfi_desc (gfc_se *parmse, gfc_expr *e, gfc_symbol *fsym)
       if (POINTER_TYPE_P (TREE_TYPE (gfc)))
 	gfc = build_fold_indirect_ref_loc (input_location, gfc);
       else if (is_subref_array (e) && e->ts.type != BT_CHARACTER)
-	 gfc_get_dataptr_offset (&se.pre, gfc, gfc, NULL, true, e);
+	 gfc_get_dataptr_offset (&se.pre, gfc, gfc, true, e);
     }
   if (e->ts.type == BT_CHARACTER)
     {
diff --git a/gcc/fortran/trans-types.cc b/gcc/fortran/trans-types.cc
index 6d5b6175cc03..0e89739b5876 100644
--- a/gcc/fortran/trans-types.cc
+++ b/gcc/fortran/trans-types.cc
@@ -1448,8 +1448,14 @@ gfc_get_element_type (tree type)
 	}
       else
 	{
-	  gcc_assert (TREE_CODE (type) == ARRAY_TYPE);
-	  element = TREE_TYPE (type);
+	  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;
 	}
     }
   else
diff --git a/gcc/fortran/trans.cc b/gcc/fortran/trans.cc
index 9ad826cf6d8c..9398deec554f 100644
--- a/gcc/fortran/trans.cc
+++ b/gcc/fortran/trans.cc
@@ -413,7 +413,7 @@ gfc_build_spanned_array_ref (tree base, tree offset, tree span)
 
 tree
 gfc_build_array_ref (tree type, tree base, tree index, bool non_negative_offset,
-		     tree offset, tree spacing)
+		     tree min_val, tree spacing)
 {
   if (DECL_P (base))
     TREE_ADDRESSABLE (base) = 1;
@@ -422,22 +422,15 @@ gfc_build_array_ref (tree type, tree base, tree index, bool non_negative_offset,
   STRIP_TYPE_NOPS (index);
 
   if (non_negative_offset)
-    {
-      tree min_val = offset ? fold_build1_loc (input_location, NEGATE_EXPR,
-					       gfc_array_index_type, offset)
-			    : NULL_TREE;
-      return build4_loc (input_location, ARRAY_REF, type, base, index,
-			 min_val, spacing);
-    }
+    return build4_loc (input_location, ARRAY_REF, type, base, index,
+		       min_val, spacing);
   /* Otherwise use pointer arithmetic.  */
   else
     {
       gcc_assert (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE);
-      tree min = NULL_TREE;
-      if (offset != NULL_TREE)
-	min = fold_build1_loc (input_location, NEGATE_EXPR,
-			       gfc_array_index_type, offset);
-      else if (TYPE_DOMAIN (TREE_TYPE (base)))
+      tree min = min_val;
+      if (min == NULL_TREE
+	  && TYPE_DOMAIN (TREE_TYPE (base)))
 	min = TYPE_MIN_VALUE (TYPE_DOMAIN (TREE_TYPE (base)));
 
       tree zero_based_index
@@ -448,9 +441,14 @@ gfc_build_array_ref (tree type, tree base, tree index, bool non_negative_offset,
 	            	    fold_convert (gfc_array_index_type, min))
 	     : fold_convert (gfc_array_index_type, index);
 
+      tree delta = spacing;
+      if (delta == NULL_TREE)
+	delta = fold_convert_loc (input_location, gfc_array_index_type,
+				  TYPE_SIZE_UNIT (type));
+
       tree offset_bytes = fold_build2_loc (input_location, MULT_EXPR,
 					   gfc_array_index_type,
-					   zero_based_index, spacing);
+					   zero_based_index, delta);
       offset_bytes = fold_convert_loc (input_location, sizetype,
 				       offset_bytes);


More information about the Gcc-cvs mailing list