https://gcc.gnu.org/g:837eb01ed7035de0cc44aa66c956492554db614b
commit 837eb01ed7035de0cc44aa66c956492554db614b Author: Mikael Morin <mik...@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 5014c1aa8731..c846b2c2a1ef 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 37fdda7e0cdd..2dcb684e326a 100644 --- a/gcc/fortran/trans-expr.cc +++ b/gcc/fortran/trans-expr.cc @@ -5938,7 +5938,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 f559b2bd384f..4661ff92fa8d 100644 --- a/gcc/fortran/trans-types.cc +++ b/gcc/fortran/trans-types.cc @@ -1445,8 +1445,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 c77bd72b3fb2..c59ebbdaf7bd 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);