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;

Reply via email to