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 Botcazoudiff --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;