[Ada] Implement late initialization rules for type extensions
Default initialization of a record object is required to initialize any components that "require late initialization" after other components. This includes the case of a type extension; "late initialization" components of the parent type are required to be initialized after non-late-init extension components. This is implemented by generalizing the use of an existing init proc parameter. Previously, the init proc for a tagged type took a Boolean parameter indicating whether or not to initialize the Tag component. With this change, this parameter can now take on any of four values indicating whether to perform 1) Full initialization (including the tag component). 2) Full initialization except for the tag component. 3) Early (non-tag) initialization only. 4) Late (non-tag) initialization only. With this change, the init proc for a type extension has the option of performing the early and late portions of the parent's initialization via two separate calls to the parent type's init proc. gcc/ada/ * exp_ch3.ads (Build_Intialization_Call): Add new formal parameter, Init_Control_Actual, with default value. Clients outside of package Exp_Ch3 are unaffected. * exp_ch3.adb (Initialization_Control): new package; support for this 4-valued parameter. The existing Requires_Late_Init function is moved into this new package. (Build_Initialization_Call): Add new formal parameter for subprogram body, use this new formal parameter in generating an init proc call. (Build_Record_Init_Proc): Replace Set_Tag Boolean formal parameter with 4-valued Init_Control_Formal. Wrap if-statements with appropriate conditions around tag initialization, early initialization, and late initialization statements. * exp_util.adb (Build_Task_Image_Decl): Avoid problem with duplicate declarations when an init proc for a type extension calls the parent type's init proc twice.
This commit is contained in:
parent
7b6fa643ef
commit
b77029ff25
@ -184,6 +184,63 @@ package body Exp_Ch3 is
|
|||||||
-- Treat user-defined stream operations as renaming_as_body if the
|
-- Treat user-defined stream operations as renaming_as_body if the
|
||||||
-- subprogram they rename is not frozen when the type is frozen.
|
-- subprogram they rename is not frozen when the type is frozen.
|
||||||
|
|
||||||
|
package Initialization_Control is
|
||||||
|
|
||||||
|
function Requires_Late_Init
|
||||||
|
(Decl : Node_Id; Rec_Type : Entity_Id) return Boolean;
|
||||||
|
-- Return True iff the given component declaration requires late
|
||||||
|
-- initialization, as defined by 3.3.1 (8.1/5).
|
||||||
|
|
||||||
|
function Has_Late_Init_Component
|
||||||
|
(Tagged_Rec_Type : Entity_Id) return Boolean;
|
||||||
|
-- Return True iff the given tagged record type has at least one
|
||||||
|
-- component that requires late initialization; this includes
|
||||||
|
-- components of ancestor types.
|
||||||
|
|
||||||
|
type Initialization_Mode is
|
||||||
|
(Full_Init, Full_Init_Except_Tag, Early_Init_Only, Late_Init_Only);
|
||||||
|
-- The initialization routine for a tagged type is passed in a
|
||||||
|
-- formal parameter of this type, indicating what initialization
|
||||||
|
-- is to be performed. This parameter defaults to Full_Init in all
|
||||||
|
-- cases except when the init proc of a type extension (let's call
|
||||||
|
-- that type T2) calls the init proc of its parent (let's call that
|
||||||
|
-- type T1). In that case, one of the other 3 values will
|
||||||
|
-- be passed in. In all three of those cases, the Tag component has
|
||||||
|
-- already been initialized before the call and is therefore not to be
|
||||||
|
-- modified. T2's init proc will either call T1's init proc
|
||||||
|
-- once (with Full_Init_Except_Tag as the parameter value) or twice
|
||||||
|
-- (first with Early_Init_Only, then later with Late_Init_Only),
|
||||||
|
-- depending on the result returned by Has_Late_Init_Component (T1).
|
||||||
|
-- In the latter case, the first call does not initialize any
|
||||||
|
-- components that require late initialization and the second call
|
||||||
|
-- then performs that deferred initialization.
|
||||||
|
-- Strictly speaking, the formal parameter subtype is actually Natural
|
||||||
|
-- but calls will only pass in values corresponding to literals
|
||||||
|
-- of this enumeration type.
|
||||||
|
|
||||||
|
function Make_Mode_Literal
|
||||||
|
(Loc : Source_Ptr; Mode : Initialization_Mode) return Node_Id
|
||||||
|
is (Make_Integer_Literal (Loc, Initialization_Mode'Pos (Mode)));
|
||||||
|
-- Generate an integer literal for a given mode value.
|
||||||
|
|
||||||
|
function Tag_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id;
|
||||||
|
function Early_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id;
|
||||||
|
function Late_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id;
|
||||||
|
-- These three functions each return a Boolean expression that
|
||||||
|
-- can be used to determine whether a given call to the initialization
|
||||||
|
-- expression for a tagged type should initialize (respectively)
|
||||||
|
-- the Tag component, the non-Tag components that do not require late
|
||||||
|
-- initialization, and the components that do require late
|
||||||
|
-- initialization.
|
||||||
|
|
||||||
|
end Initialization_Control;
|
||||||
|
|
||||||
procedure Initialization_Warning (E : Entity_Id);
|
procedure Initialization_Warning (E : Entity_Id);
|
||||||
-- If static elaboration of the package is requested, indicate
|
-- If static elaboration of the package is requested, indicate
|
||||||
-- when a type does meet the conditions for static initialization. If
|
-- when a type does meet the conditions for static initialization. If
|
||||||
@ -1447,14 +1504,15 @@ package body Exp_Ch3 is
|
|||||||
-- end;
|
-- end;
|
||||||
|
|
||||||
function Build_Initialization_Call
|
function Build_Initialization_Call
|
||||||
(Loc : Source_Ptr;
|
(Loc : Source_Ptr;
|
||||||
Id_Ref : Node_Id;
|
Id_Ref : Node_Id;
|
||||||
Typ : Entity_Id;
|
Typ : Entity_Id;
|
||||||
In_Init_Proc : Boolean := False;
|
In_Init_Proc : Boolean := False;
|
||||||
Enclos_Type : Entity_Id := Empty;
|
Enclos_Type : Entity_Id := Empty;
|
||||||
Discr_Map : Elist_Id := New_Elmt_List;
|
Discr_Map : Elist_Id := New_Elmt_List;
|
||||||
With_Default_Init : Boolean := False;
|
With_Default_Init : Boolean := False;
|
||||||
Constructor_Ref : Node_Id := Empty) return List_Id
|
Constructor_Ref : Node_Id := Empty;
|
||||||
|
Init_Control_Actual : Entity_Id := Empty) return List_Id
|
||||||
is
|
is
|
||||||
Res : constant List_Id := New_List;
|
Res : constant List_Id := New_List;
|
||||||
|
|
||||||
@ -1838,14 +1896,26 @@ package body Exp_Ch3 is
|
|||||||
|
|
||||||
-- If this is a call to initialize the parent component of a derived
|
-- If this is a call to initialize the parent component of a derived
|
||||||
-- tagged type, indicate that the tag should not be set in the parent.
|
-- tagged type, indicate that the tag should not be set in the parent.
|
||||||
|
-- This is done via the actual parameter value for the Init_Control
|
||||||
|
-- formal parameter, which is also used to deal with late initialization
|
||||||
|
-- requirements.
|
||||||
|
--
|
||||||
|
-- We pass in Full_Init_Except_Tag unless the caller tells us to do
|
||||||
|
-- otherwise (by passing in a nonempty Init_Control_Actual parameter).
|
||||||
|
|
||||||
if Is_Tagged_Type (Full_Init_Type)
|
if Is_Tagged_Type (Full_Init_Type)
|
||||||
and then not Is_CPP_Class (Full_Init_Type)
|
and then not Is_CPP_Class (Full_Init_Type)
|
||||||
and then Nkind (Id_Ref) = N_Selected_Component
|
and then Nkind (Id_Ref) = N_Selected_Component
|
||||||
and then Chars (Selector_Name (Id_Ref)) = Name_uParent
|
and then Chars (Selector_Name (Id_Ref)) = Name_uParent
|
||||||
then
|
then
|
||||||
Append_To (Args, New_Occurrence_Of (Standard_False, Loc));
|
declare
|
||||||
|
use Initialization_Control;
|
||||||
|
begin
|
||||||
|
Append_To (Args,
|
||||||
|
(if Present (Init_Control_Actual)
|
||||||
|
then Init_Control_Actual
|
||||||
|
else Make_Mode_Literal (Loc, Full_Init_Except_Tag)));
|
||||||
|
end;
|
||||||
elsif Present (Constructor_Ref) then
|
elsif Present (Constructor_Ref) then
|
||||||
Append_List_To (Args,
|
Append_List_To (Args,
|
||||||
New_Copy_List (Parameter_Associations (Constructor_Ref)));
|
New_Copy_List (Parameter_Associations (Constructor_Ref)));
|
||||||
@ -1906,8 +1976,9 @@ package body Exp_Ch3 is
|
|||||||
Counter : Nat := 0;
|
Counter : Nat := 0;
|
||||||
Proc_Id : Entity_Id;
|
Proc_Id : Entity_Id;
|
||||||
Rec_Type : Entity_Id;
|
Rec_Type : Entity_Id;
|
||||||
Set_Tag : Entity_Id := Empty;
|
|
||||||
Has_Late_Init_Comp : Boolean := False; -- set in Build_Init_Statements
|
Init_Control_Formal : Entity_Id := Empty; -- set in Build_Init_Statements
|
||||||
|
Has_Late_Init_Comp : Boolean := False; -- set in Build_Init_Statements
|
||||||
|
|
||||||
function Build_Assignment
|
function Build_Assignment
|
||||||
(Id : Entity_Id;
|
(Id : Entity_Id;
|
||||||
@ -2532,6 +2603,7 @@ package body Exp_Ch3 is
|
|||||||
Proc_Spec_Node : Node_Id;
|
Proc_Spec_Node : Node_Id;
|
||||||
Record_Extension_Node : Node_Id;
|
Record_Extension_Node : Node_Id;
|
||||||
|
|
||||||
|
use Initialization_Control;
|
||||||
begin
|
begin
|
||||||
Body_Stmts := New_List;
|
Body_Stmts := New_List;
|
||||||
Body_Node := New_Node (N_Subprogram_Body, Loc);
|
Body_Node := New_Node (N_Subprogram_Body, Loc);
|
||||||
@ -2544,21 +2616,27 @@ package body Exp_Ch3 is
|
|||||||
Append_List_To (Parameters,
|
Append_List_To (Parameters,
|
||||||
Build_Discriminant_Formals (Rec_Type, True));
|
Build_Discriminant_Formals (Rec_Type, True));
|
||||||
|
|
||||||
-- For tagged types, we add a flag to indicate whether the routine
|
-- For tagged types, we add a parameter to indicate what
|
||||||
-- is called to initialize a parent component in the init_proc of
|
-- portion of the object's initialization is to be performed.
|
||||||
-- a type extension. If the flag is false, we do not set the tag
|
-- This is used for two purposes:
|
||||||
-- because it has been set already in the extension.
|
-- 1) When a type extension's initialization procedure calls
|
||||||
|
-- the initialization procedure of the parent type, we do
|
||||||
|
-- not want the parent to initialize the Tag component;
|
||||||
|
-- it has been set already.
|
||||||
|
-- 2) If an ancestor type has at least one component that requires
|
||||||
|
-- late initialization, then we need to be able to initialize
|
||||||
|
-- those components separately after initializing any other
|
||||||
|
-- components.
|
||||||
|
|
||||||
if Is_Tagged_Type (Rec_Type) then
|
if Is_Tagged_Type (Rec_Type) then
|
||||||
Set_Tag := Make_Temporary (Loc, 'P');
|
Init_Control_Formal := Make_Temporary (Loc, 'P');
|
||||||
|
|
||||||
Append_To (Parameters,
|
Append_To (Parameters,
|
||||||
Make_Parameter_Specification (Loc,
|
Make_Parameter_Specification (Loc,
|
||||||
Defining_Identifier => Set_Tag,
|
Defining_Identifier => Init_Control_Formal,
|
||||||
Parameter_Type =>
|
Parameter_Type =>
|
||||||
New_Occurrence_Of (Standard_Boolean, Loc),
|
New_Occurrence_Of (Standard_Natural, Loc),
|
||||||
Expression =>
|
Expression => Make_Mode_Literal (Loc, Full_Init)));
|
||||||
New_Occurrence_Of (Standard_True, Loc)));
|
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Create an extra accessibility parameter to capture the level of
|
-- Create an extra accessibility parameter to capture the level of
|
||||||
@ -2622,22 +2700,45 @@ package body Exp_Ch3 is
|
|||||||
declare
|
declare
|
||||||
Parent_IP : constant Name_Id :=
|
Parent_IP : constant Name_Id :=
|
||||||
Make_Init_Proc_Name (Etype (Rec_Ent));
|
Make_Init_Proc_Name (Etype (Rec_Ent));
|
||||||
Stmt : Node_Id;
|
Stmt : Node_Id := First (Stmts);
|
||||||
IP_Call : Node_Id;
|
IP_Call : Node_Id := Empty;
|
||||||
IP_Stmts : List_Id;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
-- Look for a call to the parent IP at the beginning
|
-- Look for a call to the parent IP associated with
|
||||||
-- of Stmts associated with the record extension
|
-- the record extension.
|
||||||
|
-- The call will be inside not one but two
|
||||||
|
-- if-statements (with the same condition). Testing
|
||||||
|
-- the same Early_Init condition twice might seem
|
||||||
|
-- redundant. However, as soon as we exit this loop,
|
||||||
|
-- we are going to hoist the inner if-statement out
|
||||||
|
-- of the outer one; the "redundant" test was built
|
||||||
|
-- in anticipation of this hoisting.
|
||||||
|
|
||||||
Stmt := First (Stmts);
|
|
||||||
IP_Call := Empty;
|
|
||||||
while Present (Stmt) loop
|
while Present (Stmt) loop
|
||||||
if Nkind (Stmt) = N_Procedure_Call_Statement
|
if Nkind (Stmt) = N_If_Statement then
|
||||||
and then Chars (Name (Stmt)) = Parent_IP
|
declare
|
||||||
then
|
Then_Stmt1 : Node_Id :=
|
||||||
IP_Call := Stmt;
|
First (Then_Statements (Stmt));
|
||||||
exit;
|
Then_Stmt2 : Node_Id;
|
||||||
|
begin
|
||||||
|
while Present (Then_Stmt1) loop
|
||||||
|
if Nkind (Then_Stmt1) = N_If_Statement then
|
||||||
|
Then_Stmt2 :=
|
||||||
|
First (Then_Statements (Then_Stmt1));
|
||||||
|
|
||||||
|
if Nkind (Then_Stmt2) =
|
||||||
|
N_Procedure_Call_Statement
|
||||||
|
and then Chars (Name (Then_Stmt2)) =
|
||||||
|
Parent_IP
|
||||||
|
then
|
||||||
|
-- IP_Call is a call wrapped in an
|
||||||
|
-- if statement.
|
||||||
|
IP_Call := Then_Stmt1;
|
||||||
|
exit;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
Next (Then_Stmt1);
|
||||||
|
end loop;
|
||||||
|
end;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Next (Stmt);
|
Next (Stmt);
|
||||||
@ -2647,14 +2748,8 @@ package body Exp_Ch3 is
|
|||||||
-- statements of this IP routine
|
-- statements of this IP routine
|
||||||
|
|
||||||
if Present (IP_Call) then
|
if Present (IP_Call) then
|
||||||
IP_Stmts := New_List;
|
Remove (IP_Call);
|
||||||
loop
|
Prepend_List_To (Body_Stmts, New_List (IP_Call));
|
||||||
Stmt := Remove_Head (Stmts);
|
|
||||||
Append_To (IP_Stmts, Stmt);
|
|
||||||
exit when Stmt = IP_Call;
|
|
||||||
end loop;
|
|
||||||
|
|
||||||
Prepend_List_To (Body_Stmts, IP_Stmts);
|
|
||||||
end if;
|
end if;
|
||||||
end;
|
end;
|
||||||
end if;
|
end if;
|
||||||
@ -2729,7 +2824,8 @@ package body Exp_Ch3 is
|
|||||||
|
|
||||||
Elab_List := New_List (
|
Elab_List := New_List (
|
||||||
Make_If_Statement (Loc,
|
Make_If_Statement (Loc,
|
||||||
Condition => New_Occurrence_Of (Set_Tag, Loc),
|
Condition =>
|
||||||
|
Tag_Init_Condition (Loc, Init_Control_Formal),
|
||||||
Then_Statements => Init_Tags_List));
|
Then_Statements => Init_Tags_List));
|
||||||
|
|
||||||
if Elab_Flag_Needed (Rec_Type) then
|
if Elab_Flag_Needed (Rec_Type) then
|
||||||
@ -2755,7 +2851,8 @@ package body Exp_Ch3 is
|
|||||||
else
|
else
|
||||||
Prepend_To (Body_Stmts,
|
Prepend_To (Body_Stmts,
|
||||||
Make_If_Statement (Loc,
|
Make_If_Statement (Loc,
|
||||||
Condition => New_Occurrence_Of (Set_Tag, Loc),
|
Condition =>
|
||||||
|
Tag_Init_Condition (Loc, Init_Control_Formal),
|
||||||
Then_Statements => Init_Tags_List));
|
Then_Statements => Init_Tags_List));
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
@ -2823,11 +2920,18 @@ package body Exp_Ch3 is
|
|||||||
begin
|
begin
|
||||||
-- Search for the call to the IP of the parent. We assume
|
-- Search for the call to the IP of the parent. We assume
|
||||||
-- that the first init_proc call is for the parent.
|
-- that the first init_proc call is for the parent.
|
||||||
|
-- It is wrapped in an "if Early_Init_Condition"
|
||||||
|
-- if-statement.
|
||||||
|
|
||||||
Ins_Nod := First (Body_Stmts);
|
Ins_Nod := First (Body_Stmts);
|
||||||
while Present (Next (Ins_Nod))
|
while Present (Next (Ins_Nod))
|
||||||
and then (Nkind (Ins_Nod) /= N_Procedure_Call_Statement
|
and then
|
||||||
or else not Is_Init_Proc (Name (Ins_Nod)))
|
(Nkind (Ins_Nod) /= N_If_Statement
|
||||||
|
or else (Nkind (First (Then_Statements (Ins_Nod)))
|
||||||
|
/= N_Procedure_Call_Statement)
|
||||||
|
or else not Is_Init_Proc
|
||||||
|
(Name (First (Then_Statements
|
||||||
|
(Ins_Nod)))))
|
||||||
loop
|
loop
|
||||||
Next (Ins_Nod);
|
Next (Ins_Nod);
|
||||||
end loop;
|
end loop;
|
||||||
@ -2974,34 +3078,31 @@ package body Exp_Ch3 is
|
|||||||
Decl : Node_Id;
|
Decl : Node_Id;
|
||||||
Id : Entity_Id;
|
Id : Entity_Id;
|
||||||
Parent_Stmts : List_Id;
|
Parent_Stmts : List_Id;
|
||||||
Stmts : List_Id;
|
Parent_Id : Entity_Id := Empty;
|
||||||
|
Stmts, Late_Stmts : List_Id := Empty_List;
|
||||||
Typ : Entity_Id;
|
Typ : Entity_Id;
|
||||||
|
|
||||||
procedure Increment_Counter (Loc : Source_Ptr);
|
procedure Increment_Counter
|
||||||
|
(Loc : Source_Ptr; Late : Boolean := False);
|
||||||
-- Generate an "increment by one" statement for the current counter
|
-- Generate an "increment by one" statement for the current counter
|
||||||
-- and append it to the list Stmts.
|
-- and append it to the appropriate statement list.
|
||||||
|
|
||||||
procedure Make_Counter (Loc : Source_Ptr);
|
procedure Make_Counter (Loc : Source_Ptr);
|
||||||
-- Create a new counter for the current component list. The routine
|
-- Create a new counter for the current component list. The routine
|
||||||
-- creates a new defining Id, adds an object declaration and sets
|
-- creates a new defining Id, adds an object declaration and sets
|
||||||
-- the Id generator for the next variant.
|
-- the Id generator for the next variant.
|
||||||
|
|
||||||
function Requires_Late_Initialization
|
|
||||||
(Decl : Node_Id;
|
|
||||||
Rec_Type : Entity_Id) return Boolean;
|
|
||||||
-- Return whether the given Decl requires late initialization, as
|
|
||||||
-- defined by 3.3.1 (8.1/5).
|
|
||||||
|
|
||||||
-----------------------
|
-----------------------
|
||||||
-- Increment_Counter --
|
-- Increment_Counter --
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
procedure Increment_Counter (Loc : Source_Ptr) is
|
procedure Increment_Counter
|
||||||
|
(Loc : Source_Ptr; Late : Boolean := False) is
|
||||||
begin
|
begin
|
||||||
-- Generate:
|
-- Generate:
|
||||||
-- Counter := Counter + 1;
|
-- Counter := Counter + 1;
|
||||||
|
|
||||||
Append_To (Stmts,
|
Append_To ((if Late then Late_Stmts else Stmts),
|
||||||
Make_Assignment_Statement (Loc,
|
Make_Assignment_Statement (Loc,
|
||||||
Name => New_Occurrence_Of (Counter_Id, Loc),
|
Name => New_Occurrence_Of (Counter_Id, Loc),
|
||||||
Expression =>
|
Expression =>
|
||||||
@ -3038,157 +3139,6 @@ package body Exp_Ch3 is
|
|||||||
Make_Integer_Literal (Loc, 0)));
|
Make_Integer_Literal (Loc, 0)));
|
||||||
end Make_Counter;
|
end Make_Counter;
|
||||||
|
|
||||||
----------------------------------
|
|
||||||
-- Requires_Late_Initialization --
|
|
||||||
----------------------------------
|
|
||||||
|
|
||||||
function Requires_Late_Initialization
|
|
||||||
(Decl : Node_Id;
|
|
||||||
Rec_Type : Entity_Id) return Boolean
|
|
||||||
is
|
|
||||||
References_Current_Instance : Boolean := False;
|
|
||||||
Has_Access_Discriminant : Boolean := False;
|
|
||||||
Has_Internal_Call : Boolean := False;
|
|
||||||
|
|
||||||
function Find_Access_Discriminant
|
|
||||||
(N : Node_Id) return Traverse_Result;
|
|
||||||
-- Look for a name denoting an access discriminant
|
|
||||||
|
|
||||||
function Find_Current_Instance
|
|
||||||
(N : Node_Id) return Traverse_Result;
|
|
||||||
-- Look for a reference to the current instance of the type
|
|
||||||
|
|
||||||
function Find_Internal_Call
|
|
||||||
(N : Node_Id) return Traverse_Result;
|
|
||||||
-- Look for an internal protected function call
|
|
||||||
|
|
||||||
------------------------------
|
|
||||||
-- Find_Access_Discriminant --
|
|
||||||
------------------------------
|
|
||||||
|
|
||||||
function Find_Access_Discriminant
|
|
||||||
(N : Node_Id) return Traverse_Result is
|
|
||||||
begin
|
|
||||||
if Is_Entity_Name (N)
|
|
||||||
and then Denotes_Discriminant (N)
|
|
||||||
and then Is_Access_Type (Etype (N))
|
|
||||||
then
|
|
||||||
Has_Access_Discriminant := True;
|
|
||||||
return Abandon;
|
|
||||||
else
|
|
||||||
return OK;
|
|
||||||
end if;
|
|
||||||
end Find_Access_Discriminant;
|
|
||||||
|
|
||||||
---------------------------
|
|
||||||
-- Find_Current_Instance --
|
|
||||||
---------------------------
|
|
||||||
|
|
||||||
function Find_Current_Instance
|
|
||||||
(N : Node_Id) return Traverse_Result is
|
|
||||||
begin
|
|
||||||
if Is_Entity_Name (N)
|
|
||||||
and then Present (Entity (N))
|
|
||||||
and then Is_Current_Instance (N)
|
|
||||||
then
|
|
||||||
References_Current_Instance := True;
|
|
||||||
return Abandon;
|
|
||||||
else
|
|
||||||
return OK;
|
|
||||||
end if;
|
|
||||||
end Find_Current_Instance;
|
|
||||||
|
|
||||||
------------------------
|
|
||||||
-- Find_Internal_Call --
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
function Find_Internal_Call (N : Node_Id) return Traverse_Result is
|
|
||||||
|
|
||||||
function Call_Scope (N : Node_Id) return Entity_Id;
|
|
||||||
-- Return the scope enclosing a given call node N
|
|
||||||
|
|
||||||
----------------
|
|
||||||
-- Call_Scope --
|
|
||||||
----------------
|
|
||||||
|
|
||||||
function Call_Scope (N : Node_Id) return Entity_Id is
|
|
||||||
Nam : constant Node_Id := Name (N);
|
|
||||||
begin
|
|
||||||
if Nkind (Nam) = N_Selected_Component then
|
|
||||||
return Scope (Entity (Prefix (Nam)));
|
|
||||||
else
|
|
||||||
return Scope (Entity (Nam));
|
|
||||||
end if;
|
|
||||||
end Call_Scope;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if Nkind (N) = N_Function_Call
|
|
||||||
and then Call_Scope (N)
|
|
||||||
= Corresponding_Concurrent_Type (Rec_Type)
|
|
||||||
then
|
|
||||||
Has_Internal_Call := True;
|
|
||||||
return Abandon;
|
|
||||||
else
|
|
||||||
return OK;
|
|
||||||
end if;
|
|
||||||
end Find_Internal_Call;
|
|
||||||
|
|
||||||
procedure Search_Access_Discriminant is new
|
|
||||||
Traverse_Proc (Find_Access_Discriminant);
|
|
||||||
|
|
||||||
procedure Search_Current_Instance is new
|
|
||||||
Traverse_Proc (Find_Current_Instance);
|
|
||||||
|
|
||||||
procedure Search_Internal_Call is new
|
|
||||||
Traverse_Proc (Find_Internal_Call);
|
|
||||||
|
|
||||||
begin
|
|
||||||
-- A component of an object is said to require late initialization
|
|
||||||
-- if:
|
|
||||||
|
|
||||||
-- it has an access discriminant value constrained by a per-object
|
|
||||||
-- expression;
|
|
||||||
|
|
||||||
if Has_Access_Constraint (Defining_Identifier (Decl))
|
|
||||||
and then No (Expression (Decl))
|
|
||||||
then
|
|
||||||
return True;
|
|
||||||
|
|
||||||
elsif Present (Expression (Decl)) then
|
|
||||||
|
|
||||||
-- it has an initialization expression that includes a name
|
|
||||||
-- denoting an access discriminant;
|
|
||||||
|
|
||||||
Search_Access_Discriminant (Expression (Decl));
|
|
||||||
|
|
||||||
if Has_Access_Discriminant then
|
|
||||||
return True;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
-- or it has an initialization expression that includes a
|
|
||||||
-- reference to the current instance of the type either by
|
|
||||||
-- name...
|
|
||||||
|
|
||||||
Search_Current_Instance (Expression (Decl));
|
|
||||||
|
|
||||||
if References_Current_Instance then
|
|
||||||
return True;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
-- ...or implicitly as the target object of a call.
|
|
||||||
|
|
||||||
if Is_Protected_Record_Type (Rec_Type) then
|
|
||||||
Search_Internal_Call (Expression (Decl));
|
|
||||||
|
|
||||||
if Has_Internal_Call then
|
|
||||||
return True;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
end if;
|
|
||||||
|
|
||||||
return False;
|
|
||||||
end Requires_Late_Initialization;
|
|
||||||
|
|
||||||
-- Start of processing for Build_Init_Statements
|
-- Start of processing for Build_Init_Statements
|
||||||
|
|
||||||
begin
|
begin
|
||||||
@ -3256,7 +3206,10 @@ package body Exp_Ch3 is
|
|||||||
-- Leave any processing of component requiring late initialization
|
-- Leave any processing of component requiring late initialization
|
||||||
-- for the second pass.
|
-- for the second pass.
|
||||||
|
|
||||||
if Requires_Late_Initialization (Decl, Rec_Type) then
|
if Initialization_Control.Requires_Late_Init (Decl, Rec_Type) then
|
||||||
|
if not Has_Late_Init_Comp then
|
||||||
|
Late_Stmts := New_List;
|
||||||
|
end if;
|
||||||
Has_Late_Init_Comp := True;
|
Has_Late_Init_Comp := True;
|
||||||
|
|
||||||
-- Regular component cases
|
-- Regular component cases
|
||||||
@ -3403,17 +3356,56 @@ package body Exp_Ch3 is
|
|||||||
elsif not Is_Interface (Typ)
|
elsif not Is_Interface (Typ)
|
||||||
and then Has_Non_Null_Base_Init_Proc (Typ)
|
and then Has_Non_Null_Base_Init_Proc (Typ)
|
||||||
then
|
then
|
||||||
Actions :=
|
declare
|
||||||
Build_Initialization_Call
|
use Initialization_Control;
|
||||||
(Comp_Loc,
|
Init_Control_Actual : Node_Id := Empty;
|
||||||
Make_Selected_Component (Comp_Loc,
|
Is_Parent : constant Boolean := Chars (Id) = Name_uParent;
|
||||||
Prefix =>
|
Init_Call_Stmts : List_Id;
|
||||||
Make_Identifier (Comp_Loc, Name_uInit),
|
begin
|
||||||
Selector_Name => New_Occurrence_Of (Id, Comp_Loc)),
|
if Is_Parent and then Has_Late_Init_Component (Etype (Id))
|
||||||
Typ,
|
then
|
||||||
In_Init_Proc => True,
|
Init_Control_Actual :=
|
||||||
Enclos_Type => Rec_Type,
|
Make_Mode_Literal (Comp_Loc, Early_Init_Only);
|
||||||
Discr_Map => Discr_Map);
|
-- Parent_Id used later in second call to parent's
|
||||||
|
-- init proc to initialize late-init components.
|
||||||
|
Parent_Id := Id;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Init_Call_Stmts :=
|
||||||
|
Build_Initialization_Call
|
||||||
|
(Comp_Loc,
|
||||||
|
Make_Selected_Component (Comp_Loc,
|
||||||
|
Prefix =>
|
||||||
|
Make_Identifier (Comp_Loc, Name_uInit),
|
||||||
|
Selector_Name => New_Occurrence_Of (Id, Comp_Loc)),
|
||||||
|
Typ,
|
||||||
|
In_Init_Proc => True,
|
||||||
|
Enclos_Type => Rec_Type,
|
||||||
|
Discr_Map => Discr_Map,
|
||||||
|
Init_Control_Actual => Init_Control_Actual);
|
||||||
|
|
||||||
|
if Is_Parent then
|
||||||
|
-- This is tricky. At first it looks like
|
||||||
|
-- we are going to end up with nested
|
||||||
|
-- if-statements with the same condition:
|
||||||
|
-- if Early_Init_Condition then
|
||||||
|
-- if Early_Init_Condition then
|
||||||
|
-- Parent_TypeIP (...);
|
||||||
|
-- end if;
|
||||||
|
-- end if;
|
||||||
|
-- But later we will hoist the inner if-statement
|
||||||
|
-- out of the outer one; we do this because the
|
||||||
|
-- init-proc call for the _Parent component of a type
|
||||||
|
-- extension has to precede any other initialization.
|
||||||
|
Actions :=
|
||||||
|
New_List (Make_If_Statement (Loc,
|
||||||
|
Condition =>
|
||||||
|
Early_Init_Condition (Loc, Init_Control_Formal),
|
||||||
|
Then_Statements => Init_Call_Stmts));
|
||||||
|
else
|
||||||
|
Actions := Init_Call_Stmts;
|
||||||
|
end if;
|
||||||
|
end;
|
||||||
|
|
||||||
Clean_Task_Names (Typ, Proc_Id);
|
Clean_Task_Names (Typ, Proc_Id);
|
||||||
|
|
||||||
@ -3443,7 +3435,7 @@ package body Exp_Ch3 is
|
|||||||
-- DIC here.
|
-- DIC here.
|
||||||
|
|
||||||
if Has_DIC (Typ)
|
if Has_DIC (Typ)
|
||||||
and then not Present (Expression (Decl))
|
and then No (Expression (Decl))
|
||||||
and then Present (DIC_Procedure (Typ))
|
and then Present (DIC_Procedure (Typ))
|
||||||
and then not Has_Null_Body (DIC_Procedure (Typ))
|
and then not Has_Null_Body (DIC_Procedure (Typ))
|
||||||
|
|
||||||
@ -3481,7 +3473,6 @@ package body Exp_Ch3 is
|
|||||||
if Present (Actions) then
|
if Present (Actions) then
|
||||||
if Chars (Id) = Name_uParent then
|
if Chars (Id) = Name_uParent then
|
||||||
Append_List_To (Parent_Stmts, Actions);
|
Append_List_To (Parent_Stmts, Actions);
|
||||||
|
|
||||||
else
|
else
|
||||||
Append_List_To (Stmts, Actions);
|
Append_List_To (Stmts, Actions);
|
||||||
|
|
||||||
@ -3595,6 +3586,34 @@ package body Exp_Ch3 is
|
|||||||
|
|
||||||
-- Second pass: components that require late initialization
|
-- Second pass: components that require late initialization
|
||||||
|
|
||||||
|
if Present (Parent_Id) then
|
||||||
|
declare
|
||||||
|
Parent_Loc : constant Source_Ptr := Sloc (Parent (Parent_Id));
|
||||||
|
use Initialization_Control;
|
||||||
|
begin
|
||||||
|
-- We are building the init proc for a type extension.
|
||||||
|
-- Call the parent type's init proc a second time, this
|
||||||
|
-- time to initialize the parent's components that require
|
||||||
|
-- late initialization.
|
||||||
|
|
||||||
|
Append_List_To (Late_Stmts,
|
||||||
|
Build_Initialization_Call
|
||||||
|
(Loc => Parent_Loc,
|
||||||
|
Id_Ref =>
|
||||||
|
Make_Selected_Component (Parent_Loc,
|
||||||
|
Prefix => Make_Identifier
|
||||||
|
(Parent_Loc, Name_uInit),
|
||||||
|
Selector_Name => New_Occurrence_Of (Parent_Id,
|
||||||
|
Parent_Loc)),
|
||||||
|
Typ => Etype (Parent_Id),
|
||||||
|
In_Init_Proc => True,
|
||||||
|
Enclos_Type => Rec_Type,
|
||||||
|
Discr_Map => Discr_Map,
|
||||||
|
Init_Control_Actual => Make_Mode_Literal
|
||||||
|
(Parent_Loc, Late_Init_Only)));
|
||||||
|
end;
|
||||||
|
end if;
|
||||||
|
|
||||||
if Has_Late_Init_Comp then
|
if Has_Late_Init_Comp then
|
||||||
Decl := First_Non_Pragma (Component_Items (Comp_List));
|
Decl := First_Non_Pragma (Component_Items (Comp_List));
|
||||||
while Present (Decl) loop
|
while Present (Decl) loop
|
||||||
@ -3602,13 +3621,14 @@ package body Exp_Ch3 is
|
|||||||
Id := Defining_Identifier (Decl);
|
Id := Defining_Identifier (Decl);
|
||||||
Typ := Etype (Id);
|
Typ := Etype (Id);
|
||||||
|
|
||||||
if Requires_Late_Initialization (Decl, Rec_Type) then
|
if Initialization_Control.Requires_Late_Init (Decl, Rec_Type)
|
||||||
|
then
|
||||||
if Present (Expression (Decl)) then
|
if Present (Expression (Decl)) then
|
||||||
Append_List_To (Stmts,
|
Append_List_To (Late_Stmts,
|
||||||
Build_Assignment (Id, Expression (Decl)));
|
Build_Assignment (Id, Expression (Decl)));
|
||||||
|
|
||||||
elsif Has_Non_Null_Base_Init_Proc (Typ) then
|
elsif Has_Non_Null_Base_Init_Proc (Typ) then
|
||||||
Append_List_To (Stmts,
|
Append_List_To (Late_Stmts,
|
||||||
Build_Initialization_Call (Comp_Loc,
|
Build_Initialization_Call (Comp_Loc,
|
||||||
Make_Selected_Component (Comp_Loc,
|
Make_Selected_Component (Comp_Loc,
|
||||||
Prefix =>
|
Prefix =>
|
||||||
@ -3628,10 +3648,10 @@ package body Exp_Ch3 is
|
|||||||
Make_Counter (Comp_Loc);
|
Make_Counter (Comp_Loc);
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
Increment_Counter (Comp_Loc);
|
Increment_Counter (Comp_Loc, Late => True);
|
||||||
end if;
|
end if;
|
||||||
elsif Component_Needs_Simple_Initialization (Typ) then
|
elsif Component_Needs_Simple_Initialization (Typ) then
|
||||||
Append_List_To (Stmts,
|
Append_List_To (Late_Stmts,
|
||||||
Build_Assignment
|
Build_Assignment
|
||||||
(Id => Id,
|
(Id => Id,
|
||||||
Default =>
|
Default =>
|
||||||
@ -3646,7 +3666,8 @@ package body Exp_Ch3 is
|
|||||||
end loop;
|
end loop;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- Process the variant part
|
-- Process the variant part (incorrectly ignoring late
|
||||||
|
-- initialization requirements for components therein).
|
||||||
|
|
||||||
if Present (Variant_Part (Comp_List)) then
|
if Present (Variant_Part (Comp_List)) then
|
||||||
declare
|
declare
|
||||||
@ -3681,16 +3702,42 @@ package body Exp_Ch3 is
|
|||||||
end;
|
end;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
-- If no initializations when generated for component declarations
|
if No (Init_Control_Formal) then
|
||||||
-- corresponding to this Stmts, append a null statement to Stmts to
|
Append_List_To (Stmts, Late_Stmts);
|
||||||
-- to make it a valid Ada tree.
|
|
||||||
|
|
||||||
if Is_Empty_List (Stmts) then
|
-- If no initializations were generated for component declarations
|
||||||
Append (Make_Null_Statement (Loc), Stmts);
|
-- and included in Stmts, then append a null statement to Stmts
|
||||||
|
-- to make it a valid Ada tree.
|
||||||
|
|
||||||
|
if Is_Empty_List (Stmts) then
|
||||||
|
Append (Make_Null_Statement (Loc), Stmts);
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return Stmts;
|
||||||
|
else
|
||||||
|
declare
|
||||||
|
use Initialization_Control;
|
||||||
|
|
||||||
|
If_Early : constant Node_Id :=
|
||||||
|
(if Is_Empty_List (Stmts) then
|
||||||
|
Make_Null_Statement (Loc)
|
||||||
|
else
|
||||||
|
Make_If_Statement (Loc,
|
||||||
|
Condition =>
|
||||||
|
Early_Init_Condition (Loc, Init_Control_Formal),
|
||||||
|
Then_Statements => Stmts));
|
||||||
|
If_Late : constant Node_Id :=
|
||||||
|
(if Is_Empty_List (Late_Stmts) then
|
||||||
|
Make_Null_Statement (Loc)
|
||||||
|
else
|
||||||
|
Make_If_Statement (Loc,
|
||||||
|
Condition =>
|
||||||
|
Late_Init_Condition (Loc, Init_Control_Formal),
|
||||||
|
Then_Statements => Late_Stmts));
|
||||||
|
begin
|
||||||
|
return New_List (If_Early, If_Late);
|
||||||
|
end;
|
||||||
end if;
|
end if;
|
||||||
|
|
||||||
return Stmts;
|
|
||||||
|
|
||||||
exception
|
exception
|
||||||
when RE_Not_Available =>
|
when RE_Not_Available =>
|
||||||
return Empty_List;
|
return Empty_List;
|
||||||
@ -9048,6 +9095,230 @@ package body Exp_Ch3 is
|
|||||||
return Is_RTU (S1, System) or else Is_RTU (S1, Ada);
|
return Is_RTU (S1, System) or else Is_RTU (S1, Ada);
|
||||||
end In_Runtime;
|
end In_Runtime;
|
||||||
|
|
||||||
|
package body Initialization_Control is
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Requires_Late_Init --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
function Requires_Late_Init
|
||||||
|
(Decl : Node_Id;
|
||||||
|
Rec_Type : Entity_Id) return Boolean
|
||||||
|
is
|
||||||
|
References_Current_Instance : Boolean := False;
|
||||||
|
Has_Access_Discriminant : Boolean := False;
|
||||||
|
Has_Internal_Call : Boolean := False;
|
||||||
|
|
||||||
|
function Find_Access_Discriminant
|
||||||
|
(N : Node_Id) return Traverse_Result;
|
||||||
|
-- Look for a name denoting an access discriminant
|
||||||
|
|
||||||
|
function Find_Current_Instance
|
||||||
|
(N : Node_Id) return Traverse_Result;
|
||||||
|
-- Look for a reference to the current instance of the type
|
||||||
|
|
||||||
|
function Find_Internal_Call
|
||||||
|
(N : Node_Id) return Traverse_Result;
|
||||||
|
-- Look for an internal protected function call
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
-- Find_Access_Discriminant --
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
function Find_Access_Discriminant
|
||||||
|
(N : Node_Id) return Traverse_Result is
|
||||||
|
begin
|
||||||
|
if Is_Entity_Name (N)
|
||||||
|
and then Denotes_Discriminant (N)
|
||||||
|
and then Is_Access_Type (Etype (N))
|
||||||
|
then
|
||||||
|
Has_Access_Discriminant := True;
|
||||||
|
return Abandon;
|
||||||
|
else
|
||||||
|
return OK;
|
||||||
|
end if;
|
||||||
|
end Find_Access_Discriminant;
|
||||||
|
|
||||||
|
---------------------------
|
||||||
|
-- Find_Current_Instance --
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
function Find_Current_Instance
|
||||||
|
(N : Node_Id) return Traverse_Result is
|
||||||
|
begin
|
||||||
|
if Is_Entity_Name (N)
|
||||||
|
and then Present (Entity (N))
|
||||||
|
and then Is_Current_Instance (N)
|
||||||
|
then
|
||||||
|
References_Current_Instance := True;
|
||||||
|
return Abandon;
|
||||||
|
else
|
||||||
|
return OK;
|
||||||
|
end if;
|
||||||
|
end Find_Current_Instance;
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Find_Internal_Call --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
function Find_Internal_Call (N : Node_Id) return Traverse_Result is
|
||||||
|
|
||||||
|
function Call_Scope (N : Node_Id) return Entity_Id;
|
||||||
|
-- Return the scope enclosing a given call node N
|
||||||
|
|
||||||
|
----------------
|
||||||
|
-- Call_Scope --
|
||||||
|
----------------
|
||||||
|
|
||||||
|
function Call_Scope (N : Node_Id) return Entity_Id is
|
||||||
|
Nam : constant Node_Id := Name (N);
|
||||||
|
begin
|
||||||
|
if Nkind (Nam) = N_Selected_Component then
|
||||||
|
return Scope (Entity (Prefix (Nam)));
|
||||||
|
else
|
||||||
|
return Scope (Entity (Nam));
|
||||||
|
end if;
|
||||||
|
end Call_Scope;
|
||||||
|
|
||||||
|
begin
|
||||||
|
if Nkind (N) = N_Function_Call
|
||||||
|
and then Call_Scope (N)
|
||||||
|
= Corresponding_Concurrent_Type (Rec_Type)
|
||||||
|
then
|
||||||
|
Has_Internal_Call := True;
|
||||||
|
return Abandon;
|
||||||
|
else
|
||||||
|
return OK;
|
||||||
|
end if;
|
||||||
|
end Find_Internal_Call;
|
||||||
|
|
||||||
|
procedure Search_Access_Discriminant is new
|
||||||
|
Traverse_Proc (Find_Access_Discriminant);
|
||||||
|
|
||||||
|
procedure Search_Current_Instance is new
|
||||||
|
Traverse_Proc (Find_Current_Instance);
|
||||||
|
|
||||||
|
procedure Search_Internal_Call is new
|
||||||
|
Traverse_Proc (Find_Internal_Call);
|
||||||
|
|
||||||
|
-- Start of processing for Requires_Late_Init
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- A component of an object is said to require late initialization
|
||||||
|
-- if:
|
||||||
|
|
||||||
|
-- it has an access discriminant value constrained by a per-object
|
||||||
|
-- expression;
|
||||||
|
|
||||||
|
if Has_Access_Constraint (Defining_Identifier (Decl))
|
||||||
|
and then No (Expression (Decl))
|
||||||
|
then
|
||||||
|
return True;
|
||||||
|
|
||||||
|
elsif Present (Expression (Decl)) then
|
||||||
|
|
||||||
|
-- it has an initialization expression that includes a name
|
||||||
|
-- denoting an access discriminant;
|
||||||
|
|
||||||
|
Search_Access_Discriminant (Expression (Decl));
|
||||||
|
|
||||||
|
if Has_Access_Discriminant then
|
||||||
|
return True;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- or it has an initialization expression that includes a
|
||||||
|
-- reference to the current instance of the type either by
|
||||||
|
-- name...
|
||||||
|
|
||||||
|
Search_Current_Instance (Expression (Decl));
|
||||||
|
|
||||||
|
if References_Current_Instance then
|
||||||
|
return True;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- ...or implicitly as the target object of a call.
|
||||||
|
|
||||||
|
if Is_Protected_Record_Type (Rec_Type) then
|
||||||
|
Search_Internal_Call (Expression (Decl));
|
||||||
|
|
||||||
|
if Has_Internal_Call then
|
||||||
|
return True;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
return False;
|
||||||
|
end Requires_Late_Init;
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
-- Has_Late_Init_Component --
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
function Has_Late_Init_Component
|
||||||
|
(Tagged_Rec_Type : Entity_Id) return Boolean
|
||||||
|
is
|
||||||
|
Comp_Id : Entity_Id :=
|
||||||
|
First_Component (Implementation_Base_Type (Tagged_Rec_Type));
|
||||||
|
begin
|
||||||
|
while Present (Comp_Id) loop
|
||||||
|
if Requires_Late_Init (Decl => Parent (Comp_Id),
|
||||||
|
Rec_Type => Tagged_Rec_Type)
|
||||||
|
then
|
||||||
|
return True; -- found a component that requires late init
|
||||||
|
|
||||||
|
elsif Chars (Comp_Id) = Name_uParent
|
||||||
|
and then Has_Late_Init_Component (Etype (Comp_Id))
|
||||||
|
then
|
||||||
|
return True; -- an ancestor type has a late init component
|
||||||
|
end if;
|
||||||
|
|
||||||
|
Next_Component (Comp_Id);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
return False;
|
||||||
|
end Has_Late_Init_Component;
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
-- Tag_Init_Condition --
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
function Tag_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id is
|
||||||
|
begin
|
||||||
|
return Make_Op_Eq (Loc,
|
||||||
|
New_Occurrence_Of (Init_Control_Formal, Loc),
|
||||||
|
Make_Mode_Literal (Loc, Full_Init));
|
||||||
|
end Tag_Init_Condition;
|
||||||
|
|
||||||
|
--------------------------
|
||||||
|
-- Early_Init_Condition --
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
function Early_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id is
|
||||||
|
begin
|
||||||
|
return Make_Op_Ne (Loc,
|
||||||
|
New_Occurrence_Of (Init_Control_Formal, Loc),
|
||||||
|
Make_Mode_Literal (Loc, Late_Init_Only));
|
||||||
|
end Early_Init_Condition;
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
-- Late_Init_Condition --
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
function Late_Init_Condition
|
||||||
|
(Loc : Source_Ptr;
|
||||||
|
Init_Control_Formal : Entity_Id) return Node_Id is
|
||||||
|
begin
|
||||||
|
return Make_Op_Ne (Loc,
|
||||||
|
New_Occurrence_Of (Init_Control_Formal, Loc),
|
||||||
|
Make_Mode_Literal (Loc, Early_Init_Only));
|
||||||
|
end Late_Init_Condition;
|
||||||
|
|
||||||
|
end Initialization_Control;
|
||||||
|
|
||||||
----------------------------
|
----------------------------
|
||||||
-- Initialization_Warning --
|
-- Initialization_Warning --
|
||||||
----------------------------
|
----------------------------
|
||||||
|
@ -62,14 +62,15 @@ package Exp_Ch3 is
|
|||||||
-- and the discriminant checking functions are inserted after this node.
|
-- and the discriminant checking functions are inserted after this node.
|
||||||
|
|
||||||
function Build_Initialization_Call
|
function Build_Initialization_Call
|
||||||
(Loc : Source_Ptr;
|
(Loc : Source_Ptr;
|
||||||
Id_Ref : Node_Id;
|
Id_Ref : Node_Id;
|
||||||
Typ : Entity_Id;
|
Typ : Entity_Id;
|
||||||
In_Init_Proc : Boolean := False;
|
In_Init_Proc : Boolean := False;
|
||||||
Enclos_Type : Entity_Id := Empty;
|
Enclos_Type : Entity_Id := Empty;
|
||||||
Discr_Map : Elist_Id := New_Elmt_List;
|
Discr_Map : Elist_Id := New_Elmt_List;
|
||||||
With_Default_Init : Boolean := False;
|
With_Default_Init : Boolean := False;
|
||||||
Constructor_Ref : Node_Id := Empty) return List_Id;
|
Constructor_Ref : Node_Id := Empty;
|
||||||
|
Init_Control_Actual : Entity_Id := Empty) return List_Id;
|
||||||
-- Builds a call to the initialization procedure for the base type of Typ,
|
-- Builds a call to the initialization procedure for the base type of Typ,
|
||||||
-- passing it the object denoted by Id_Ref, plus additional parameters as
|
-- passing it the object denoted by Id_Ref, plus additional parameters as
|
||||||
-- appropriate for the type (the _Master, for task types, for example).
|
-- appropriate for the type (the _Master, for task types, for example).
|
||||||
@ -93,6 +94,12 @@ package Exp_Ch3 is
|
|||||||
--
|
--
|
||||||
-- Constructor_Ref is a call to a constructor subprogram. It is currently
|
-- Constructor_Ref is a call to a constructor subprogram. It is currently
|
||||||
-- used only to support C++ constructors.
|
-- used only to support C++ constructors.
|
||||||
|
--
|
||||||
|
-- Init_Control_Actual is Empty except in the case where the init proc
|
||||||
|
-- for a tagged type calls the init proc for its parent type in order
|
||||||
|
-- to initialize its _Parent component. In that case, it is the
|
||||||
|
-- actual parameter value corresponding to the Init_Control formal
|
||||||
|
-- parameter to be used in the call of the parent type's init proc.
|
||||||
|
|
||||||
function Build_Variant_Record_Equality
|
function Build_Variant_Record_Equality
|
||||||
(Typ : Entity_Id;
|
(Typ : Entity_Id;
|
||||||
|
@ -4377,6 +4377,12 @@ package body Exp_Util is
|
|||||||
and then
|
and then
|
||||||
Nkind (Expression (Parent (Id_Ref))) = N_Allocator;
|
Nkind (Expression (Parent (Id_Ref))) = N_Allocator;
|
||||||
|
|
||||||
|
Component_Suffix_Index : constant Int :=
|
||||||
|
(if In_Init_Proc then -1 else 0);
|
||||||
|
-- If an init proc calls Build_Task_Image_Decls twice for its
|
||||||
|
-- _Parent component (to split early/late initialization), we don't
|
||||||
|
-- want two decls with the same name. Hence, the -1 suffix.
|
||||||
|
|
||||||
begin
|
begin
|
||||||
-- If Discard_Names or No_Implicit_Heap_Allocations are in effect,
|
-- If Discard_Names or No_Implicit_Heap_Allocations are in effect,
|
||||||
-- generate a dummy declaration only.
|
-- generate a dummy declaration only.
|
||||||
@ -4418,7 +4424,8 @@ package body Exp_Util is
|
|||||||
elsif Nkind (Id_Ref) = N_Selected_Component then
|
elsif Nkind (Id_Ref) = N_Selected_Component then
|
||||||
T_Id :=
|
T_Id :=
|
||||||
Make_Defining_Identifier (Loc,
|
Make_Defining_Identifier (Loc,
|
||||||
New_External_Name (Chars (Selector_Name (Id_Ref)), 'T'));
|
New_External_Name (Chars (Selector_Name (Id_Ref)), 'T',
|
||||||
|
Suffix_Index => Component_Suffix_Index));
|
||||||
Fun := Build_Task_Record_Image (Loc, Id_Ref, Is_Dyn);
|
Fun := Build_Task_Record_Image (Loc, Id_Ref, Is_Dyn);
|
||||||
|
|
||||||
elsif Nkind (Id_Ref) = N_Indexed_Component then
|
elsif Nkind (Id_Ref) = N_Indexed_Component then
|
||||||
|
Loading…
Reference in New Issue
Block a user