Commit 7f4b58c2 by Hristian Kirtchev Committed by Pierre-Marie de Rodat

[Ada] Spurious Storage_Error on imported array

This patch moves the check which verifies that a large modular array is created
from expansion to freezing in order to take interfacing pragmas in account. The
check is no longer performed on imported objects because no object is created
in that case.

2018-05-23  Hristian Kirtchev  <kirtchev@adacore.com>

gcc/ada/

	* exp_ch3.adb (Check_Large_Modular_Array): Moved to Freeze.
	(Expand_N_Object_Declaration): Do not check for a large modular array
	here.
	* freeze.adb (Check_Large_Modular_Array): Moved from Exp_Ch3.
	(Freeze_Object_Declaration): Code cleanup. Check for a large modular
	array.
	* sem_ch3.adb: Minor reformatting.

gcc/testsuite/

	* gnat.dg/import2.adb: New testcase.

From-SVN: r260597
parent ffdd5248
2018-05-23 Hristian Kirtchev <kirtchev@adacore.com>
* exp_ch3.adb (Check_Large_Modular_Array): Moved to Freeze.
(Expand_N_Object_Declaration): Do not check for a large modular array
here.
* freeze.adb (Check_Large_Modular_Array): Moved from Exp_Ch3.
(Freeze_Object_Declaration): Code cleanup. Check for a large modular
array.
* sem_ch3.adb: Minor reformatting.
2018-05-23 Ed Schonberg <schonberg@adacore.com> 2018-05-23 Ed Schonberg <schonberg@adacore.com>
* einfo.ads: New attribute on types: Predicated_Parent, to simplify the * einfo.ads: New attribute on types: Predicated_Parent, to simplify the
......
...@@ -5606,13 +5606,6 @@ package body Exp_Ch3 is ...@@ -5606,13 +5606,6 @@ package body Exp_Ch3 is
-- value, it may be possible to build an equivalent aggregate instead, -- value, it may be possible to build an equivalent aggregate instead,
-- and prevent an actual call to the initialization procedure. -- 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 Count_Default_Sized_Task_Stacks procedure Count_Default_Sized_Task_Stacks
(Typ : Entity_Id; (Typ : Entity_Id;
Pri_Stacks : out Int; Pri_Stacks : out Int;
...@@ -5759,61 +5752,6 @@ package body Exp_Ch3 is ...@@ -5759,61 +5752,6 @@ package body Exp_Ch3 is
end if; end if;
end Build_Equivalent_Aggregate; 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) > (2 ** 30)
-- 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;
------------------------------------- -------------------------------------
-- Count_Default_Sized_Task_Stacks -- -- Count_Default_Sized_Task_Stacks --
------------------------------------- -------------------------------------
...@@ -6434,8 +6372,6 @@ package body Exp_Ch3 is ...@@ -6434,8 +6372,6 @@ package body Exp_Ch3 is
Build_Master_Entity (Def_Id); Build_Master_Entity (Def_Id);
end if; end if;
Check_Large_Modular_Array;
-- If No_Implicit_Heap_Allocations or No_Implicit_Task_Allocations -- If No_Implicit_Heap_Allocations or No_Implicit_Task_Allocations
-- restrictions are active then default-sized secondary stacks are -- restrictions are active then default-sized secondary stacks are
-- generated by the binder and allocated by SS_Init. To provide the -- generated by the binder and allocated by SS_Init. To provide the
......
...@@ -3187,6 +3187,100 @@ package body Freeze is ...@@ -3187,6 +3187,100 @@ package body Freeze is
------------------------------- -------------------------------
procedure Freeze_Object_Declaration (E : Entity_Id) is procedure Freeze_Object_Declaration (E : Entity_Id) is
procedure Check_Large_Modular_Array (Typ : Entity_Id);
-- Check that the size of array type Typ can be computed without
-- overflow, and generates a Storage_Error otherwise. This is only
-- relevant for array types whose index is a (mod 2**64) type, where
-- wrap-around arithmetic might yield a meaningless value for the
-- length of the array, or its corresponding attribute.
-------------------------------
-- Check_Large_Modular_Array --
-------------------------------
procedure Check_Large_Modular_Array (Typ : Entity_Id) is
Obj_Loc : constant Source_Ptr := Sloc (E);
Idx_Typ : Entity_Id;
begin
-- Nothing to do when expansion is disabled because this routine
-- generates a runtime check.
if not Expander_Active then
return;
-- Nothing to do for String literal subtypes because their index
-- cannot be a modular type.
elsif Ekind (Typ) = E_String_Literal_Subtype then
return;
-- Nothing to do for an imported object because the object will
-- be created on the exporting side.
elsif Is_Imported (E) then
return;
-- Nothing to do for unconstrained array types. This case arises
-- when the object declaration is illegal.
elsif not Is_Constrained (Typ) then
return;
end if;
Idx_Typ := Etype (First_Index (Typ));
-- To prevent arithmetic overflow with large values, we raise
-- Storage_Error under the following guard:
--
-- (Arr'Last / 2 - Arr'First / 2) > (2 ** 30)
--
-- 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.
if Is_Modular_Integer_Type (Idx_Typ)
and then RM_Size (Idx_Typ) = RM_Size (Standard_Long_Long_Integer)
then
Insert_Action (Declaration_Node (E),
Make_Raise_Storage_Error (Obj_Loc,
Condition =>
Make_Op_Ge (Obj_Loc,
Left_Opnd =>
Make_Op_Subtract (Obj_Loc,
Left_Opnd =>
Make_Op_Divide (Obj_Loc,
Left_Opnd =>
Make_Attribute_Reference (Obj_Loc,
Prefix =>
New_Occurrence_Of (Typ, Obj_Loc),
Attribute_Name => Name_Last),
Right_Opnd =>
Make_Integer_Literal (Obj_Loc, Uint_2)),
Right_Opnd =>
Make_Op_Divide (Obj_Loc,
Left_Opnd =>
Make_Attribute_Reference (Obj_Loc,
Prefix =>
New_Occurrence_Of (Typ, Obj_Loc),
Attribute_Name => Name_First),
Right_Opnd =>
Make_Integer_Literal (Obj_Loc, Uint_2))),
Right_Opnd =>
Make_Integer_Literal (Obj_Loc, (Uint_2 ** 30))),
Reason => SE_Object_Too_Large));
end if;
end Check_Large_Modular_Array;
-- Local variables
Typ : constant Entity_Id := Etype (E);
Def : Node_Id;
-- Start of processing for Freeze_Object_Declaration
begin begin
-- Abstract type allowed only for C++ imported variables or constants -- Abstract type allowed only for C++ imported variables or constants
...@@ -3195,22 +3289,20 @@ package body Freeze is ...@@ -3195,22 +3289,20 @@ package body Freeze is
-- x'Class'Input where x is abstract) where we legitimately -- x'Class'Input where x is abstract) where we legitimately
-- generate an abstract object. -- generate an abstract object.
if Is_Abstract_Type (Etype (E)) if Is_Abstract_Type (Typ)
and then Comes_From_Source (Parent (E)) and then Comes_From_Source (Parent (E))
and then not (Is_Imported (E) and then Is_CPP_Class (Etype (E))) and then not (Is_Imported (E) and then Is_CPP_Class (Typ))
then then
Error_Msg_N ("type of object cannot be abstract", Def := Object_Definition (Parent (E));
Object_Definition (Parent (E)));
Error_Msg_N ("type of object cannot be abstract", Def);
if Is_CPP_Class (Etype (E)) then if Is_CPP_Class (Etype (E)) then
Error_Msg_NE Error_Msg_NE ("\} may need a cpp_constructor", Def, Typ);
("\} may need a cpp_constructor",
Object_Definition (Parent (E)), Etype (E));
elsif Present (Expression (Parent (E))) then elsif Present (Expression (Parent (E))) then
Error_Msg_N -- CODEFIX Error_Msg_N -- CODEFIX
("\maybe a class-wide type was meant", ("\maybe a class-wide type was meant", Def);
Object_Definition (Parent (E)));
end if; end if;
end if; end if;
...@@ -3221,20 +3313,20 @@ package body Freeze is ...@@ -3221,20 +3313,20 @@ package body Freeze is
Validate_Object_Declaration (Declaration_Node (E)); Validate_Object_Declaration (Declaration_Node (E));
-- If there is an address clause, check that it is valid -- If there is an address clause, check that it is valid and if need
-- and if need be move initialization to the freeze node. -- be move initialization to the freeze node.
Check_Address_Clause (E); Check_Address_Clause (E);
-- Similar processing is needed for aspects that may affect -- Similar processing is needed for aspects that may affect object
-- object layout, like Alignment, if there is an initialization -- layout, like Alignment, if there is an initialization expression.
-- expression. We don't do this if there is a pragma Linker_Section, -- We don't do this if there is a pragma Linker_Section, because it
-- because it would prevent the back end from statically initializing -- would prevent the back end from statically initializing the
-- the object; we don't want elaboration code in that case. -- object; we don't want elaboration code in that case.
if Has_Delayed_Aspects (E) if Has_Delayed_Aspects (E)
and then Expander_Active and then Expander_Active
and then Is_Array_Type (Etype (E)) and then Is_Array_Type (Typ)
and then Present (Expression (Parent (E))) and then Present (Expression (Parent (E)))
and then No (Linker_Section_Pragma (E)) and then No (Linker_Section_Pragma (E))
then then
...@@ -3243,7 +3335,6 @@ package body Freeze is ...@@ -3243,7 +3335,6 @@ package body Freeze is
Lhs : constant Node_Id := New_Occurrence_Of (E, Loc); Lhs : constant Node_Id := New_Occurrence_Of (E, Loc);
begin begin
-- Capture initialization value at point of declaration, and -- Capture initialization value at point of declaration, and
-- make explicit assignment legal, because object may be a -- make explicit assignment legal, because object may be a
-- constant. -- constant.
...@@ -3251,7 +3342,7 @@ package body Freeze is ...@@ -3251,7 +3342,7 @@ package body Freeze is
Remove_Side_Effects (Expression (Decl)); Remove_Side_Effects (Expression (Decl));
Set_Assignment_OK (Lhs); Set_Assignment_OK (Lhs);
-- Move initialization to freeze actions. -- Move initialization to freeze actions
Append_Freeze_Action (E, Append_Freeze_Action (E,
Make_Assignment_Statement (Loc, Make_Assignment_Statement (Loc,
...@@ -3283,7 +3374,7 @@ package body Freeze is ...@@ -3283,7 +3374,7 @@ package body Freeze is
-- a dispatch table entry, then we mean it. -- a dispatch table entry, then we mean it.
if Ekind (E) /= E_Constant if Ekind (E) /= E_Constant
and then (Is_Aliased (E) or else Is_Aliased (Etype (E))) and then (Is_Aliased (E) or else Is_Aliased (Typ))
and then not Is_Internal_Name (Chars (E)) and then not Is_Internal_Name (Chars (E))
then then
Set_Is_True_Constant (E, False); Set_Is_True_Constant (E, False);
...@@ -3304,11 +3395,11 @@ package body Freeze is ...@@ -3304,11 +3395,11 @@ package body Freeze is
and then not Is_Imported (E) and then not Is_Imported (E)
and then not Has_Init_Expression (Declaration_Node (E)) and then not Has_Init_Expression (Declaration_Node (E))
and then and then
((Has_Non_Null_Base_Init_Proc (Etype (E)) ((Has_Non_Null_Base_Init_Proc (Typ)
and then not No_Initialization (Declaration_Node (E)) and then not No_Initialization (Declaration_Node (E))
and then not Initialization_Suppressed (Etype (E))) and then not Initialization_Suppressed (Typ))
or else or else
(Needs_Simple_Initialization (Etype (E)) (Needs_Simple_Initialization (Typ)
and then not Is_Internal (E))) and then not Is_Internal (E)))
then then
Has_Default_Initialization := True; Has_Default_Initialization := True;
...@@ -3316,9 +3407,9 @@ package body Freeze is ...@@ -3316,9 +3407,9 @@ package body Freeze is
(No_Default_Initialization, Declaration_Node (E)); (No_Default_Initialization, Declaration_Node (E));
end if; end if;
-- Check that a Thread_Local_Storage variable does not have -- Check that a Thread_Local_Storage variable does not have default
-- default initialization, and any explicit initialization must -- initialization, and any explicit initialization must either be the
-- either be the null constant or a static constant. -- null constant or a static constant.
if Has_Pragma_Thread_Local_Storage (E) then if Has_Pragma_Thread_Local_Storage (E) then
declare declare
...@@ -3356,31 +3447,30 @@ package body Freeze is ...@@ -3356,31 +3447,30 @@ package body Freeze is
Set_Is_Public (E); Set_Is_Public (E);
end if; end if;
-- For source objects that are not Imported and are library -- For source objects that are not Imported and are library level, if
-- level, if no linker section pragma was given inherit the -- no linker section pragma was given inherit the appropriate linker
-- appropriate linker section from the corresponding type. -- section from the corresponding type.
if Comes_From_Source (E) if Comes_From_Source (E)
and then not Is_Imported (E) and then not Is_Imported (E)
and then Is_Library_Level_Entity (E) and then Is_Library_Level_Entity (E)
and then No (Linker_Section_Pragma (E)) and then No (Linker_Section_Pragma (E))
then then
Set_Linker_Section_Pragma Set_Linker_Section_Pragma (E, Linker_Section_Pragma (Typ));
(E, Linker_Section_Pragma (Etype (E)));
end if; end if;
-- For convention C objects of an enumeration type, warn if the -- For convention C objects of an enumeration type, warn if the size
-- size is not integer size and no explicit size given. Skip -- is not integer size and no explicit size given. Skip warning for
-- warning for Boolean, and Character, assume programmer expects -- Boolean and Character, and assume programmer expects 8-bit sizes
-- 8-bit sizes for these cases. -- for these cases.
if (Convention (E) = Convention_C if (Convention (E) = Convention_C
or else or else
Convention (E) = Convention_CPP) Convention (E) = Convention_CPP)
and then Is_Enumeration_Type (Etype (E)) and then Is_Enumeration_Type (Typ)
and then not Is_Character_Type (Etype (E)) and then not Is_Character_Type (Typ)
and then not Is_Boolean_Type (Etype (E)) and then not Is_Boolean_Type (Typ)
and then Esize (Etype (E)) < Standard_Integer_Size and then Esize (Typ) < Standard_Integer_Size
and then not Has_Size_Clause (E) and then not Has_Size_Clause (E)
then then
Error_Msg_Uint_1 := UI_From_Int (Standard_Integer_Size); Error_Msg_Uint_1 := UI_From_Int (Standard_Integer_Size);
...@@ -3388,6 +3478,10 @@ package body Freeze is ...@@ -3388,6 +3478,10 @@ package body Freeze is
("??convention C enumeration object has size less than ^", E); ("??convention C enumeration object has size less than ^", E);
Error_Msg_N ("\??use explicit size clause to set size", E); Error_Msg_N ("\??use explicit size clause to set size", E);
end if; end if;
if Is_Array_Type (Typ) then
Check_Large_Modular_Array (Typ);
end if;
end Freeze_Object_Declaration; end Freeze_Object_Declaration;
----------------------------- -----------------------------
......
...@@ -21676,7 +21676,8 @@ package body Sem_Ch3 is ...@@ -21676,7 +21676,8 @@ package body Sem_Ch3 is
then then
Constrain_Array (Def_Id, S, Related_Nod, Related_Id, Suffix); Constrain_Array (Def_Id, S, Related_Nod, Related_Id, Suffix);
-- ... but more comonly by a discriminated record type. -- ... but more commonly is completed by a discriminated record
-- type.
else else
Constrain_Discriminated_Type (Def_Id, S, Related_Nod); Constrain_Discriminated_Type (Def_Id, S, Related_Nod);
......
2018-05-23 Hristian Kirtchev <kirtchev@adacore.com>
* gnat.dg/import2.adb: New testcase.
2018-05-23 Ed Schonberg <schonberg@adacore.com> 2018-05-23 Ed Schonberg <schonberg@adacore.com>
* gnat.dg/discr51.adb: New testcase. * gnat.dg/discr51.adb: New testcase.
......
-- { dg-do run }
procedure Import2 is
type Index_Typ is mod 2**64;
type Mod_Array is array (Index_Typ) of Integer;
Obj : Mod_Array;
pragma Import (Ada, Obj);
begin
null;
end Import2;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment