https://gcc.gnu.org/g:04794bba3a6b1ec68947725d973f8fb3f7ea5364

commit r16-5539-g04794bba3a6b1ec68947725d973f8fb3f7ea5364
Author: Eric Botcazou <[email protected]>
Date:   Mon Nov 24 10:36:35 2025 +0100

    Fix wrong code for indexed component with very large index type
    
    This fixes an old issue whereby we generate wrong code in Ada for an indexed
    component in an array with a ludicrously large index type instead of raising
    Storage_Error.  We would need the counterpart of int_const_binop for unop in
    the general case, but that's not worth the hassle and int_const_convert is
    good enough.
    
    gcc/
            PR ada/33994
            * fold-const.h (int_const_convert): New prototype.
            * fold-const.cc (fold_convert_const_int_from_int): Rename to...
            (int_const_convert): ...this, remove static keyword and add third
            parameter OVERFLOWABLE.
            (fold_convert_const): Call int_const_convert if ARG1 is an integer
            constant.
    
    gcc/ada/
            PR ada/33994
            * gcc-interface/utils.cc (convert) <INTEGER_TYPE>: Call
            int_const_convert if the expression is an integer constant.
    
    gcc/testsuite/
            * gnat.dg/object_overflow6.adb: New test.

Diff:
---
 gcc/ada/gcc-interface/utils.cc             |  5 +++++
 gcc/fold-const.cc                          | 14 +++++++-------
 gcc/fold-const.h                           |  1 +
 gcc/testsuite/gnat.dg/object_overflow6.adb | 15 +++++++++++++++
 4 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 83b9e82d2dc8..db736a8d26db 100644
--- a/gcc/ada/gcc-interface/utils.cc
+++ b/gcc/ada/gcc-interface/utils.cc
@@ -5425,6 +5425,11 @@ convert (tree type, tree expr)
            return fold_convert (type, expr);
        }
 
+      if (TREE_CODE (expr) == INTEGER_CST)
+       return int_const_convert (type, expr,
+                                 type == sizetype || type == bitsizetype
+                                 ? -1 : !POINTER_TYPE_P (etype));
+
       /* ... fall through ... */
 
     case ENUMERAL_TYPE:
diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc
index 861d73ce9607..85e7da595c6a 100644
--- a/gcc/fold-const.cc
+++ b/gcc/fold-const.cc
@@ -2183,12 +2183,12 @@ size_diffop_loc (location_t loc, tree arg0, tree arg1)
                                                             MINUS_EXPR,
                                                             arg1, arg0)));
 }
-
-/* A subroutine of fold_convert_const handling conversions of an
-   INTEGER_CST to another integer type.  */
 
-static tree
-fold_convert_const_int_from_int (tree type, const_tree arg1)
+/* Convert integer constant ARG1 to TYPE, which is an integral or offset
+   or pointer type.  */
+
+tree
+int_const_convert (tree type, const_tree arg1, int overflowable)
 {
   /* Given an integer constant, make new constant with new type,
      appropriately sign-extended or truncated.  Use widest_int
@@ -2197,7 +2197,7 @@ fold_convert_const_int_from_int (tree type, const_tree 
arg1)
   unsigned prec = MAX (TYPE_PRECISION (arg1_type), TYPE_PRECISION (type));
   return force_fit_type (type, wide_int::from (wi::to_wide (arg1), prec,
                                               TYPE_SIGN (arg1_type)),
-                        !POINTER_TYPE_P (TREE_TYPE (arg1)),
+                        overflowable,
                         TREE_OVERFLOW (arg1));
 }
 
@@ -2500,7 +2500,7 @@ fold_convert_const (enum tree_code code, tree type, tree 
arg1)
       || TREE_CODE (type) == OFFSET_TYPE)
     {
       if (TREE_CODE (arg1) == INTEGER_CST)
-       return fold_convert_const_int_from_int (type, arg1);
+       return int_const_convert (type, arg1, !POINTER_TYPE_P (arg_type));
       else if (TREE_CODE (arg1) == REAL_CST)
        return fold_convert_const_int_from_real (code, type, arg1);
       else if (TREE_CODE (arg1) == FIXED_CST)
diff --git a/gcc/fold-const.h b/gcc/fold-const.h
index 87e7ec15157a..149992d1f107 100644
--- a/gcc/fold-const.h
+++ b/gcc/fold-const.h
@@ -134,6 +134,7 @@ extern bool poly_int_binop (poly_wide_int &res, enum 
tree_code,
                            const_tree, const_tree, signop,
                            wi::overflow_type *);
 extern tree int_const_binop (enum tree_code, const_tree, const_tree, int = 1);
+extern tree int_const_convert (tree, const_tree, int = 1);
 #define build_fold_addr_expr(T)\
         build_fold_addr_expr_loc (UNKNOWN_LOCATION, (T))
 extern tree build_fold_addr_expr_loc (location_t, tree);
diff --git a/gcc/testsuite/gnat.dg/object_overflow6.adb 
b/gcc/testsuite/gnat.dg/object_overflow6.adb
new file mode 100644
index 000000000000..8aa8e04dcc5d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/object_overflow6.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+
+with System;
+
+procedure Object_Overflow6 is
+
+  type Address is range 0 .. System.Memory_Size;
+
+  type Arr is array (Address) of Character;
+
+  A : Arr; -- { dg-warning "Storage_Error" }
+
+begin
+  A(1) := 'a';
+end;

Reply via email to