[Ada] Reimplementation of accessibility checking

gcc/ada/

	* checks.adb (Apply_Accessibility_Check): Modify condition to
	avoid flawed optimization and use Get_Accessibility over
	Extra_Accessibility.
	* exp_attr.adb: Remove inclusion of Exp_Ch2.adb.
	* exp_ch2.adb, exp_ch2.ads (Param_Entity): Moved to sem_util.
	* exp_ch3.ads (Init_Proc_Level_Formal): New function.
	* exp_ch3.adb (Build_Init_Procedure): Add extra accessibility
	formal for init procs when the associated type is a limited
	record.
	(Build_Initialization_Call): Add condition to handle propagation
	of the new extra accessibility paramter actual needed for init
	procs.
	(Init_Proc_Level_Formal): Created to fetch a the extra
	accessibility parameter associated with init procs if one
	exists.
	* exp_ch4.adb (Build_Attribute_Reference): Modify static check
	to be dynamic.
	* exp_ch6.adb (Add_Cond_Expression_Extra_Actual): Move logic
	used to expand conditional expressions used as actuals for
	anonymous access formals.
	(Expand_Call_Helper): Remove extranious accessibility
	calculation logic.
	* exp_util.adb: Remove inclusion of Exp_Ch2.adb.
	* par-ch3.adb (P_Array_Type_Definition): Properly set
	Aliased_Present on access definitions
	* sem_attr.adb (Resolve_Attribute): Replace instances for
	Object_Access_Level with Static_Accessibility_Level.
	* sem_ch13.adb (Storage_Pool): Replace instances for
	Object_Access_Level with Static_Accessibility_Level.
	* sem_ch6.adb (Check_Return_Construct_Accessibility): Replace
	instances for Object_Access_Level with
	Static_Accessibility_Level.
	* sem_ch9.adb (Analyze_Requeue): Replace instances for
	Object_Access_Level with Static_Accessibility_Level.
	* sem_res.adb (Check_Aliased_Parameter,
	Check_Allocator_Discrim_Accessibility, Valid_Conversion):
	Replace instances for Object_Access_Level with
	Static_Accessibility_Level.
	* sem_util.adb, sem_util.ads (Accessibility_Level_Helper):
	Created to centralize calculation of accessibility levels.
	(Build_Component_Subtype): Replace instances for
	Object_Access_Level with Static_Accessibility_Level.
	(Defining_Entity): Add extra parameter to dictate whether an
	error is raised or empty is return in the case of an irrelevant
	N.
	(Dynamic_Accessibility_Level): Rewritten to use
	Accessibility_Level_Helper.
	(Is_View_Conversion): Check membership against Etype to capture
	nodes like explicit dereferences which have types but are not
	expanded names or identifers.
	(Object_Access_LeveL): Removed.
	(Param_Entity): Moved from sem_util.
	(Static_Accessibility_Level): Created as a replacement to
	Object_Access_Level, it also uses Accessibility_Level_Helper for
	its implementation.
	* snames.ads-tmpl: Added new name for extra accessibility
	parameter in init procs.
This commit is contained in:
Justin Squirek 2020-08-10 12:05:07 -04:00 committed by Pierre-Marie de Rodat
parent cda800dd90
commit d7e2013065
18 changed files with 994 additions and 1312 deletions

View File

@ -30,7 +30,6 @@ with Einfo; use Einfo;
with Elists; use Elists;
with Eval_Fat; use Eval_Fat;
with Exp_Ch11; use Exp_Ch11;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch4; use Exp_Ch4;
with Exp_Pakd; use Exp_Pakd;
with Exp_Util; use Exp_Util;
@ -602,19 +601,16 @@ package body Checks is
return;
-- Only apply the run-time check if the access parameter has an
-- associated extra access level parameter and when the level of the
-- type is less deep than the level of the access parameter, and
-- accessibility checks are not suppressed.
-- associated extra access level parameter and when accessibility checks
-- are enabled.
elsif Present (Param_Ent)
and then Present (Extra_Accessibility (Param_Ent))
and then UI_Gt (Object_Access_Level (N),
Deepest_Type_Access_Level (Typ))
and then Present (Get_Accessibility (Param_Ent))
and then not Accessibility_Checks_Suppressed (Param_Ent)
and then not Accessibility_Checks_Suppressed (Typ)
then
Param_Level :=
New_Occurrence_Of (Extra_Accessibility (Param_Ent), Loc);
New_Occurrence_Of (Get_Accessibility (Param_Ent), Loc);
-- Use the dynamic accessibility parameter for the function's result
-- when one has been created instead of statically referring to the

View File

@ -29,7 +29,6 @@ with Checks; use Checks;
with Einfo; use Einfo;
with Elists; use Elists;
with Exp_Atag; use Exp_Atag;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch9; use Exp_Ch9;

View File

@ -717,98 +717,4 @@ package body Exp_Ch2 is
Analyze_And_Resolve (N, T);
end Expand_Renaming;
------------------
-- Param_Entity --
------------------
-- This would be trivial, simply a test for an identifier that was a
-- reference to a formal, if it were not for the fact that a previous call
-- to Expand_Entry_Parameter will have modified the reference to the
-- identifier. A formal of a protected entity is rewritten as
-- typ!(recobj).rec.all'Constrained
-- where rec is a selector whose Entry_Formal link points to the formal
-- If the type of the entry parameter has a representation clause, then an
-- extra temp is involved (see below).
-- For a formal of a task entity, the formal is rewritten as a local
-- renaming.
-- In addition, a formal that is marked volatile because it is aliased
-- through an address clause is rewritten as dereference as well.
function Param_Entity (N : Node_Id) return Entity_Id is
Renamed_Obj : Node_Id;
begin
-- Simple reference case
if Nkind (N) in N_Identifier | N_Expanded_Name then
if Is_Formal (Entity (N)) then
return Entity (N);
-- Handle renamings of formal parameters and formals of tasks that
-- are rewritten as renamings.
elsif Nkind (Parent (Entity (N))) = N_Object_Renaming_Declaration then
Renamed_Obj := Get_Referenced_Object (Renamed_Object (Entity (N)));
if Is_Entity_Name (Renamed_Obj)
and then Is_Formal (Entity (Renamed_Obj))
then
return Entity (Renamed_Obj);
elsif
Nkind (Parent (Parent (Entity (N)))) = N_Accept_Statement
then
return Entity (N);
end if;
end if;
else
if Nkind (N) = N_Explicit_Dereference then
declare
P : Node_Id := Prefix (N);
S : Node_Id;
E : Entity_Id;
Decl : Node_Id;
begin
-- If the type of an entry parameter has a representation
-- clause, then the prefix is not a selected component, but
-- instead a reference to a temp pointing at the selected
-- component. In this case, set P to be the initial value of
-- that temp.
if Nkind (P) = N_Identifier then
E := Entity (P);
if Ekind (E) = E_Constant then
Decl := Parent (E);
if Nkind (Decl) = N_Object_Declaration then
P := Expression (Decl);
end if;
end if;
end if;
if Nkind (P) = N_Selected_Component then
S := Selector_Name (P);
if Present (Entry_Formal (Entity (S))) then
return Entry_Formal (Entity (S));
end if;
elsif Nkind (Original_Node (N)) = N_Identifier then
return Param_Entity (Original_Node (N));
end if;
end;
end if;
end if;
return (Empty);
end Param_Entity;
end Exp_Ch2;

