https://gcc.gnu.org/g:c4a80f2d336b8fb78cc97f9107981119b1eff30b
commit r17-4541-gc4a80f2d336b8fb78cc97f9107981119b1eff30b Author: Eric Botcazou <[email protected]> Date: Mon Sep 21 23:46:34 2026 +0200 RISC-V: Fix ICE on array with negative low bound in 32-bit mode The included Ada testcase trips on the failure of the assertion present on line 6848 in riscv_flatten_aggregate_field: n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) - tree_to_uhwi (TYPE_MIN_VALUE (index)); gcc_assert (n_elts >= 0); The problem is that the computation of the number of elements is performed in HOST_WIDE_INT, which does not reproduce the wraparound phenomenon of the 32-bit sizetype index that happens when the low bound is negative and the high bound is not. The correct computation is implemented by tree.cc:array_type_nelts_top but it is done on trees, while using wide-ints is sufficient in this case. gcc/ * config/riscv/riscv.cc (riscv_flatten_aggregate_field) <ARRAY_TYPE>: Perform the computation of the number of elements using the precision of the index type instead of using HOST_WIDE_INT. gcc/testsuite/ * gnat.dg/array44.adb: New test. Diff: --- gcc/config/riscv/riscv.cc | 14 +++++++------- gcc/testsuite/gnat.dg/array44.adb | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index b676292ca566..87c24e5dcc15 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -6807,7 +6807,6 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, case ARRAY_TYPE: { - HOST_WIDE_INT n_elts; riscv_aggregate_field subfields[8]; tree index = TYPE_DOMAIN (type); tree elt_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); @@ -6828,9 +6827,9 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST || !index || !TYPE_MAX_VALUE (index) - || !tree_fits_uhwi_p (TYPE_MAX_VALUE (index)) + || TREE_CODE (TYPE_MAX_VALUE (index)) != INTEGER_CST || !TYPE_MIN_VALUE (index) - || !tree_fits_uhwi_p (TYPE_MIN_VALUE (index)) + || TREE_CODE (TYPE_MIN_VALUE (index)) != INTEGER_CST || !tree_fits_uhwi_p (elt_size)) return -1; @@ -6843,11 +6842,12 @@ riscv_flatten_aggregate_field (const_tree type, riscv_aggregate_field *fields, if (n_subfields <= 0) return -1; - n_elts = 1 + tree_to_uhwi (TYPE_MAX_VALUE (index)) - - tree_to_uhwi (TYPE_MIN_VALUE (index)); - gcc_assert (n_elts >= 0); + const wide_int max = wi::to_wide (TYPE_MAX_VALUE (index)); + const wide_int min = wi::to_wide (TYPE_MIN_VALUE (index)); + const wide_int n_elts = max - min + 1; + gcc_assert (wi::fits_uhwi_p (n_elts)); - for (HOST_WIDE_INT i = 0; i < n_elts; i++) + for (unsigned HOST_WIDE_INT i = 0; i < n_elts.to_uhwi (); i++) for (int j = 0; j < n_subfields; j++) { if (n >= max_aggregate_field) diff --git a/gcc/testsuite/gnat.dg/array44.adb b/gcc/testsuite/gnat.dg/array44.adb new file mode 100644 index 000000000000..149d9c0bdb01 --- /dev/null +++ b/gcc/testsuite/gnat.dg/array44.adb @@ -0,0 +1,19 @@ +-- { dg-do compile } +-- { dg-options "-gnata" } + +procedure Array44 is + + type Buffer_Type is array (Integer range -1 .. 0) of Natural range 0 .. 255; + + type U is record + Buffer : Buffer_Type; + end record; + + function F (Src : in Buffer_Type) return U is ((Buffer => Src)); + + Src : constant Buffer_Type := (others => 1); + Dst : constant U := F (Src); + +begin + pragma Assert (Dst.Buffer (0) = 1); +end;
