]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix wrong code for indexed component with very large index type
authorEric Botcazou <ebotcazou@adacore.com>
Mon, 24 Nov 2025 09:36:35 +0000 (10:36 +0100)
committerEric Botcazou <ebotcazou@adacore.com>
Mon, 24 Nov 2025 09:42:45 +0000 (10:42 +0100)
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.

gcc/ada/gcc-interface/utils.cc
gcc/fold-const.cc
gcc/fold-const.h
gcc/testsuite/gnat.dg/object_overflow6.adb [new file with mode: 0644]

index 83b9e82d2dc89c519e5261e9efcf60be440bcdaf..db736a8d26db79c1010b257e05955284c5549516 100644 (file)
@@ -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:
index 861d73ce9607a34bec2f65a783a1a34f64bc0180..85e7da595c6a956e48f6e3ef9e598161e2e94296 100644 (file)
@@ -2183,12 +2183,12 @@ size_diffop_loc (location_t loc, tree arg0, tree arg1)
                                                             MINUS_EXPR,
                                                             arg1, arg0)));
 }
-\f
-/* 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)
index 87e7ec15157a2af9dd8a461ea54468a689909fc2..149992d1f107835f630990e946127e1ec426ba0b 100644 (file)
@@ -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 (file)
index 0000000..8aa8e04
--- /dev/null
@@ -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;