View File

@ -32,14 +32,4 @@ package Exp_Ch2 is
procedure Expand_N_Identifier (N : Node_Id);
procedure Expand_N_Real_Literal (N : Node_Id);
function Param_Entity (N : Node_Id) return Entity_Id;
-- Given an expression N, determines if the expression is a reference
-- to a formal (of a subprogram or entry), and if so returns the Id
-- of the corresponding formal entity, otherwise returns Empty. The
-- reason that this is in Exp_Ch2 is that it has to deal with the case
-- where the reference is to an entry formal, and has been expanded
-- already. Since Exp_Ch2 is in charge of the expansion, it is best
-- suited to knowing how to detect this case. Also handles the case
-- of references to renamings of formals.
end Exp_Ch2;

View File

@ -1335,6 +1335,31 @@ package body Exp_Ch3 is
return Agg;
end Build_Equivalent_Record_Aggregate;
----------------------------
-- Init_Proc_Level_Formal --
----------------------------
function Init_Proc_Level_Formal (Proc : Entity_Id) return Entity_Id is
Form : Entity_Id;
begin
-- Move through the formals of the initialization procedure Proc to find
-- the extra accessibility level parameter associated with the object
-- being initialized.
Form := First_Formal (Proc);
while Present (Form) loop
if Chars (Form) = Name_uInit_Level then
return Form;
end if;
Next_Formal (Form);
end loop;
-- No formal was found, return Empty
return Empty;
end Init_Proc_Level_Formal;
-------------------------------
-- Build_Initialization_Call --
-------------------------------
@ -1772,6 +1797,24 @@ package body Exp_Ch3 is
New_Copy_List (Parameter_Associations (Constructor_Ref)));
end if;
-- Pass the extra accessibility level parameter associated with the
-- level of the object being initialized when required.
-- When no entity is present for Id_Ref it may not have been fully
-- analyzed, so allow the default value of standard standard to be
-- passed ???
if Is_Entity_Name (Id_Ref)
and then Present (Init_Proc_Level_Formal (Proc))
then
Append_To (Args,
Make_Parameter_Association (Loc,
Selector_Name =>
Make_Identifier (Loc, Name_uInit_Level),
Explicit_Actual_Parameter =>
Dynamic_Accessibility_Level (Id_Ref)));
end if;
Append_To (Res,
Make_Procedure_Call_Statement (Loc,
Name => New_Occurrence_Of (Proc, Loc),
@ -2513,6 +2556,21 @@ package body Exp_Ch3 is
New_Occurrence_Of (Standard_True, Loc)));
end if;
-- Create an extra accessibility parameter to capture the level of
-- the object being initialized when its type is a limited record.
if Is_Limited_Record (Rec_Type) then
Append_To (Parameters,
Make_Parameter_Specification (Loc,
Defining_Identifier => Make_Defining_Identifier
(Loc, Name_uInit_Level),
Parameter_Type =>
New_Occurrence_Of (Standard_Natural, Loc),
Expression =>
Make_Integer_Literal
(Loc, Scope_Depth (Standard_Standard))));
end if;
Set_Parameter_Specifications (Proc_Spec_Node, Parameters);
Set_Specification (Body_Node, Proc_Spec_Node);
Set_Declarations (Body_Node, Decls);
@ -7449,7 +7507,8 @@ package body Exp_Ch3 is
if No (Expr) then
Level_Expr :=
Make_Integer_Literal (Loc, Scope_Depth (Standard_Standard));
Make_Integer_Literal
(Loc, Scope_Depth (Standard_Standard));
-- When the expression of the object is a function which returns
-- an anonymous access type the master of the call is the object
@ -7459,7 +7518,7 @@ package body Exp_Ch3 is
and then Ekind (Etype (Name (Expr))) = E_Anonymous_Access_Type
then
Level_Expr := Make_Integer_Literal (Loc,
Object_Access_Level (Def_Id));
Static_Accessibility_Level (Def_Id));
-- General case
@ -8143,7 +8202,8 @@ package body Exp_Ch3 is
-- It is known that the accessibility level of the access
-- type is deeper than that of the pool.
if Type_Access_Level (Def_Id) > Object_Access_Level (Pool)
if Type_Access_Level (Def_Id)
> Static_Accessibility_Level (Pool)
and then Is_Class_Wide_Type (Etype (Pool))
and then not Accessibility_Checks_Suppressed (Def_Id)
and then not Accessibility_Checks_Suppressed (Pool)

View File

