From: Eric Botcazou <[email protected]>
This implements the last part of the RM 4.8(10.1) rule about allocators
for types with access discriminants. The implementation is modeled on
that of returns for types with access discriminants, given that the set
of rules applying to them is the same (RM 3.10.2(12-12.4)).
The change also streamlines the latter by applying the RM 3.10.2(12.4)
rule in Apply_Accessibility_Check_For_Discriminated_Return.
gcc/ada/ChangeLog:
* accessibility.ads (Apply_Accessibility_Check_For_Allocator):
Rename to...
(Apply_Accessibility_Check_For_Class_Wide_Allocator): ...this.
(Apply_Accessibility_Check_For_Discriminated_Allocator): New.
* accessibility.adb (Apply_Accessibility_Check_For_Allocator):
Rename to...
(Apply_Accessibility_Check_For_Class_Wide_Allocator): ...this.
Call Duplicate_Subexpr directly instead of reimplementing it.
(Apply_Accessibility_Check_For_Discriminated_Allocator): New.
(Apply_Accessibility_Check_For_Discriminated_Return): Streamline.
(Apply_Accessibility_Check_For_Return): Tweak comments.
* exp_ch4.adb (Expand_Allocator_Expression): Call
Apply_Accessibility_Check_For_Discriminated_Allocator and
adjust calls to Apply_Accessibility_Check_For_Allocator.
(Expand_N_Allocator): Likewise.
Tested on x86_64-pc-linux-gnu, committed on master.
---
gcc/ada/accessibility.adb | 194 +++++++++++++++++++++++++-------------
gcc/ada/accessibility.ads | 9 +-
gcc/ada/exp_ch4.adb | 14 ++-
3 files changed, 149 insertions(+), 68 deletions(-)
diff --git a/gcc/ada/accessibility.adb b/gcc/ada/accessibility.adb
index fcd30dde28f..702ab6c5f37 100644
--- a/gcc/ada/accessibility.adb
+++ b/gcc/ada/accessibility.adb
@@ -990,11 +990,11 @@ package body Accessibility is
end case;
end Accessibility_Level;
- ---------------------------------------------
- -- Apply_Accessibility_Check_For_Allocator --
- ---------------------------------------------
+ --------------------------------------------------------
+ -- Apply_Accessibility_Check_For_Class_Wide_Allocator --
+ --------------------------------------------------------
- procedure Apply_Accessibility_Check_For_Allocator
+ procedure Apply_Accessibility_Check_For_Class_Wide_Allocator
(N : Node_Id;
Exp : Node_Id;
Ref : Node_Id;
@@ -1025,14 +1025,13 @@ package body Accessibility is
-- If the allocator was built in place, Ref is already a reference
-- to the access object initialized to the result of the allocator
-- (see Exp_Ch6.Make_Build_In_Place_Call_In_Allocator). We call
- -- Remove_Side_Effects for cases where the build-in-place call may
+ -- Duplicate_Subexpr for cases where the build-in-place call may
-- still be the prefix of the reference (to avoid generating
-- duplicate calls). Otherwise, it is the entity associated with
-- the object containing the address of the allocated object.
if Built_In_Place then
- Remove_Side_Effects (Ref);
- Obj_Ref := New_Copy_Tree (Ref);
+ Obj_Ref := Duplicate_Subexpr (Ref);
else
Obj_Ref := New_Occurrence_Of (Ref, Loc);
end if;
@@ -1178,7 +1177,7 @@ package body Accessibility is
Then_Statements => Stmts),
Suppress => All_Checks);
end if;
- end Apply_Accessibility_Check_For_Allocator;
+ end Apply_Accessibility_Check_For_Class_Wide_Allocator;
----------------------------------------------------
-- Apply_Accessibility_Check_For_Anonymous_Return --
@@ -1367,6 +1366,102 @@ package body Accessibility is
end if;
end Apply_Accessibility_Check_For_Class_Wide_Return;
+ -----------------------------------------------------------
+ -- Apply_Accessibility_Check_For_Discriminated_Allocator --
+ -----------------------------------------------------------
+
+ procedure Apply_Accessibility_Check_For_Discriminated_Allocator
+ (N : Node_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (N);
+ Typ : constant Entity_Id := Etype (Expression (N));
+ Exp : constant Node_Id := Unqualify (Expression (N));
+ Exp_Typ : constant Entity_Id := Etype (Exp);
+
+ Discr : Entity_Id;
+ Discr_Elmt : Elmt_Id;
+ Discr_Exp : Node_Id;
+
+ -- Start of Apply_Accessibility_Check_For_Discriminated_Allocator
+
+ begin
+ -- Return immediately if accessibility checks are suppressed for N
+
+ if Scope_Suppress.Suppress (Accessibility_Check)
+ or else No_Dynamic_Accessibility_Checks_Enabled (N)
+ then
+ return;
+
+ -- Check that the allocator's access discriminants do not designate
+ -- entities that the allocator could outlive (RM 4.8(10.1)).
+
+ elsif not Has_Anonymous_Access_Discriminant (Typ) then
+ return;
+
+ -- We ignore coextensions as they cannot be implemented under the
+ -- "small integer" model.
+
+ elsif Is_Static_Coextension (N) or else Is_Dynamic_Coextension (N) then
+ return;
+
+ -- If we are allocating a function result, then that function will
+ -- perform the check.
+
+ elsif Nkind (Exp) = N_Function_Call then
+ return;
+
+ -- When the value of the access discriminant is determined by
+ -- an object with an unconstrained nominal subtype, its level
+ -- is the accessibility level of the object (RM 3.10.2(12.4)).
+
+ elsif not Is_Constrained (Exp_Typ) then
+ Insert_Action (N,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd => Accessibility_Level (Exp, Dynamic_Level),
+ Right_Opnd => Accessibility_Level (N, Dynamic_Level)),
+ Reason => PE_Accessibility_Check_Failed),
+ Suppress => Access_Check);
+
+ return;
+ end if;
+
+ Discr := First_Discriminant (Typ);
+ Discr_Elmt := First_Elmt (Discriminant_Constraint (Exp_Typ));
+
+ while Present (Discr) loop
+ if Is_Anonymous_Access_Type (Etype (Discr)) then
+ Discr_Exp := Node (Discr_Elmt);
+
+ -- The accessibility level of a function call whose result type is
+ -- an anonymous access type used to define the discriminant of an
+ -- object is the level of the object (RM 3.10.2(10.3, 14.1)).
+
+ if Nkind (Original_Node (Discr_Exp)) = N_Function_Call
+ and then
+ Is_Anonymous_Access_Type (Etype (Original_Node (Discr_Exp)))
+ then
+ null;
+
+ else
+ Insert_Action (N,
+ Make_Raise_Program_Error (Loc,
+ Condition =>
+ Make_Op_Gt (Loc,
+ Left_Opnd =>
+ Accessibility_Level (Discr_Exp, Dynamic_Level),
+ Right_Opnd => Accessibility_Level (N, Dynamic_Level)),
+ Reason => PE_Accessibility_Check_Failed),
+ Suppress => Access_Check);
+ end if;
+ end if;
+
+ Next_Discriminant (Discr);
+ Next_Elmt (Discr_Elmt);
+ end loop;
+ end Apply_Accessibility_Check_For_Discriminated_Allocator;
+
--------------------------------------------------------
-- Apply_Accessibility_Check_For_Discriminated_Return --
--------------------------------------------------------
@@ -1389,18 +1484,11 @@ package body Accessibility is
procedure Apply_Accessibility_Check_For_Discriminated_Return
(Exp : Node_Id; Func : Entity_Id)
is
- Loc : constant Source_Ptr := Sloc (Exp);
-
function Constraint_Bearing_Subtype_If_Any
(Exp : Node_Id) return Node_Id;
-- If we can locate a constrained subtype whose constraint applies
-- to Exp, then return that. Otherwise, return Etype (Exp).
- function Discr_Expression
- (Typ : Entity_Id; Discr_Index : Positive) return Node_Id;
- -- Typ is a constrained discriminated subtype.
- -- Return the constraint expression for the indexed discriminant.
-
---------------------------------------
-- Constraint_Bearing_Subtype_If_Any --
---------------------------------------
@@ -1448,31 +1536,11 @@ package body Accessibility is
return Etype (Exp);
end Constraint_Bearing_Subtype_If_Any;
- ----------------------
- -- Discr_Expression --
- ----------------------
-
- function Discr_Expression
- (Typ : Entity_Id; Discr_Index : Positive) return Node_Id
- is
- Constraint_Elmt : Elmt_Id :=
- First_Elmt (Discriminant_Constraint (Typ));
- begin
- for Skip in 1 .. Discr_Index - 1 loop
- Next_Elmt (Constraint_Elmt);
- end loop;
-
- return Node (Constraint_Elmt);
- end Discr_Expression;
-
-- Local variables
- Constrained_Subtype : constant Entity_Id :=
- Constraint_Bearing_Subtype_If_Any (Exp);
-
- Discr : Entity_Id := First_Discriminant (Etype (Func));
- Discr_Index : Positive := 1;
- Discr_Exp : Node_Id;
+ Discr : Entity_Id;
+ Discr_Elmt : Elmt_Id;
+ Exp_Typ : Entity_Id;
-- Start of Apply_Accessibility_Check_For_Discriminated_Return
@@ -1486,14 +1554,12 @@ package body Accessibility is
if Ada_Version <= Ada_95 then
return;
- end if;
- -- If we are returning a function call then that function will
- -- perform the needed check.
+ -- If we are returning a function result, then that function will
+ -- perform the check.
- if Nkind (Unqualify (Exp)) = N_Function_Call then
+ elsif Nkind (Unqualify (Exp)) = N_Function_Call then
return;
- end if;
-- ??? Cope with the consequences of the Disable_Tagged_Cases flag
-- in accessibility.adb (which can cause the extra formal parameter
@@ -1502,33 +1568,33 @@ package body Accessibility is
-- prevent generation of a required check (or even a required
-- legality check - see "statically too deep" check below).
- if No (Extra_Accessibility_Of_Result (Func)) then
+ elsif No (Extra_Accessibility_Of_Result (Func)) then
return;
end if;
- Remove_Side_Effects (Exp);
+ Exp_Typ := Constraint_Bearing_Subtype_If_Any (Exp);
+
+ -- When the value of the access discriminant is determined by
+ -- an object with an unconstrained nominal subtype, its level
+ -- is the accessibility level of the object (RM 3.10.2(12.4)).
+
+ if not Is_Constrained (Exp_Typ) then
+ Apply_Accessibility_Check_For_Anonymous_Return (Exp, Func, Exp);
+
+ return;
+ end if;
+
+ Discr := First_Discriminant (Etype (Func));
+ Discr_Elmt := First_Elmt (Discriminant_Constraint (Exp_Typ));
while Present (Discr) loop
if Is_Anonymous_Access_Type (Etype (Discr)) then
- if Is_Constrained (Constrained_Subtype) then
- Discr_Exp :=
- New_Copy_Tree
- (Discr_Expression (Constrained_Subtype, Discr_Index));
- else
- Discr_Exp :=
- Make_Selected_Component (Loc,
- Prefix => New_Copy_Tree (Exp),
- Selector_Name => New_Occurrence_Of (Discr, Loc));
- end if;
-
- Analyze (Discr_Exp);
-
Apply_Accessibility_Check_For_Anonymous_Return
- (Discr_Exp, Func, Exp);
+ (Node (Discr_Elmt), Func, Exp);
end if;
Next_Discriminant (Discr);
- Discr_Index := Discr_Index + 1;
+ Next_Elmt (Discr_Elmt);
end loop;
end Apply_Accessibility_Check_For_Discriminated_Return;
@@ -1654,7 +1720,7 @@ package body Accessibility is
Typ : constant Entity_Id := Etype (Func);
begin
- -- Return immediately if accessiblity checks are suppressed for Func
+ -- Return immediately if accessibility checks are suppressed for Func
if Accessibility_Checks_Suppressed (Func) then
return;
@@ -1675,13 +1741,13 @@ package body Accessibility is
Apply_Accessibility_Check_For_Class_Wide_Return (Exp, Func);
-- Check that the access result does not designate an entity that
- -- the function result could outlive.
+ -- the result could outlive.
elsif Ekind (Typ) = E_Anonymous_Access_Type then
Apply_Accessibility_Check_For_Anonymous_Return (Exp, Func, Exp);
- -- Check that result's access discriminants (if any) do not designate
- -- entities that the function result could outlive.
+ -- Check that the result's access discriminants do not designate
+ -- entities that the result could outlive (RM 6.5(21)).
elsif Has_Anonymous_Access_Discriminant (Typ) then
Apply_Accessibility_Check_For_Discriminated_Return (Exp, Func);
diff --git a/gcc/ada/accessibility.ads b/gcc/ada/accessibility.ads
index 958d5f6375b..6790864d7d7 100644
--- a/gcc/ada/accessibility.ads
+++ b/gcc/ada/accessibility.ads
@@ -71,7 +71,7 @@ package Accessibility is
-- The Allow_Alt_Model parameter allows the alternative level calculation
-- under the restriction No_Dynamic_Accessibility_Checks to be performed.
- procedure Apply_Accessibility_Check_For_Allocator
+ procedure Apply_Accessibility_Check_For_Class_Wide_Allocator
(N : Node_Id;
Exp : Node_Id;
Ref : Node_Id;
@@ -111,6 +111,13 @@ package Accessibility is
-- type of the object is not deeper than the level of Typ. Insert_Node
-- indicates the node where the check should be inserted.
+ procedure Apply_Accessibility_Check_For_Discriminated_Allocator
+ (N : Node_Id);
+ -- If the subtype determined by the subtype indication or the qualified
+ -- expression of an allocator N has access discriminants, insert checks
+ -- that the accessibility level of each entity designated by an access
+ -- discriminant is not deeper than the level of the allocator.
+
procedure Apply_Accessibility_Check_For_Return
(Exp : Node_Id;
Func : Entity_Id);
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index 52826388282..7279fe3cf76 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -794,6 +794,10 @@ package body Exp_Ch4 is
return;
end if;
+ -- Apply accessibility checks if access discriminants are present
+
+ Apply_Accessibility_Check_For_Discriminated_Allocator (N);
+
-- If we have:
-- type A is access T1;
-- X : A := new T2'(...);
@@ -858,7 +862,7 @@ package body Exp_Ch4 is
if Is_Build_In_Place_Function_Call (Exp) then
Make_Build_In_Place_Call_In_Allocator (N, Exp);
- Apply_Accessibility_Check_For_Allocator
+ Apply_Accessibility_Check_For_Class_Wide_Allocator
(N, Exp, N, Built_In_Place => True);
return;
@@ -871,7 +875,7 @@ package body Exp_Ch4 is
elsif Present (Unqual_BIP_Iface_Function_Call (Exp)) then
Make_Build_In_Place_Iface_Call_In_Allocator (N, Exp);
- Apply_Accessibility_Check_For_Allocator
+ Apply_Accessibility_Check_For_Class_Wide_Allocator
(N, Exp, N, Built_In_Place => True);
return;
end if;
@@ -1100,7 +1104,7 @@ package body Exp_Ch4 is
-- Note: the accessibility check must be inserted after the call to
-- [Deep_]Adjust to ensure proper completion of the assignment.
- Apply_Accessibility_Check_For_Allocator (N, Exp, Temp);
+ Apply_Accessibility_Check_For_Class_Wide_Allocator (N, Exp, Temp);
-- Case of aggregate built in place
@@ -4863,6 +4867,10 @@ package body Exp_Ch4 is
-- that tasks get activated (see Build_Task_Allocate_Block for details).
else
+ -- Apply accessibility checks if access discriminants are present
+
+ Apply_Accessibility_Check_For_Discriminated_Allocator (N);
+
-- Apply constraint checks against designated subtype (RM 4.8(10/2)).
-- Discriminant checks will be generated by the expansion below.
--
2.53.0