===================================================================
@@ -5465,6 +5465,13 @@
-- value, it may be possible to build an equivalent aggregate instead,
-- and prevent an actual call to the initialization procedure.
+ procedure Check_Large_Modular_Array;
+ -- Check that the size of the array can be computed without overflow,
+ -- and generate a Storage_Error otherwise. This is only relevant for
+ -- array types whose index in a (mod 2**64) type, where wrap-around
+ -- arithmetic might yield a meaningless value for the length of the
+ -- array, or its corresponding attribute.
+
procedure Default_Initialize_Object (After : Node_Id);
-- Generate all default initialization actions for object Def_Id. Any
-- new code is inserted after node After.
@@ -5603,6 +5610,58 @@
end Build_Equivalent_Aggregate;
-------------------------------
+ -- Check_Large_Modular_Array --
+ -------------------------------
+
+ procedure Check_Large_Modular_Array is
+ Index_Typ : Entity_Id;
+
+ begin
+ if Is_Array_Type (Typ)
+ and then Is_Modular_Integer_Type (Etype (First_Index (Typ)))
+ then
+ -- To prevent arithmetic overflow with large values, we
+ -- raise Storage_Error under the following guard:
+ --
+ -- (Arr'Last / 2 - Arr'First / 2) > (Typ'Last - 1) / 2
+
+ -- This takes care of the boundary case, but it is preferable
+ -- to use a smaller limit, because even on 64-bit architectures
+ -- an array of more than 2 ** 30 bytes is likely to raise
+ -- Storage_Error.
+
+ Index_Typ := Etype (First_Index (Typ));
+ if RM_Size (Index_Typ) = RM_Size (Standard_Long_Long_Integer) then
+ Insert_Action (N,
+ Make_Raise_Storage_Error (Loc,
+ Condition =>
+ Make_Op_Ge (Loc,
+ Left_Opnd =>
+ Make_Op_Subtract (Loc,
+ Left_Opnd =>
+ Make_Op_Divide (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Typ, Loc),
+ Attribute_Name => Name_Last),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Uint_2)),
+ Right_Opnd =>
+ Make_Op_Divide (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Typ, Loc),
+ Attribute_Name => Name_First),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, Uint_2))),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, (Uint_2 ** 30))),
+ Reason => SE_Object_Too_Large));
+ end if;
+ end if;
+ end Check_Large_Modular_Array;
+
+ -------------------------------
-- Default_Initialize_Object --
-------------------------------
@@ -6012,6 +6071,8 @@
Build_Master_Entity (Def_Id);
end if;
+ Check_Large_Modular_Array;
+
-- Default initialization required, and no expression present
if No (Expr) then