@ -135,6 +135,11 @@ package Exp_Ch3 is
-- type is valid only when Normalize_Scalars or Initialize_Scalars is
-- active, or if N is the node for a 'Invalid_Value attribute node.
function Init_Proc_Level_Formal (Proc : Entity_Id) return Entity_Id;
-- Fetch the extra formal from an initalization procedure "proc"
-- corresponding to the level of the object being initialized. When none
-- is present Empty is returned.
procedure Init_Secondary_Tags
(Typ : Entity_Id;
Target : Node_Id;

View File

@ -31,7 +31,6 @@ with Elists; use Elists;
with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr;
with Exp_Atag; use Exp_Atag;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
@ -6867,37 +6866,27 @@ package body Exp_Ch4 is
-- Apply an accessibility check if the access object has an
-- associated access level and when the level of the type is
-- less deep than the level of the access parameter. This
-- only occur for access parameters and stand-alone objects
-- of an anonymous access type.
-- can only occur for access parameters and stand-alone
-- objects of an anonymous access type.
else
if Present (Expr_Entity)
and then
Present
(Effective_Extra_Accessibility (Expr_Entity))
and then UI_Gt (Object_Access_Level (Lop),
Type_Access_Level (Rtyp))
then
Param_Level :=
New_Occurrence_Of
(Effective_Extra_Accessibility (Expr_Entity), Loc);
Param_Level := Dynamic_Accessibility_Level (Expr_Entity);
Type_Level :=
Make_Integer_Literal (Loc, Type_Access_Level (Rtyp));
Type_Level :=
Make_Integer_Literal (Loc, Type_Access_Level (Rtyp));
-- Return True only if the accessibility level of the
-- expression entity is not deeper than the level of
-- the tested access type.
-- Return True only if the accessibility level of the
-- expression entity is not deeper than the level of
-- the tested access type.
Rewrite (N,
Make_And_Then (Loc,
Left_Opnd => Relocate_Node (N),
Right_Opnd => Make_Op_Le (Loc,
Left_Opnd => Param_Level,
Right_Opnd => Type_Level)));
Rewrite (N,
Make_And_Then (Loc,
Left_Opnd => Relocate_Node (N),
Right_Opnd => Make_Op_Le (Loc,
Left_Opnd => Param_Level,
Right_Opnd => Type_Level)));
Analyze_And_Resolve (N);
end if;
Analyze_And_Resolve (N);
-- If the designated type is tagged, do tagged membership
-- operation.
@ -12296,7 +12285,7 @@ package body Exp_Ch4 is
and then Ekind (Operand_Type) = E_Anonymous_Access_Type
and then Nkind (Operand) = N_Selected_Component
and then Ekind (Entity (Selector_Name (Operand))) = E_Discriminant
and then Object_Access_Level (Operand) >
and then Static_Accessibility_Level (Operand) >
Type_Access_Level (Target_Type)
then
Raise_Accessibility_Error;

View File

@ -34,7 +34,6 @@ with Elists; use Elists;
with Expander; use Expander;
with Exp_Aggr; use Exp_Aggr;
with Exp_Atag; use Exp_Atag;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch3; use Exp_Ch3;
with Exp_Ch7; use Exp_Ch7;
with Exp_Ch9; use Exp_Ch9;
@ -1807,13 +1806,7 @@ package body Exp_Ch6 is
pragma Assert (Ada_Version >= Ada_2012);
if Type_Access_Level (E_Formal) >
Object_Access_Level (Lhs)
then
Append_To (Post_Call,
Make_Raise_Program_Error (Loc,
Reason => PE_Accessibility_Check_Failed));
end if;
Apply_Accessibility_Check (Lhs, E_Formal, N);
Append_To (Post_Call,
Make_Assignment_Statement (Loc,
@ -2782,6 +2775,15 @@ package body Exp_Ch6 is
-- default parameters and for extra actuals (for Extra_Formals). The
-- argument is an N_Parameter_Association node.
procedure Add_Cond_Expression_Extra_Actual (Formal : Entity_Id);
-- Adds extra accessibility actuals in the case of a conditional
-- expression corresponding to Formal.
-- Note: Conditional expressions used as actuals for anonymous access
-- formals complicate the process of propagating extra accessibility
-- actuals and must be handled in a recursive fashion since they can
-- be embedded within each other.
procedure Add_Extra_Actual (Expr : Node_Id; EF : Entity_Id);
-- Adds an extra actual to the list of extra actuals. Expr is the
-- expression for the value of the actual, EF is the entity for the
@ -2869,6 +2871,219 @@ package body Exp_Ch6 is
Prev := Actual_Expr;
end Add_Actual_Parameter;
--------------------------------------
-- Add_Cond_Expression_Extra_Actual --
--------------------------------------
procedure Add_Cond_Expression_Extra_Actual
(Formal : Entity_Id)
is
Decl : Node_Id;
-- Suppress warning for the final removal loop
pragma Warnings (Off, Decl);
Lvl : Entity_Id;
Res : Entity_Id;
Temp : Node_Id;
Typ : Node_Id;
procedure Insert_Level_Assign (Branch : Node_Id);
-- Recursivly add assignment of the level temporary on each branch
-- while moving through nested conditional expressions.
-------------------------
-- Insert_Level_Assign --
-------------------------
procedure Insert_Level_Assign (Branch : Node_Id) is
procedure Expand_Branch (Res_Assn : Node_Id);
-- Perform expansion or iterate further within nested
-- conditionals given the object declaration or assignment to
-- result object created during expansion which represents a
-- branch of the conditional expression.
-------------------
-- Expand_Branch --
-------------------
procedure Expand_Branch (Res_Assn : Node_Id) is
begin
pragma Assert (Nkind (Res_Assn) in
N_Assignment_Statement |
N_Object_Declaration);
-- There are more nested conditional expressions so we must go
-- deeper.
if Nkind (Expression (Res_Assn)) =
N_Expression_With_Actions
and then
Nkind
(Original_Node (Expression (Res_Assn)))
in N_Case_Expression | N_If_Expression
then
Insert_Level_Assign
(Expression (Res_Assn));
-- Add the level assignment
else
Insert_Before_And_Analyze (Res_Assn,
Make_Assignment_Statement (Loc,
Name =>
New_Occurrence_Of
(Lvl, Loc),
Expression =>
Dynamic_Accessibility_Level
(Expression (Res_Assn))));
end if;
end Expand_Branch;
Cond : Node_Id;
Alt : Node_Id;
-- Start of processing for Insert_Level_Assign
begin
-- Examine further nested condtionals
pragma Assert (Nkind (Branch) =
N_Expression_With_Actions);
-- Find the relevant statement in the actions
Cond := First (Actions (Branch));
while Present (Cond) loop
exit when Nkind (Cond) in
N_Case_Statement | N_If_Statement;
Next (Cond);
end loop;
-- The conditional expression may have been optimized away, so
-- examine the actions in the branch.
if No (Cond) then
Expand_Branch (Last (Actions (Branch)));
-- Iterate through if expression branches
elsif Nkind (Cond) = N_If_Statement then
Expand_Branch (Last (Then_Statements (Cond)));
Expand_Branch (Last (Else_Statements (Cond)));
-- Iterate through case alternatives
elsif Nkind (Cond) = N_Case_Statement then
Alt := First (Alternatives (Cond));
while Present (Alt) loop
Expand_Branch (Last (Statements (Alt)));
Next (Alt);
end loop;
end if;
end Insert_Level_Assign;
-- Start of processing for cond expression case
begin
-- Create declaration of a temporary to store the accessibility
-- level of each branch of the conditional expression.
Lvl := Make_Temporary (Loc, 'L');
Decl := Make_Object_Declaration (Loc,
Defining_Identifier => Lvl,
Object_Definition =>
New_Occurrence_Of (Standard_Natural, Loc));
-- Install the declaration and perform necessary expansion if we
-- are dealing with a function call.
if Nkind (Call_Node) = N_Procedure_Call_Statement then
-- Generate:
-- Lvl : Natural;
-- Call (
-- {do
-- If_Exp_Res : Typ;
-- if Cond then
-- Lvl := 0; -- Access level
-- If_Exp_Res := Exp;
-- ...
-- in If_Exp_Res end;},
-- Lvl,
-- ...
-- )
Insert_Before_And_Analyze (Call_Node, Decl);
-- A function call must be transformed into an expression with
-- actions.
else
-- Generate:
-- do
-- Lvl : Natural;
-- in Call (do{
-- If_Exp_Res : Typ
-- if Cond then
-- Lvl := 0; -- Access level
-- If_Exp_Res := Exp;
-- in If_Exp_Res end;},
-- Lvl,
-- ...
-- )
-- end;
Res := Make_Temporary (Loc, 'R');
Typ := Etype (Call_Node);
Temp := Relocate_Node (Call_Node);
-- Perform the rewrite with the dummy
Rewrite (Call_Node,
Make_Expression_With_Actions (Loc,
Expression => New_Occurrence_Of (Res, Loc),
Actions => New_List (
Decl,
Make_Object_Declaration (Loc,
Defining_Identifier => Res,
Object_Definition =>
New_Occurrence_Of (Typ, Loc)))));
-- Analyze the expression with the dummy
Analyze_And_Resolve (Call_Node, Typ);
-- Properly set the expression and move our view of the call node
Set_Expression (Call_Node, Relocate_Node (Temp));
Call_Node := Expression (Call_Node);
-- Remove the declaration of the dummy and the subsequent actions
-- its analysis has created.
while Present (Remove_Next (Decl)) loop
null;
end loop;
end if;
-- Decorate the conditional expression with assignments to our level
-- temporary.
Insert_Level_Assign (Prev);
-- Make our level temporary the passed actual
Add_Extra_Actual
(Expr => New_Occurrence_Of (Lvl, Loc),
EF => Extra_Accessibility (Formal));
end Add_Cond_Expression_Extra_Actual;
----------------------
-- Add_Extra_Actual --
----------------------
@ -3300,7 +3515,6 @@ package body Exp_Ch6 is
Param_Count : Positive;
Parent_Formal : Entity_Id;
Parent_Subp : Entity_Id;
Prev_Ult : Node_Id;
Scop : Entity_Id;
Subp : Entity_Id;
@ -3751,417 +3965,20 @@ package body Exp_Ch6 is
EF => Extra_Accessibility (Formal));
end;
elsif Is_Entity_Name (Prev_Orig) then
-- Conditional expressions
-- When passing an access parameter, or a renaming of an access
-- parameter, as the actual to another access parameter we need
-- to pass along the actual's own access level parameter. This
-- is done if we are within the scope of the formal access
-- parameter (if this is an inlined body the extra formal is
-- irrelevant).
if (Is_Formal (Entity (Prev_Orig))
or else
(Present (Renamed_Object (Entity (Prev_Orig)))
and then
Is_Entity_Name (Renamed_Object (Entity (Prev_Orig)))
and then
Is_Formal
(Entity (Renamed_Object (Entity (Prev_Orig))))))
and then Ekind (Etype (Prev_Orig)) = E_Anonymous_Access_Type
and then In_Open_Scopes (Scope (Entity (Prev_Orig)))
then
declare
Parm_Ent : constant Entity_Id := Param_Entity (Prev_Orig);
begin
pragma Assert (Present (Parm_Ent));
if Present (Get_Accessibility (Parm_Ent)) then
Add_Extra_Actual
(Expr =>
New_Occurrence_Of
(Get_Accessibility (Parm_Ent), Loc),
EF => Extra_Accessibility (Formal));
-- If the actual access parameter does not have an
-- associated extra formal providing its scope level,
-- then treat the actual as having library-level
-- accessibility.
else
Add_Extra_Actual
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Standard_Standard)),
EF => Extra_Accessibility (Formal));
end if;
end;
-- The actual is a normal access value, so just pass the level
-- of the actual's access type.
else
Add_Extra_Actual
(Expr => Dynamic_Accessibility_Level (Prev_Orig),
EF => Extra_Accessibility (Formal));
end if;
-- If the actual is an access discriminant, then pass the level
-- of the enclosing object (RM05-3.10.2(12.4/2)).
elsif Nkind (Prev_Orig) = N_Selected_Component
and then Ekind (Entity (Selector_Name (Prev_Orig))) =
E_Discriminant
and then Ekind (Etype (Entity (Selector_Name (Prev_Orig)))) =
E_Anonymous_Access_Type
elsif Nkind (Prev) = N_Expression_With_Actions
and then Nkind (Original_Node (Prev)) in
N_If_Expression | N_Case_Expression
then
Add_Extra_Actual
(Expr =>
Make_Integer_Literal (Loc,
Intval => Object_Access_Level (Prefix (Prev_Orig))),
EF => Extra_Accessibility (Formal));
Add_Cond_Expression_Extra_Actual (Formal);
-- All other cases
-- Normal case
else
case Nkind (Prev_Orig) is
when N_Attribute_Reference =>
case Get_Attribute_Id (Attribute_Name (Prev_Orig)) is
-- Ignore 'Result, 'Loop_Entry, and 'Old as they can
-- be used to identify access objects and do not have
-- an effect on accessibility level.
when Attribute_Loop_Entry
| Attribute_Old
| Attribute_Result
=>
null;
-- For X'Access, pass on the level of the prefix X
when Attribute_Access =>
-- Accessibility level of S'Access is that of A
Prev_Orig := Prefix (Prev_Orig);
-- If the expression is a view conversion, the
-- accessibility level is that of the expression.
if Nkind (Original_Node (Prev_Orig)) =
N_Type_Conversion
and then
Nkind (Expression (Original_Node (Prev_Orig))) =
N_Explicit_Dereference
then
Prev_Orig :=
Expression (Original_Node (Prev_Orig));
end if;
-- Obtain the ultimate prefix so we can check for
-- the case where we are taking 'Access of a
-- component of an anonymous access formal - which
-- would mean we need to pass said formal's
-- corresponding extra accessibility formal.
Prev_Ult := Ultimate_Prefix (Prev_Orig);
if Is_Entity_Name (Prev_Ult)
and then not Is_Type (Entity (Prev_Ult))
and then Present
(Get_Accessibility
(Entity (Prev_Ult)))
then
Add_Extra_Actual
(Expr =>
New_Occurrence_Of
(Get_Accessibility
(Entity (Prev_Ult)), Loc),
EF => Extra_Accessibility (Formal));
-- Normal case, call Object_Access_Level. Note:
-- should be Dynamic_Accessibility_Level ???
else
Add_Extra_Actual
(Expr =>
Make_Integer_Literal (Loc,
Intval =>
Object_Access_Level (Prev_Orig)),
EF => Extra_Accessibility (Formal));
end if;
-- Treat the unchecked attributes as library-level
when Attribute_Unchecked_Access
| Attribute_Unrestricted_Access
=>
Add_Extra_Actual
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Standard_Standard)),
EF => Extra_Accessibility (Formal));
-- No other cases of attributes returning access
-- values that can be passed to access parameters.
when others =>
raise Program_Error;
end case;
-- For allocators we pass the level of the execution of the
-- called subprogram, which is one greater than the current
-- scope level. However, according to RM 3.10.2(14/3) this
-- is wrong since for an anonymous allocator defining the
-- value of an access parameter, the accessibility level is
-- that of the innermost master of the call???
when N_Allocator =>
Add_Extra_Actual
(Expr =>
Make_Integer_Literal (Loc,
Intval => Scope_Depth (Current_Scope) + 1),
EF => Extra_Accessibility (Formal));
-- For most other cases we simply pass the level of the
-- actual's access type. The type is retrieved from
-- Prev rather than Prev_Orig, because in some cases
-- Prev_Orig denotes an original expression that has
-- not been analyzed.
-- However, when the actual is wrapped in a conditional
-- expression we must add a local temporary to store the
-- level at each branch, and, possibly, expand the call
-- into an expression with actions.
when others =>
if Nkind (Prev) = N_Expression_With_Actions
and then Nkind (Original_Node (Prev)) in
N_If_Expression | N_Case_Expression
then
declare
Decl : Node_Id;
pragma Warnings (Off, Decl);
-- Suppress warning for the final removal loop
Lvl : Entity_Id;
Res : Entity_Id;
Temp : Node_Id;
Typ : Node_Id;
procedure Insert_Level_Assign (Branch : Node_Id);
-- Recursivly add assignment of the level temporary
-- on each branch while moving through nested
-- conditional expressions.
-------------------------
-- Insert_Level_Assign --
-------------------------
procedure Insert_Level_Assign (Branch : Node_Id) is
procedure Expand_Branch (Res_Assn : Node_Id);
-- Perform expansion or iterate further within
-- nested conditionals given the object
-- declaration or assignment to result object
-- created during expansion which represents
-- a branch of the conditional expression.
-------------------
-- Expand_Branch --
-------------------
procedure Expand_Branch (Res_Assn : Node_Id) is
begin
pragma Assert (Nkind (Res_Assn) in
N_Assignment_Statement |
N_Object_Declaration);
-- There are more nested conditional
-- expressions so we must go deeper.
if Nkind (Expression (Res_Assn)) =
N_Expression_With_Actions
and then
Nkind
(Original_Node (Expression (Res_Assn)))
in N_Case_Expression | N_If_Expression
then
Insert_Level_Assign
(Expression (Res_Assn));
-- Add the level assignment
else
Insert_Before_And_Analyze (Res_Assn,
Make_Assignment_Statement (Loc,
Name =>
New_Occurrence_Of
(Lvl, Loc),
Expression =>
Dynamic_Accessibility_Level
(Expression (Res_Assn))));
end if;
end Expand_Branch;
Cond : Node_Id;
Alt : Node_Id;
-- Start of processing for Insert_Level_Assign
begin
-- Examine further nested condtionals
pragma Assert (Nkind (Branch) =
N_Expression_With_Actions);
-- Find the relevant statement in the actions
Cond := First (Actions (Branch));
while Present (Cond) loop
exit when Nkind (Cond) in
N_Case_Statement | N_If_Statement;
Next (Cond);
end loop;
-- The conditional expression may have been
-- optimized away, so examine the actions in
-- the branch.
if No (Cond) then
Expand_Branch (Last (Actions (Branch)));
-- Iterate through if expression branches
elsif Nkind (Cond) = N_If_Statement then
Expand_Branch (Last (Then_Statements (Cond)));
Expand_Branch (Last (Else_Statements (Cond)));
-- Iterate through case alternatives
elsif Nkind (Cond) = N_Case_Statement then
Alt := First (Alternatives (Cond));
while Present (Alt) loop
Expand_Branch (Last (Statements (Alt)));
Next (Alt);
end loop;
end if;
end Insert_Level_Assign;
-- Start of processing for cond expression case
begin
-- Create declaration of a temporary to store the
-- accessibility level of each branch of the
-- conditional expression.
Lvl := Make_Temporary (Loc, 'L');
Decl :=
Make_Object_Declaration (Loc,
Defining_Identifier => Lvl,
Object_Definition =>
New_Occurrence_Of (Standard_Natural, Loc));
-- Install the declaration and perform necessary
-- expansion if we are dealing with a function
-- call.
if Nkind (Call_Node) = N_Procedure_Call_Statement
then
-- Generate:
-- Lvl : Natural;
-- Call (
-- {do
-- If_Exp_Res : Typ;
-- if Cond then
-- Lvl := 0; -- Access level
-- If_Exp_Res := Exp;
-- ...
-- in If_Exp_Res end;},
-- Lvl,
-- ...
-- )
Insert_Before_And_Analyze (Call_Node, Decl);
-- A function call must be transformed into an
-- expression with actions.
else
-- Generate:
-- do
-- Lvl : Natural;
-- in Call (do{
-- If_Exp_Res : Typ
-- if Cond then
-- Lvl := 0; -- Access level
-- If_Exp_Res := Exp;
-- in If_Exp_Res end;},
-- Lvl,
-- ...
-- )
-- end;
Res := Make_Temporary (Loc, 'R');
Typ := Etype (Call_Node);
Temp := Relocate_Node (Call_Node);
-- Perform the rewrite with the dummy
Rewrite (Call_Node,
Make_Expression_With_Actions (Loc,
Expression => New_Occurrence_Of (Res, Loc),
Actions => New_List (
Decl,
Make_Object_Declaration (Loc,
Defining_Identifier => Res,
Object_Definition =>
New_Occurrence_Of (Typ, Loc)))));
-- Analyze the expression with the dummy
Analyze_And_Resolve (Call_Node, Typ);
-- Properly set the expression and move our view
-- of the call node
Set_Expression (Call_Node, Relocate_Node (Temp));
Call_Node := Expression (Call_Node);
-- Remove the declaration of the dummy and the
-- subsequent actions its analysis has created.
while Present (Remove_Next (Decl)) loop
null;
end loop;
end if;
-- Decorate the conditional expression with
-- assignments to our level temporary.
Insert_Level_Assign (Prev);
-- Make our level temporary the passed actual
Add_Extra_Actual
(Expr => New_Occurrence_Of (Lvl, Loc),
EF => Extra_Accessibility (Formal));
end;
-- General case uncomplicated by conditional expressions
else
Add_Extra_Actual
(Expr => Dynamic_Accessibility_Level (Prev),
EF => Extra_Accessibility (Formal));
end if;
end case;
Add_Extra_Actual
(Expr => Dynamic_Accessibility_Level (Prev),
EF => Extra_Accessibility (Formal));
end if;
end if;
@ -4447,7 +4264,7 @@ package body Exp_Ch6 is
else
Level :=
Make_Integer_Literal (Loc,
Intval => Object_Access_Level (Def_Id));
Intval => Static_Accessibility_Level (Def_Id));
end if;
end;
@ -7838,190 +7655,8 @@ package body Exp_Ch6 is
if Is_Special_Aliased_Formal_Access (Exp, Scope_Id) then
Check_Against_Result_Level
(Make_Integer_Literal (Loc,
Object_Access_Level (Entity (Ultimate_Prefix (Prefix (Exp))))));
end if;
-- AI05-0234: Check unconstrained access discriminants to ensure
-- that the result does not outlive an object designated by one
-- of its discriminants (RM 6.5(21/3)).
if Present (Extra_Accessibility_Of_Result (Scope_Id))
and then Has_Unconstrained_Access_Discriminants (R_Type)
then
declare
Discrim_Source : Node_Id;
begin
Discrim_Source := Exp;
while Nkind (Discrim_Source) = N_Qualified_Expression loop
Discrim_Source := Expression (Discrim_Source);
end loop;
if Nkind (Discrim_Source) = N_Identifier
and then Is_Return_Object (Entity (Discrim_Source))
then
Discrim_Source := Entity (Discrim_Source);
if Is_Constrained (Etype (Discrim_Source)) then
Discrim_Source := Etype (Discrim_Source);
else
Discrim_Source := Expression (Parent (Discrim_Source));
end if;
elsif Nkind (Discrim_Source) = N_Identifier
and then Nkind (Original_Node (Discrim_Source)) in
N_Aggregate | N_Extension_Aggregate
then
Discrim_Source := Original_Node (Discrim_Source);
elsif Nkind (Discrim_Source) = N_Explicit_Dereference and then
Nkind (Original_Node (Discrim_Source)) = N_Function_Call
then
Discrim_Source := Original_Node (Discrim_Source);
end if;
Discrim_Source := Unqual_Conv (Discrim_Source);
case Nkind (Discrim_Source) is
when N_Defining_Identifier =>
pragma Assert (Is_Composite_Type (Discrim_Source)
and then Has_Discriminants (Discrim_Source)
and then Is_Constrained (Discrim_Source));
declare
Discrim : Entity_Id :=
First_Discriminant (Base_Type (R_Type));
Disc_Elmt : Elmt_Id :=
First_Elmt (Discriminant_Constraint
(Discrim_Source));
begin
loop
if Ekind (Etype (Discrim)) =
E_Anonymous_Access_Type
then
Check_Against_Result_Level
(Dynamic_Accessibility_Level (Node (Disc_Elmt)));
end if;
Next_Elmt (Disc_Elmt);
Next_Discriminant (Discrim);
exit when not Present (Discrim);
end loop;
end;
when N_Aggregate
| N_Extension_Aggregate
=>
-- Unimplemented: extension aggregate case where discrims
-- come from ancestor part, not extension part.
declare
Discrim : Entity_Id :=
First_Discriminant (Base_Type (R_Type));
Disc_Exp : Node_Id := Empty;
Positionals_Exhausted
: Boolean := not Present (Expressions
(Discrim_Source));
function Associated_Expr
(Comp_Id : Entity_Id;
Associations : List_Id) return Node_Id;
-- Given a component and a component associations list,
-- locate the expression for that component; returns
-- Empty if no such expression is found.
---------------------
-- Associated_Expr --
---------------------
function Associated_Expr
(Comp_Id : Entity_Id;
Associations : List_Id) return Node_Id
is
Assoc : Node_Id;
Choice : Node_Id;
begin
-- Simple linear search seems ok here
Assoc := First (Associations);
while Present (Assoc) loop
Choice := First (Choices (Assoc));
while Present (Choice) loop
if (Nkind (Choice) = N_Identifier
and then Chars (Choice) = Chars (Comp_Id))
or else (Nkind (Choice) = N_Others_Choice)
then
return Expression (Assoc);
end if;
Next (Choice);
end loop;
Next (Assoc);
end loop;
return Empty;
end Associated_Expr;
begin
if not Positionals_Exhausted then
Disc_Exp := First (Expressions (Discrim_Source));
end if;
loop
if Positionals_Exhausted then
Disc_Exp :=
Associated_Expr
(Discrim,
Component_Associations (Discrim_Source));
end if;
if Ekind (Etype (Discrim)) =
E_Anonymous_Access_Type
then
Check_Against_Result_Level
(Dynamic_Accessibility_Level (Disc_Exp));
end if;
Next_Discriminant (Discrim);
exit when not Present (Discrim);
if not Positionals_Exhausted then
Next (Disc_Exp);
Positionals_Exhausted := not Present (Disc_Exp);
end if;
end loop;
end;
when N_Function_Call =>
-- No check needed (check performed by callee)
null;
when others =>
declare
Level : constant Node_Id :=
Make_Integer_Literal (Loc,
Object_Access_Level (Discrim_Source));
begin
-- Unimplemented: check for name prefix that includes
-- a dereference of an access value with a dynamic
-- accessibility level (e.g., an access param or a
-- saooaaat) and use dynamic level in that case. For
-- example:
-- return Access_Param.all(Some_Index).Some_Component;
-- ???
Set_Etype (Level, Standard_Natural);
Check_Against_Result_Level (Level);
end;
end case;
end;
Static_Accessibility_Level
(Entity (Ultimate_Prefix (Prefix (Exp))))));
end if;
-- If we are returning a nonscalar object that is possibly unaligned,

