[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:
parent
cda800dd90
commit
d7e2013065
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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
|
||||
|
||||
1159
gcc/ada/sem_util.adb
1159
gcc/ada/sem_util.adb
File diff suppressed because it is too large
Load Diff
@ -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.
|
||||
|
||||
@ -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 + $;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user