aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikael Morin <mikael@gcc.gnu.org>2022-04-22 22:52:26 +0200
committerMikael Morin <mikael@gcc.gnu.org>2022-04-22 22:52:26 +0200
commite72fbb6915c1dd1a52ecef55e10329e353cc3072 (patch)
tree15791c0b35c94c7d7a99bd0ed8e19938674ab764
parent89ca0fffa48b799b228beee48a16e26e24d8e199 (diff)
downloadgcc-e72fbb6915c1dd1a52ecef55e10329e353cc3072.zip
gcc-e72fbb6915c1dd1a52ecef55e10329e353cc3072.tar.gz
gcc-e72fbb6915c1dd1a52ecef55e10329e353cc3072.tar.bz2
fortran: Update index extraction code. [PR102043]
This avoids a regression on hollerith4.f90 and hollerith6.f90 later in the patch series when code generation for array references is changed to use pointer arithmetic. The problem comes from the extraction of the array index from an ARRAY_REF tree, which doesn’t work if the tree is not an ARRAY_REF any more. This updates the code generated for remaining size evaluation to work with a source tree that uses either array indexing or pointer arithmetic. PR fortran/102043 gcc/fortran/ChangeLog: * trans-io.cc: Add handling for the case where the array is referenced using pointer arithmetic.
-rw-r--r--gcc/fortran/trans-io.cc48
1 files changed, 37 insertions, 11 deletions
diff --git a/gcc/fortran/trans-io.cc b/gcc/fortran/trans-io.cc
index 732221f..9f86815 100644
--- a/gcc/fortran/trans-io.cc
+++ b/gcc/fortran/trans-io.cc
@@ -737,7 +737,6 @@ set_parameter_ref (stmtblock_t *block, stmtblock_t *postblock,
static void
gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
{
- tree size;
if (e->rank == 0)
{
@@ -755,12 +754,13 @@ gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
array = sym->backend_decl;
type = TREE_TYPE (array);
+ tree elts_count;
if (GFC_ARRAY_TYPE_P (type))
- size = GFC_TYPE_ARRAY_SIZE (type);
+ elts_count = GFC_TYPE_ARRAY_SIZE (type);
else
{
gcc_assert (GFC_DESCRIPTOR_TYPE_P (type));
- size = gfc_conv_array_stride (array, rank);
+ tree stride = gfc_conv_array_stride (array, rank);
tmp = fold_build2_loc (input_location, MINUS_EXPR,
gfc_array_index_type,
gfc_conv_array_ubound (array, rank),
@@ -768,23 +768,49 @@ gfc_convert_array_to_string (gfc_se * se, gfc_expr * e)
tmp = fold_build2_loc (input_location, PLUS_EXPR,
gfc_array_index_type, tmp,
gfc_index_one_node);
+ elts_count = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, tmp, stride);
+ }
+ gcc_assert (elts_count);
+
+ tree elt_size = TYPE_SIZE_UNIT (gfc_get_element_type (type));
+ elt_size = fold_convert (gfc_array_index_type, elt_size);
+
+ tree size;
+ if (TREE_CODE (se->expr) == ARRAY_REF)
+ {
+ tree index = TREE_OPERAND (se->expr, 1);
+ index = fold_convert (gfc_array_index_type, index);
+
+ elts_count = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type,
+ elts_count, index);
+
size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, tmp, size);
+ gfc_array_index_type, elts_count, elt_size);
+ }
+ else
+ {
+ gcc_assert (TREE_CODE (se->expr) == INDIRECT_REF);
+ tree ptr = TREE_OPERAND (se->expr, 0);
+
+ gcc_assert (TREE_CODE (ptr) == POINTER_PLUS_EXPR);
+ tree offset = fold_convert_loc (input_location, gfc_array_index_type,
+ TREE_OPERAND (ptr, 1));
+
+ size = fold_build2_loc (input_location, MULT_EXPR,
+ gfc_array_index_type, elts_count, elt_size);
+ size = fold_build2_loc (input_location, MINUS_EXPR,
+ gfc_array_index_type, size, offset);
}
gcc_assert (size);
- size = fold_build2_loc (input_location, MINUS_EXPR,
- gfc_array_index_type, size,
- TREE_OPERAND (se->expr, 1));
se->expr = gfc_build_addr_expr (NULL_TREE, se->expr);
- tmp = TYPE_SIZE_UNIT (gfc_get_element_type (type));
- size = fold_build2_loc (input_location, MULT_EXPR,
- gfc_array_index_type, size,
- fold_convert (gfc_array_index_type, tmp));
se->string_length = fold_convert (gfc_charlen_type_node, size);
return;
}
+ tree size;
gfc_conv_array_parameter (se, e, true, NULL, NULL, &size);
se->string_length = fold_convert (gfc_charlen_type_node, size);
}