View File

@ -32,7 +32,6 @@ with Einfo; use Einfo;
with Elists; use Elists;
with Errout; use Errout;
with Exp_Aggr; use Exp_Aggr;
with Exp_Ch2; use Exp_Ch2;
with Exp_Ch6; use Exp_Ch6;
with Exp_Ch7; use Exp_Ch7;
with Exp_Ch11; use Exp_Ch11;

View File

@ -2810,7 +2810,7 @@ package body Ch3 is
-- end if;
Set_Subtype_Indication (CompDef_Node, Empty);
Set_Aliased_Present (CompDef_Node, False);
Set_Aliased_Present (CompDef_Node, Aliased_Present);
Set_Access_Definition (CompDef_Node,
P_Access_Definition (Not_Null_Present));
else

View File

@ -11280,7 +11280,8 @@ package body Sem_Attr is
and then not Is_Special_Aliased_Formal_Access
(N, Current_Scope)
and then
Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp)
Static_Accessibility_Level (P) >
Deepest_Type_Access_Level (Btyp)
then
-- In an instance, this is a runtime check, but one we know
-- will fail, so generate an appropriate warning. As usual,
@ -11424,7 +11425,8 @@ package body Sem_Attr is
if Attr_Id /= Attribute_Unchecked_Access
and then Ekind (Btyp) = E_General_Access_Type
and then
Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp)
Static_Accessibility_Level (P)
> Deepest_Type_Access_Level (Btyp)
then
Accessibility_Message;
return;
@ -11445,7 +11447,8 @@ package body Sem_Attr is
-- anonymous_access_to_protected, there are no accessibility
-- checks either. Omit check entirely for Unrestricted_Access.
elsif Object_Access_Level (P) > Deepest_Type_Access_Level (Btyp)
elsif Static_Accessibility_Level (P)
> Deepest_Type_Access_Level (Btyp)
and then Comes_From_Source (N)
and then Ekind (Btyp) = E_Access_Protected_Subprogram_Type
and then Attr_Id /= Attribute_Unrestricted_Access

