Hi,

the attached 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 of the 32-bit sizetype
index that happens when the low bound is negative and the high bound is not.

The correct computation is the one implemented by tree.cc:array_type_nelts_top
but it is done on trees, while using wide-ints is sufficient in this case.

Tested on riscv32-elf, OK for the mainline?


2026-09-21  Eric Botcazou  <[email protected]>

        * 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.


2026-09-21  Eric Botcazou  <[email protected]>

        * gnat.dg/array44.adb: New test.


-- 
Eric Botcazou
diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc
index 9fca2f679a0..1153505bf95 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)
-- { 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