Hi,

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 probably need the counterpart of int_const_binop for 
unop in the general case, but that's not worth the hassle so int_const_convert 
is good enough.

Tested on x86-64/Linux, OK for the mainline?


2025-11-24  Eric Botcazou  <[email protected]>

        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.


2025-11-24  Eric Botcazou  <[email protected]>

        PR ada/33994
        * gcc-interface/utils.cc (convert) <INTEGER_TYPE>: Call
        int_const_convert if the expression is an integer constant.


2025-11-24  Eric Botcazou  <[email protected]>

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

-- 
Eric Botcazou
diff --git a/gcc/ada/gcc-interface/utils.cc b/gcc/ada/gcc-interface/utils.cc
index 83b9e82d2dc..db736a8d26d 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 861d73ce960..415d84a54dc 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 87e7ec15157..149992d1f10 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);
-- { 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