View File

@ -7208,7 +7208,9 @@ package body Sem_Ch13 is
-- check (B)
if Type_Access_Level (Ent) > Object_Access_Level (Pool) then
if Type_Access_Level (Ent)
> Static_Accessibility_Level (Pool)
then
Error_Msg_N
("subpool access type has deeper accessibility "
& "level than pool", Ent);

View File

@ -965,7 +965,7 @@ package body Sem_Ch6 is
-- special logic above, and call Object_Access_Level with
-- the original expression.
elsif Object_Access_Level (Expr) >
elsif Static_Accessibility_Level (Expr) >
Scope_Depth (Scope (Scope_Id))
then
Error_Msg_N
@ -1436,7 +1436,7 @@ package body Sem_Ch6 is
if (Ada_Version < Ada_2005 or else Debug_Flag_Dot_L)
and then Is_Limited_View (Etype (Scope_Id))
and then Object_Access_Level (Expr) >
and then Static_Accessibility_Level (Expr) >
Subprogram_Access_Level (Scope_Id)
then
-- Suppress the message in a generic, where the rewriting
@ -4718,7 +4718,7 @@ package body Sem_Ch6 is
Attribute_Name => Name_Min,
Expressions => New_List (
Make_Integer_Literal (Loc,
Object_Access_Level (Form)),
Scope_Depth (Current_Scope)),
New_Occurrence_Of
(Extra_Accessibility (Form), Loc))));
begin

View File

@ -2360,7 +2360,7 @@ package body Sem_Ch9 is
-- entry body) unless it is a parameter of the innermost enclosing
-- accept statement (or entry body).
if Object_Access_Level (Target_Obj) >= Scope_Depth (Outer_Ent)
if Static_Accessibility_Level (Target_Obj) >= Scope_Depth (Outer_Ent)
and then
(not Is_Entity_Name (Target_Obj)
or else not Is_Formal (Entity (Target_Obj))

View File

@ -3499,16 +3499,16 @@ package body Sem_Res is
elsif Ekind (Etype (Nam)) = E_Anonymous_Access_Type then
if Nkind (Parent (N)) = N_Type_Conversion
and then Type_Access_Level (Etype (Parent (N))) <
Object_Access_Level (A)
and then Type_Access_Level (Etype (Parent (N)))
< Static_Accessibility_Level (A)
then
Error_Msg_N ("aliased actual has wrong accessibility", A);
end if;
elsif Nkind (Parent (N)) = N_Qualified_Expression
and then Nkind (Parent (Parent (N))) = N_Allocator
and then Type_Access_Level (Etype (Parent (Parent (N)))) <
Object_Access_Level (A)
and then Type_Access_Level (Etype (Parent (Parent (N))))
< Static_Accessibility_Level (A)
then
Error_Msg_N
("aliased actual in allocator has wrong accessibility", A);
@ -5049,7 +5049,7 @@ package body Sem_Res is
elsif Nkind (Disc_Exp) = N_Attribute_Reference
and then Get_Attribute_Id (Attribute_Name (Disc_Exp)) =
Attribute_Access
and then Object_Access_Level (Prefix (Disc_Exp)) >
and then Static_Accessibility_Level (Prefix (Disc_Exp)) >
Deepest_Type_Access_Level (Alloc_Typ)
then
Error_Msg_N
@ -5061,7 +5061,7 @@ package body Sem_Res is
elsif Ekind (Etype (Disc_Exp)) = E_Anonymous_Access_Type
and then Nkind (Disc_Exp) = N_Selected_Component
and then Object_Access_Level (Prefix (Disc_Exp)) >
and then Static_Accessibility_Level (Prefix (Disc_Exp)) >
Deepest_Type_Access_Level (Alloc_Typ)
then
Error_Msg_N
@ -13343,8 +13343,8 @@ package body Sem_Res is
-- checking the prefix of the operand for this case).
if Nkind (Operand) = N_Selected_Component
and then Object_Access_Level (Operand) >
Deepest_Type_Access_Level (Target_Type)
and then Static_Accessibility_Level (Operand)
> Deepest_Type_Access_Level (Target_Type)
then
-- In an instance, this is a run-time check, but one we know
-- will fail, so generate an appropriate warning. The raise
@ -13550,8 +13550,8 @@ package body Sem_Res is
-- checking the prefix of the operand for this case).
if Nkind (Operand) = N_Selected_Component
and then Object_Access_Level (Operand) >
Deepest_Type_Access_Level (Target_Type)
and then Static_Accessibility_Level (Operand)
> Deepest_Type_Access_Level (Target_Type)
then
-- In an instance, this is a run-time check, but one we know
-- will fail, so generate an appropriate warning. The raise

File diff suppressed because it is too large Load Diff

View File

@ -610,7 +610,9 @@ package Sem_Util is
-- in the case of a descendant of a generic formal type (returns Int'Last
-- instead of 0).
function Defining_Entity (N : Node_Id) return Entity_Id;
function Defining_Entity
(N : Node_Id;
Empty_On_Errors : Boolean := False) return Entity_Id;
-- Given a declaration N, returns the associated defining entity. If the
-- declaration has a specification, the entity is obtained from the
-- specification. If the declaration has a defining unit name, then the
@ -621,6 +623,16 @@ package Sem_Util is
-- local entities declared during loop expansion. These entities need
-- debugging information, generated through Qualify_Entity_Names, and
-- the loop declaration must be placed in the table Name_Qualify_Units.
--
-- Set flag Empty_On_Errors to change the behavior of this routine as
-- follows:
--
-- * True - A declaration that lacks a defining entity returns Empty.
-- A node that does not allow for a defining entity returns Empty.
--
-- * False - A declaration that lacks a defining entity is given a new
-- internally generated entity which is subsequently returned. A node
-- that does not allow for a defining entity raises Program_Error
-- WARNING: There is a matching C declaration of this subprogram in fe.h
@ -672,11 +684,11 @@ package Sem_Util is
-- private components of protected objects, but is generally useful when
-- restriction No_Implicit_Heap_Allocation is active.
function Dynamic_Accessibility_Level (N : Node_Id) return Node_Id;
-- N should be an expression of an access type. Builds an integer literal
-- except in cases involving anonymous access types, where accessibility
-- levels are tracked at run time (access parameters and Ada 2012 stand-
-- alone objects).
function Dynamic_Accessibility_Level (Expr : Node_Id) return Node_Id;
-- Expr should be an expression of an access type. Builds an integer
-- literal except in cases involving anonymous access types, where
-- accessibility levels are tracked at run time (access parameters and
-- stand-alone objects of anonymous access types).
function Effective_Extra_Accessibility (Id : Entity_Id) return Entity_Id;
-- Same as Einfo.Extra_Accessibility except thtat object renames
@ -2610,10 +2622,8 @@ package Sem_Util is
-- is known at compile time. If the bounds are not known at compile time,
-- the function returns the value zero.
function Object_Access_Level (Obj : Node_Id) return Uint;
-- Return the accessibility level of the view of the object Obj. For
-- convenience, qualified expressions applied to object names are also
-- allowed as actuals for this function.
function Static_Accessibility_Level (Expr : Node_Id) return Uint;
-- Return the numeric accessibility level of the expression Expr
function Original_Aspect_Pragma_Name (N : Node_Id) return Name_Id;
-- Retrieve the name of aspect or pragma N, taking into account a possible
@ -2649,6 +2659,12 @@ package Sem_Util is
-- WARNING: this routine should be used in debugging scenarios such as
-- tracking down undefined symbols as it is fairly low level.
function Param_Entity (N : Node_Id) return Entity_Id;
-- Given an expression N, determines if the expression is a reference
-- to a formal (of a subprogram or entry), and if so returns the Id
-- of the corresponding formal entity, otherwise returns Empty. Also
-- handles the case of references to renamings of formals.
function Policy_In_Effect (Policy : Name_Id) return Name_Id;
-- Given a policy, return the policy identifier associated with it. If no
-- such policy is in effect, the value returned is No_Name.

View File

@ -174,6 +174,7 @@ package Snames is
Name_uFinalizer : constant Name_Id := N + $;
Name_uIdepth : constant Name_Id := N + $;
Name_uInit : constant Name_Id := N + $;
Name_uInit_Level : constant Name_Id := N + $;
Name_uInvariant : constant Name_Id := N + $;
Name_uMaster : constant Name_Id := N + $;
Name_uObject : constant Name_Id := N + $;