aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada')
-rw-r--r--gcc/ada/einfo.ads8
-rw-r--r--gcc/ada/exp_ch4.adb4
-rw-r--r--gcc/ada/exp_ch7.adb804
-rw-r--r--gcc/ada/exp_ch7.ads7
-rw-r--r--gcc/ada/exp_util.adb7
-rw-r--r--gcc/ada/gen_il-fields.ads2
-rw-r--r--gcc/ada/gen_il-gen-gen_entities.adb2
-rw-r--r--gcc/ada/libgnat/s-finpri.adb32
-rw-r--r--gcc/ada/libgnat/s-finpri.ads12
-rw-r--r--gcc/ada/rtsfind.ads2
10 files changed, 500 insertions, 380 deletions
diff --git a/gcc/ada/einfo.ads b/gcc/ada/einfo.ads
index 2496400..6f563d5 100644
--- a/gcc/ada/einfo.ads
+++ b/gcc/ada/einfo.ads
@@ -1305,15 +1305,13 @@ package Einfo is
-- type. Empty for access-to-subprogram types. Empty for access types
-- whose designated type does not need finalization actions.
--- Finalization_Master_Node_Or_Object
+-- Finalization_Master_Node
-- Defined in variables and constants that require finalization actions.
-- The field contains the entity of an object (called a Master_Node) that
-- contains the address of the finalizable object, along with an access
-- value denoting the finalizable object's finalization procedure. The
-- Master_Node may be attached to a finalization list associated with
-- either the global scope or some dynamic scope (block or subprogram).
--- Conversely, for a Master_Node entity, the field contains the entity
--- of the finalizable object.
-- Finalize_Storage_Only [base type only]
-- Defined in all types. Set on direct controlled types to which a
@@ -5304,7 +5302,7 @@ package Einfo is
-- Related_Type (constants only)
-- Initialization_Statements
-- BIP_Initialization_Call
- -- Finalization_Master_Node_Or_Object
+ -- Finalization_Master_Node
-- Last_Aggregate_Assignment
-- Activation_Record_Component
-- Encapsulating_State (constants only)
@@ -6191,7 +6189,7 @@ package Einfo is
-- Related_Type
-- Initialization_Statements
-- BIP_Initialization_Call
- -- Finalization_Master_Node_Or_Object
+ -- Finalization_Master_Node
-- Last_Aggregate_Assignment
-- Activation_Record_Component
-- Encapsulating_State
diff --git a/gcc/ada/exp_ch4.adb b/gcc/ada/exp_ch4.adb
index dd64705..5fa47c9 100644
--- a/gcc/ada/exp_ch4.adb
+++ b/gcc/ada/exp_ch4.adb
@@ -14980,6 +14980,10 @@ package body Exp_Ch4 is
Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj_Id);
Insert_Action (Hook_Context, Master_Node_Decl);
+ -- Generate the attachment of the object to the Master_Node
+
+ Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id);
+
-- When the node is part of a return statement, there is no need
-- to insert a finalization call, as the general finalization
-- mechanism (see Build_Finalizer) would take care of the master
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 4382de9..7a84576 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -515,6 +515,13 @@ package body Exp_Ch7 is
-- of the formal of Proc, or force a conversion to the class-wide type in
-- the case where the operation is abstract.
+ function Make_Address_For_Finalize
+ (Loc : Source_Ptr;
+ Obj_Ref : Node_Id;
+ Obj_Typ : Entity_Id) return Node_Id;
+ -- Build the address of an object denoted by Obj_Ref and Obj_Typ for use as
+ -- the actual parameter in a call to a Finalize_Address procedure.
+
function Make_Call
(Loc : Source_Ptr;
Proc_Id : Entity_Id;
@@ -562,6 +569,327 @@ package body Exp_Ch7 is
-- [Deep_]Finalize (Acc_Typ (V).all);
-- end;
+ ----------------------------------
+ -- Attach_Object_To_Master_Node --
+ ----------------------------------
+
+ procedure Attach_Object_To_Master_Node
+ (Obj_Decl : Node_Id;
+ Master_Node : Entity_Id)
+ is
+ Loc : constant Source_Ptr := Sloc (Obj_Decl);
+ Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
+ Func_Id : constant Entity_Id :=
+ (if Is_Return_Object (Obj_Id)
+ then Return_Applies_To (Scope (Obj_Id))
+ else Empty);
+
+ function Build_BIP_Cleanup_Stmts
+ (Func_Id : Entity_Id;
+ Obj_Addr : Node_Id) return Node_Id;
+ -- Func_Id denotes a build-in-place function. Generate the following
+ -- cleanup code:
+ --
+ -- if BIPallocform > Secondary_Stack'Pos
+ -- and then BIPfinalizationmaster /= null
+ -- then
+ -- declare
+ -- type Ptr_Typ is access Fun_Typ;
+ -- for Ptr_Typ'Storage_Pool
+ -- use Base_Pool (BIPfinalizationmaster);
+ -- begin
+ -- Free (Ptr_Typ (Obj_Addr));
+ -- end;
+ -- end if;
+ --
+ -- Fun_Typ is the return type of the Func_Id.
+
+ -----------------------------
+ -- Build_BIP_Cleanup_Stmts --
+ -----------------------------
+
+ function Build_BIP_Cleanup_Stmts
+ (Func_Id : Entity_Id;
+ Obj_Addr : Node_Id) return Node_Id
+ is
+ Decls : constant List_Id := New_List;
+ Fin_Mas_Id : constant Entity_Id :=
+ Build_In_Place_Formal
+ (Func_Id, BIP_Finalization_Master);
+ Func_Typ : constant Entity_Id := Etype (Func_Id);
+
+ Cond : Node_Id;
+ Free_Blk : Node_Id;
+ Free_Stmt : Node_Id;
+ Pool_Id : Entity_Id;
+ Ptr_Typ : Entity_Id;
+
+ begin
+ -- Generate:
+ -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
+
+ Pool_Id := Make_Temporary (Loc, 'P');
+
+ Append_To (Decls,
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Pool_Id,
+ Subtype_Mark =>
+ New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Base_Pool), Loc),
+ Parameter_Associations => New_List (
+ Make_Explicit_Dereference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Fin_Mas_Id, Loc)))))));
+
+ -- Create an access type which uses the storage pool of the
+ -- caller's finalization master.
+
+ -- Generate:
+ -- type Ptr_Typ is access Func_Typ;
+
+ Ptr_Typ := Make_Temporary (Loc, 'P');
+
+ Append_To (Decls,
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Ptr_Typ,
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
+
+ -- Perform minor decoration in order to set the master and the
+ -- storage pool attributes.
+
+ Mutate_Ekind (Ptr_Typ, E_Access_Type);
+ Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
+ Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
+
+ if Debug_Generated_Code then
+ Set_Debug_Info_Needed (Pool_Id);
+ end if;
+
+ -- Create an explicit free statement. Note that the free uses the
+ -- caller's pool expressed as a renaming.
+
+ Free_Stmt :=
+ Make_Free_Statement (Loc,
+ Expression =>
+ Unchecked_Convert_To (Ptr_Typ, Obj_Addr));
+
+ Set_Storage_Pool (Free_Stmt, Pool_Id);
+
+ -- Create a block to house the dummy type and the instantiation as
+ -- well as to perform the cleanup the temporary.
+
+ -- Generate:
+ -- declare
+ -- <Decls>
+ -- begin
+ -- Free (Ptr_Typ (Obj_Addr));
+ -- end;
+
+ Free_Blk :=
+ Make_Block_Statement (Loc,
+ Declarations => Decls,
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => New_List (Free_Stmt)));
+
+ -- Generate:
+ -- if BIPfinalizationmaster /= null then
+
+ Cond :=
+ Make_Op_Ne (Loc,
+ Left_Opnd => New_Occurrence_Of (Fin_Mas_Id, Loc),
+ Right_Opnd => Make_Null (Loc));
+
+ -- For unconstrained or tagged results, escalate the condition to
+ -- include the allocation format. Generate:
+
+ -- if BIPallocform > Secondary_Stack'Pos
+ -- and then BIPfinalizationmaster /= null
+ -- then
+
+ if Needs_BIP_Alloc_Form (Func_Id) then
+ declare
+ Alloc : constant Entity_Id :=
+ Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
+ begin
+ Cond :=
+ Make_And_Then (Loc,
+ Left_Opnd =>
+ Make_Op_Gt (Loc,
+ Left_Opnd => New_Occurrence_Of (Alloc, Loc),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc,
+ UI_From_Int
+ (BIP_Allocation_Form'Pos (Secondary_Stack)))),
+
+ Right_Opnd => Cond);
+ end;
+ end if;
+
+ -- Generate:
+ -- if <Cond> then
+ -- <Free_Blk>
+ -- end if;
+
+ return
+ Make_If_Statement (Loc,
+ Condition => Cond,
+ Then_Statements => New_List (Free_Blk));
+ end Build_BIP_Cleanup_Stmts;
+
+ Fin_Id : Entity_Id;
+ Master_Node_Attach : Node_Id;
+ Master_Node_Ins : Node_Id;
+ Obj_Ref : Node_Id;
+ Obj_Typ : Entity_Id;
+
+ begin
+ -- Finalize_Address is not generated in CodePeer mode because the
+ -- body contains address arithmetic. So we don't want to generate
+ -- the attach in this case.
+
+ if CodePeer_Mode then
+ return;
+ end if;
+
+ -- When the transient object is initialized by an aggregate, the
+ -- attachment must occur after the last aggregate assignment takes
+ -- place. Only then is the object considered initialized. Likewise
+ -- if we have a build-in-place call: we must attach only after it.
+
+ if Ekind (Obj_Id) in E_Constant | E_Variable then
+ if Present (Last_Aggregate_Assignment (Obj_Id)) then
+ Master_Node_Ins := Last_Aggregate_Assignment (Obj_Id);
+ elsif Present (BIP_Initialization_Call (Obj_Id)) then
+ Master_Node_Ins := BIP_Initialization_Call (Obj_Id);
+ else
+ Master_Node_Ins := Obj_Decl;
+ end if;
+
+ else
+ Master_Node_Ins := Obj_Decl;
+ end if;
+
+ -- Handle the object type and the reference to the object
+
+ Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
+ Obj_Typ := Etype (Obj_Id);
+ if not Is_Class_Wide_Type (Obj_Typ) then
+ Obj_Typ := Base_Type (Obj_Typ);
+ end if;
+
+ if Is_Access_Type (Obj_Typ) then
+ Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
+ Obj_Typ := Available_View (Designated_Type (Obj_Typ));
+ end if;
+
+ -- If we are dealing with a return object of a build-in-place
+ -- function, generate the following cleanup statements:
+
+ -- if BIPallocform > Secondary_Stack'Pos
+ -- and then BIPfinalizationmaster /= null
+ -- then
+ -- declare
+ -- type Ptr_Typ is access Obj_Typ;
+ -- for Ptr_Typ'Storage_Pool use
+ -- Base_Pool (BIPfinalizationmaster.all).all;
+ -- begin
+ -- Free (Ptr_Typ (Obj'Address));
+ -- end;
+ -- end if;
+
+ -- The generated code effectively detaches the temporary from the
+ -- caller finalization master and deallocates the object.
+
+ if Present (Func_Id)
+ and then Is_Build_In_Place_Function (Func_Id)
+ and then Needs_BIP_Finalization_Master (Func_Id)
+ then
+ declare
+ Ptr_Typ : constant Node_Id := Make_Temporary (Loc, 'P');
+ Param : constant Entity_Id :=
+ Make_Defining_Identifier (Loc, Name_V);
+
+ Fin_Body : Node_Id;
+ Fin_Stmts : List_Id;
+
+ begin
+ Fin_Stmts := Make_Finalize_Address_Stmts (Obj_Typ);
+
+ Append_To (Fin_Stmts,
+ Build_BIP_Cleanup_Stmts
+ (Func_Id, New_Occurrence_Of (Param, Loc)));
+
+ Fin_Id :=
+ Make_Defining_Identifier (Loc,
+ Make_TSS_Name_Local
+ (Obj_Typ, TSS_Finalize_Address));
+
+ Fin_Body :=
+ Make_Subprogram_Body (Loc,
+ Specification =>
+ Make_Procedure_Specification (Loc,
+ Defining_Unit_Name => Fin_Id,
+
+ Parameter_Specifications => New_List (
+ Make_Parameter_Specification (Loc,
+ Defining_Identifier => Param,
+ Parameter_Type =>
+ New_Occurrence_Of (RTE (RE_Address), Loc)))),
+
+ Declarations => New_List (
+ Make_Full_Type_Declaration (Loc,
+ Defining_Identifier => Ptr_Typ,
+ Type_Definition =>
+ Make_Access_To_Object_Definition (Loc,
+ All_Present => True,
+ Subtype_Indication =>
+ New_Occurrence_Of (Obj_Typ, Loc)))),
+
+ Handled_Statement_Sequence =>
+ Make_Handled_Sequence_Of_Statements (Loc,
+ Statements => Fin_Stmts));
+
+ Insert_After_And_Analyze
+ (Master_Node_Ins, Fin_Body, Suppress => All_Checks);
+
+ Master_Node_Ins := Fin_Body;
+ end;
+
+ else
+ Fin_Id := Finalize_Address (Obj_Typ);
+
+ if No (Fin_Id) and then Ekind (Obj_Typ) = E_Class_Wide_Subtype then
+ Fin_Id := TSS (Obj_Typ, TSS_Finalize_Address);
+ end if;
+ end if;
+
+ -- Now build the attachment call that will initialize the object's
+ -- Master_Node using the object's address and finalization procedure.
+
+ Master_Node_Attach :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Attach_Object_To_Node), Loc),
+ Parameter_Associations => New_List (
+ Make_Address_For_Finalize (Loc, Obj_Ref, Obj_Typ),
+ Make_Attribute_Reference (Loc,
+ Prefix =>
+ New_Occurrence_Of (Fin_Id, Loc),
+ Attribute_Name => Name_Unrestricted_Access),
+ New_Occurrence_Of (Master_Node, Loc)));
+
+ Insert_After_And_Analyze
+ (Master_Node_Ins, Master_Node_Attach, Suppress => All_Checks);
+ end Attach_Object_To_Master_Node;
+
--------------------------------
-- Allows_Finalization_Master --
--------------------------------
@@ -2152,11 +2480,10 @@ package body Exp_Ch7 is
-- Conversely, if one of the above cases created a Master_Node,
-- finalization actions are required for the associated object.
- -- Note that we need to make sure that we will not process both
- -- the Master_Node and the associated object here.
- elsif Present (Finalization_Master_Node_Or_Object (Obj_Id)) then
- pragma Assert (Is_RTE (Obj_Typ, RE_Master_Node));
+ elsif Ekind (Obj_Id) = E_Variable
+ and then Is_RTE (Obj_Typ, RE_Master_Node)
+ then
Processing_Actions (Decl);
-- Ignored Ghost objects do not need any cleanup actions
@@ -2335,17 +2662,8 @@ package body Exp_Ch7 is
(Decl : Node_Id;
Is_Protected : Boolean := False)
is
- Def_Id : constant Entity_Id := Defining_Identifier (Decl);
- Obj_Id : constant Entity_Id :=
- (if Is_RTE (Etype (Def_Id), RE_Master_Node)
- then Finalization_Master_Node_Or_Object (Def_Id)
- else Def_Id);
- Obj_Decl : constant Entity_Id := Declaration_Node (Obj_Id);
- Func_Id : constant Entity_Id :=
- (if Is_Return_Object (Obj_Id)
- then Return_Applies_To (Scope (Obj_Id))
- else Empty);
- Loc : constant Source_Ptr := Sloc (Obj_Decl);
+ Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
+ Loc : constant Source_Ptr := Sloc (Decl);
Init_Typ : Entity_Id;
-- The initialization type of the related object declaration. Note
@@ -2355,26 +2673,6 @@ package body Exp_Ch7 is
Obj_Typ : Entity_Id;
-- The type of the related object declaration
- function Build_BIP_Cleanup_Stmts
- (Func_Id : Entity_Id;
- Obj_Addr : Node_Id) return Node_Id;
- -- Func_Id denotes a build-in-place function. Generate the following
- -- cleanup code:
- --
- -- if BIPallocfrom > Secondary_Stack'Pos
- -- and then BIPfinalizationmaster /= null
- -- then
- -- declare
- -- type Ptr_Typ is access Fun_Typ;
- -- for Ptr_Typ'Storage_Pool
- -- use Base_Pool (BIPfinalizationmaster);
- -- begin
- -- Free (Ptr_Typ (Obj_Addr));
- -- end;
- -- end if;
- --
- -- Fun_Typ is the return type of the Func_Id.
-
procedure Find_Last_Init
(Last_Init : out Node_Id;
Body_Insert : out Node_Id);
@@ -2383,153 +2681,6 @@ package body Exp_Ch7 is
-- Decl. Body_Insert denotes a node where the finalizer body could be
-- potentially inserted after (if blocks are involved).
- function Make_Address_For_Finalize
- (Loc : Source_Ptr;
- Obj_Ref : Node_Id;
- Obj_Typ : Entity_Id) return Node_Id;
- -- Build the address of an object denoted by Obj_Ref and Obj_Typ for
- -- use as actual parameter in a call to a Finalize_Address procedure.
-
- -----------------------------
- -- Build_BIP_Cleanup_Stmts --
- -----------------------------
-
- function Build_BIP_Cleanup_Stmts
- (Func_Id : Entity_Id;
- Obj_Addr : Node_Id) return Node_Id
- is
- Decls : constant List_Id := New_List;
- Fin_Mas_Id : constant Entity_Id :=
- Build_In_Place_Formal
- (Func_Id, BIP_Finalization_Master);
- Func_Typ : constant Entity_Id := Etype (Func_Id);
-
- Cond : Node_Id;
- Free_Blk : Node_Id;
- Free_Stmt : Node_Id;
- Pool_Id : Entity_Id;
- Ptr_Typ : Entity_Id;
-
- begin
- -- Generate:
- -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
-
- Pool_Id := Make_Temporary (Loc, 'P');
-
- Append_To (Decls,
- Make_Object_Renaming_Declaration (Loc,
- Defining_Identifier => Pool_Id,
- Subtype_Mark =>
- New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
- Name =>
- Make_Explicit_Dereference (Loc,
- Prefix =>
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Base_Pool), Loc),
- Parameter_Associations => New_List (
- Make_Explicit_Dereference (Loc,
- Prefix =>
- New_Occurrence_Of (Fin_Mas_Id, Loc)))))));
-
- -- Create an access type which uses the storage pool of the
- -- caller's finalization master.
-
- -- Generate:
- -- type Ptr_Typ is access Func_Typ;
-
- Ptr_Typ := Make_Temporary (Loc, 'P');
-
- Append_To (Decls,
- Make_Full_Type_Declaration (Loc,
- Defining_Identifier => Ptr_Typ,
- Type_Definition =>
- Make_Access_To_Object_Definition (Loc,
- Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
-
- -- Perform minor decoration in order to set the master and the
- -- storage pool attributes.
-
- Mutate_Ekind (Ptr_Typ, E_Access_Type);
- Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
- Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
-
- if Debug_Generated_Code then
- Set_Debug_Info_Needed (Pool_Id);
- end if;
-
- -- Create an explicit free statement. Note that the free uses the
- -- caller's pool expressed as a renaming.
-
- Free_Stmt :=
- Make_Free_Statement (Loc,
- Expression =>
- Unchecked_Convert_To (Ptr_Typ, Obj_Addr));
-
- Set_Storage_Pool (Free_Stmt, Pool_Id);
-
- -- Create a block to house the dummy type and the instantiation as
- -- well as to perform the cleanup the temporary.
-
- -- Generate:
- -- declare
- -- <Decls>
- -- begin
- -- Free (Ptr_Typ (Obj_Addr));
- -- end;
-
- Free_Blk :=
- Make_Block_Statement (Loc,
- Declarations => Decls,
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => New_List (Free_Stmt)));
-
- -- Generate:
- -- if BIPfinalizationmaster /= null then
-
- Cond :=
- Make_Op_Ne (Loc,
- Left_Opnd => New_Occurrence_Of (Fin_Mas_Id, Loc),
- Right_Opnd => Make_Null (Loc));
-
- -- For unconstrained or tagged results, escalate the condition to
- -- include the allocation format. Generate:
-
- -- if BIPallocform > Secondary_Stack'Pos
- -- and then BIPfinalizationmaster /= null
- -- then
-
- if Needs_BIP_Alloc_Form (Func_Id) then
- declare
- Alloc : constant Entity_Id :=
- Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
- begin
- Cond :=
- Make_And_Then (Loc,
- Left_Opnd =>
- Make_Op_Gt (Loc,
- Left_Opnd => New_Occurrence_Of (Alloc, Loc),
- Right_Opnd =>
- Make_Integer_Literal (Loc,
- UI_From_Int
- (BIP_Allocation_Form'Pos (Secondary_Stack)))),
-
- Right_Opnd => Cond);
- end;
- end if;
-
- -- Generate:
- -- if <Cond> then
- -- <Free_Blk>
- -- end if;
-
- return
- Make_If_Statement (Loc,
- Condition => Cond,
- Then_Statements => New_List (Free_Blk));
- end Build_BIP_Cleanup_Stmts;
-
--------------------
-- Find_Last_Init --
--------------------
@@ -2696,14 +2847,14 @@ package body Exp_Ch7 is
-- Start of processing for Find_Last_Init
begin
- Last_Init := Obj_Decl;
+ Last_Init := Decl;
Body_Insert := Empty;
-- Objects that capture controlled function results do not require
-- initialization.
- if Nkind (Obj_Decl) = N_Object_Declaration
- and then Nkind (Expression (Obj_Decl)) = N_Reference
+ if Nkind (Decl) = N_Object_Declaration
+ and then Nkind (Expression (Decl)) = N_Reference
then
return;
end if;
@@ -2712,7 +2863,7 @@ package body Exp_Ch7 is
Stmt := First (Actions (Freeze_Node (Obj_Id)));
Body_Insert := Freeze_Node (Obj_Id);
else
- Stmt := Next_Suitable_Statement (Obj_Decl);
+ Stmt := Next_Suitable_Statement (Decl);
end if;
-- For an object with suppressed initialization, we check whether
@@ -2725,8 +2876,8 @@ package body Exp_Ch7 is
-- call raises an exception, we will finalize the (uninitialized)
-- object, which is wrong.
- if Nkind (Obj_Decl) = N_Object_Declaration
- and then No_Initialization (Obj_Decl)
+ if Nkind (Decl) = N_Object_Declaration
+ and then No_Initialization (Decl)
then
if No (Expression (Last_Init)) then
loop
@@ -2811,61 +2962,6 @@ package body Exp_Ch7 is
end if;
end Find_Last_Init;
- -------------------------------
- -- Make_Address_For_Finalize --
- -------------------------------
-
- function Make_Address_For_Finalize
- (Loc : Source_Ptr;
- Obj_Ref : Node_Id;
- Obj_Typ : Entity_Id) return Node_Id
- is
- Obj_Addr : Node_Id;
-
- begin
- Obj_Addr :=
- Make_Attribute_Reference (Loc,
- Prefix => Obj_Ref,
- Attribute_Name => Name_Address);
-
- -- If the type of a constrained array has an unconstrained first
- -- subtype, its Finalize_Address primitive expects the address of
- -- an object with a dope vector (see Make_Finalize_Address_Stmts).
- -- This is achieved by setting Is_Constr_Subt_For_UN_Aliased, but
- -- the address of the object is still that of its elements, so we
- -- need to shift it.
-
- if Is_Array_Type (Obj_Typ)
- and then not Is_Constrained (First_Subtype (Obj_Typ))
- then
- -- Shift the address from the start of the elements to the
- -- start of the dope vector:
-
- -- V - (Obj_Typ'Descriptor_Size / Storage_Unit)
-
- -- Note that this is done through a wrapper routine as RTSfind
- -- cannot retrieve operations with string name of the form "+".
-
- Obj_Addr :=
- Make_Function_Call (Loc,
- Name =>
- New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
- Parameter_Associations => New_List (
- Obj_Addr,
- Make_Op_Minus (Loc,
- Make_Op_Divide (Loc,
- Left_Opnd =>
- Make_Attribute_Reference (Loc,
- Prefix =>
- New_Occurrence_Of (Obj_Typ, Loc),
- Attribute_Name => Name_Descriptor_Size),
- Right_Opnd =>
- Make_Integer_Literal (Loc, System_Storage_Unit)))));
- end if;
-
- return Obj_Addr;
- end Make_Address_For_Finalize;
-
-- Local variables
Body_Ins : Node_Id;
@@ -2913,30 +3009,31 @@ package body Exp_Ch7 is
end if;
end loop;
- -- Create the declaration of the Master_Node for the object and
- -- insert it before the declaration of the object itself, except
- -- for the case where it is the only object because it will play
- -- the role of a degenerated scope master and therefore needs to
- -- inserted at the same place the scope master would have been.
+ -- If the object is a Master_Node, then nothing to do, except if it
+ -- is the only object, in which case we move its declaration, call
+ -- marker (if any) and initialization call, as well as mark it to
+ -- avoid double processing.
- if Present (Finalization_Master_Node_Or_Object (Obj_Id)) then
- Master_Node_Id := Finalization_Master_Node_Or_Object (Obj_Id);
-
- -- Move declaration, call marker if any and initialization call
- -- and mark the Master_Node to avoid double processing
+ if Is_RTE (Obj_Typ, RE_Master_Node) then
+ Master_Node_Id := Obj_Id;
if Counter_Val = 1 then
- Master_Node_Decl := Declaration_Node (Master_Node_Id);
- if Nkind (Next (Master_Node_Decl)) = N_Call_Marker then
- Prepend_To (Decls, Remove_Next (Next (Master_Node_Decl)));
+ if Nkind (Next (Decl)) = N_Call_Marker then
+ Prepend_To (Decls, Remove_Next (Next (Decl)));
end if;
- Prepend_To (Decls, Remove_Next (Master_Node_Decl));
- Remove (Master_Node_Decl);
- Prepend_To (Decls, Master_Node_Decl);
- Set_Is_Ignored_For_Finalization (Master_Node_Id);
+ Prepend_To (Decls, Remove_Next (Decl));
+ Remove (Decl);
+ Prepend_To (Decls, Decl);
+ Set_Is_Ignored_For_Finalization (Obj_Id);
end if;
- else
+ -- Create the declaration of the Master_Node for the object and
+ -- insert it before the declaration of the object itself, except
+ -- for the case where it is the only object because it will play
+ -- the role of a degenerated scope master and therefore needs to
+ -- be inserted at the same place the scope master would have been.
+
+ else pragma Assert (No (Finalization_Master_Node (Obj_Id)));
-- For one object, use the Sloc the scope master would have had
if Counter_Val = 1 then
@@ -2956,7 +3053,7 @@ package body Exp_Ch7 is
if Counter_Val = 1 then
Prepend_To (Decls, Master_Node_Decl);
else
- Insert_Before (Obj_Decl, Master_Node_Decl);
+ Insert_Before (Decl, Master_Node_Decl);
end if;
Analyze (Master_Node_Decl);
Pop_Scope;
@@ -3004,7 +3101,7 @@ package body Exp_Ch7 is
-- of the Master_Node after the declaration of the object itself.
if No (Master_Node_Ins) then
- Master_Node_Ins := Obj_Decl;
+ Master_Node_Ins := Decl;
end if;
-- Processing for simple protected objects. Such objects require
@@ -3041,17 +3138,17 @@ package body Exp_Ch7 is
Set_Etype (Ren_Ref, Obj_Typ);
if Is_Simple_Protected_Type (Obj_Typ) then
- Fin_Call := Cleanup_Protected_Object (Obj_Decl, Ren_Ref);
+ Fin_Call := Cleanup_Protected_Object (Decl, Ren_Ref);
if Present (Fin_Call) then
Fin_Stmts := New_List (Fin_Call);
end if;
elsif Is_Array_Type (Obj_Typ) then
- Fin_Stmts := Cleanup_Array (Obj_Decl, Ren_Ref, Obj_Typ);
+ Fin_Stmts := Cleanup_Array (Decl, Ren_Ref, Obj_Typ);
else
- Fin_Stmts := Cleanup_Record (Obj_Decl, Ren_Ref, Obj_Typ);
+ Fin_Stmts := Cleanup_Record (Decl, Ren_Ref, Obj_Typ);
end if;
if No (Fin_Stmts) then
@@ -3116,81 +3213,6 @@ package body Exp_Ch7 is
Master_Node_Ins := Fin_Body;
end;
- -- If we are dealing with a return object of a build-in-place
- -- function, generate the following cleanup statements:
-
- -- if BIPallocfrom > Secondary_Stack'Pos
- -- and then BIPfinalizationmaster /= null
- -- then
- -- declare
- -- type Ptr_Typ is access Obj_Typ;
- -- for Ptr_Typ'Storage_Pool use
- -- Base_Pool (BIPfinalizationmaster.all).all;
- -- begin
- -- Free (Ptr_Typ (Obj'Address));
- -- end;
- -- end if;
-
- -- The generated code effectively detaches the temporary from the
- -- caller finalization master and deallocates the object.
-
- elsif Present (Func_Id)
- and then Is_Build_In_Place_Function (Func_Id)
- and then Needs_BIP_Finalization_Master (Func_Id)
- then
- declare
- Ptr_Typ : constant Node_Id := Make_Temporary (Loc, 'P');
- Param : constant Entity_Id :=
- Make_Defining_Identifier (Loc, Name_V);
-
- Fin_Body : Node_Id;
- Fin_Stmts : List_Id;
-
- begin
- Fin_Stmts := Make_Finalize_Address_Stmts (Obj_Typ);
-
- Append_To (Fin_Stmts,
- Build_BIP_Cleanup_Stmts
- (Func_Id, New_Occurrence_Of (Param, Loc)));
-
- Fin_Id :=
- Make_Defining_Identifier (Loc,
- Make_TSS_Name_Local
- (Obj_Typ, TSS_Finalize_Address));
-
- Fin_Body :=
- Make_Subprogram_Body (Loc,
- Specification =>
- Make_Procedure_Specification (Loc,
- Defining_Unit_Name => Fin_Id,
-
- Parameter_Specifications => New_List (
- Make_Parameter_Specification (Loc,
- Defining_Identifier => Param,
- Parameter_Type =>
- New_Occurrence_Of (RTE (RE_Address), Loc)))),
-
- Declarations => New_List (
- Make_Full_Type_Declaration (Loc,
- Defining_Identifier => Ptr_Typ,
- Type_Definition =>
- Make_Access_To_Object_Definition (Loc,
- All_Present => True,
- Subtype_Indication =>
- New_Occurrence_Of (Obj_Typ, Loc)))),
-
- Handled_Statement_Sequence =>
- Make_Handled_Sequence_Of_Statements (Loc,
- Statements => Fin_Stmts));
-
- Push_Scope (Scope (Obj_Id));
- Insert_After_And_Analyze
- (Master_Node_Ins, Fin_Body, Suppress => All_Checks);
- Pop_Scope;
-
- Master_Node_Ins := Fin_Body;
- end;
-
else
Fin_Id := Finalize_Address (Obj_Typ);
@@ -3207,9 +3229,9 @@ package body Exp_Ch7 is
if Counter_Val = 1 then
-- Finalize_Address is not generated in CodePeer mode because the
-- body contains address arithmetic. So we don't want to generate
- -- the attach in this case.
+ -- the attach in this case. Ditto if the object is a Master_Node.
- if CodePeer_Mode then
+ if CodePeer_Mode or else Obj_Id = Master_Node_Id then
Master_Node_Attach := Make_Null_Statement (Loc);
else
Master_Node_Attach :=
@@ -3257,12 +3279,26 @@ package body Exp_Ch7 is
end if;
Append_To (Finalizer_Stmts, Fin_Call);
+
else
+ -- If the object is a Master_Node, we just need to chain it
+
+ if Obj_Id = Master_Node_Id then
+ Master_Node_Attach :=
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Chain_Node_To_Master), Loc),
+ Parameter_Associations => New_List (
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Obj_Id, Loc),
+ Attribute_Name => Name_Unrestricted_Access),
+ New_Occurrence_Of (Finalization_Scope_Master, Loc)));
+
-- Finalize_Address is not generated in CodePeer mode because the
-- body contains address arithmetic. So we don't want to generate
-- the attach in this case.
- if CodePeer_Mode then
+ elsif CodePeer_Mode then
Master_Node_Attach := Make_Null_Statement (Loc);
else
Master_Node_Attach :=
@@ -5390,8 +5426,7 @@ package body Exp_Ch7 is
begin
-- If the object needs to be exported to the outer finalizer,
-- create the declaration of the Master_Node for the object,
- -- which will later be picked up by Build_Finalizer. Then add
- -- the finalization call for the object.
+ -- which will later be picked up by Build_Finalizer.
if Must_Export then
Master_Node_Id := Make_Temporary (Loc, 'N');
@@ -5399,6 +5434,12 @@ package body Exp_Ch7 is
Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj_Id);
Insert_Before_And_Analyze (Obj_Decl, Master_Node_Decl);
+ -- Generate the attachment of the object to the Master_Node
+
+ Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id);
+
+ -- Then add the finalization call for the object
+
Insert_After_And_Analyze (Insert_Nod,
Make_Procedure_Call_Statement (Loc,
Name =>
@@ -5624,6 +5665,60 @@ package body Exp_Ch7 is
and then Is_RTE (Find_Protection_Type (T), RE_Protection);
end Is_Simple_Protected_Type;
+ -------------------------------
+ -- Make_Address_For_Finalize --
+ -------------------------------
+
+ function Make_Address_For_Finalize
+ (Loc : Source_Ptr;
+ Obj_Ref : Node_Id;
+ Obj_Typ : Entity_Id) return Node_Id
+ is
+ Obj_Addr : Node_Id;
+
+ begin
+ Obj_Addr :=
+ Make_Attribute_Reference (Loc,
+ Prefix => Obj_Ref,
+ Attribute_Name => Name_Address);
+
+ -- If the type of a constrained array has an unconstrained first
+ -- subtype, its Finalize_Address primitive expects the address of
+ -- an object with a dope vector (see Make_Finalize_Address_Stmts).
+ -- This is achieved by setting Is_Constr_Array_Subt_With_Bounds,
+ -- but the address of the object is still that of its elements,
+ -- so we need to shift it.
+
+ if Is_Array_Type (Obj_Typ)
+ and then not Is_Constrained (First_Subtype (Obj_Typ))
+ then
+ -- Shift the address from the start of the elements to the
+ -- start of the dope vector:
+
+ -- V - (Obj_Typ'Descriptor_Size / Storage_Unit)
+
+ -- Note that this is done through a wrapper routine as RTSfind
+ -- cannot retrieve operations with string name of the form "+".
+
+ Obj_Addr :=
+ Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
+ Parameter_Associations => New_List (
+ Obj_Addr,
+ Make_Op_Minus (Loc,
+ Make_Op_Divide (Loc,
+ Left_Opnd =>
+ Make_Attribute_Reference (Loc,
+ Prefix => New_Occurrence_Of (Obj_Typ, Loc),
+ Attribute_Name => Name_Descriptor_Size),
+ Right_Opnd =>
+ Make_Integer_Literal (Loc, System_Storage_Unit)))));
+ end if;
+
+ return Obj_Addr;
+ end Make_Address_For_Finalize;
+
-----------------------
-- Make_Adjust_Call --
-----------------------
@@ -8644,10 +8739,7 @@ package body Exp_Ch7 is
Obj : Entity_Id) return Node_Id
is
begin
- Set_Finalization_Master_Node_Or_Object (Obj, Master_Node);
-
- Mutate_Ekind (Master_Node, E_Variable);
- Set_Finalization_Master_Node_Or_Object (Master_Node, Obj);
+ Set_Finalization_Master_Node (Obj, Master_Node);
return
Make_Object_Declaration (Loc,
@@ -8707,6 +8799,8 @@ package body Exp_Ch7 is
(Loc : Source_Ptr;
Obj : Entity_Id) return Node_Id
is
+ Obj_Decl : constant Node_Id := Declaration_Node (Obj);
+
Master_Node_Decl : Node_Id;
Master_Node_Id : Entity_Id;
@@ -8714,14 +8808,18 @@ package body Exp_Ch7 is
-- Create the declaration of the Master_Node for the object and
-- insert it before the declaration of the object itself.
- if Present (Finalization_Master_Node_Or_Object (Obj)) then
- Master_Node_Id := Finalization_Master_Node_Or_Object (Obj);
+ if Present (Finalization_Master_Node (Obj)) then
+ Master_Node_Id := Finalization_Master_Node (Obj);
else
Master_Node_Id := Make_Temporary (Loc, 'N');
Master_Node_Decl :=
Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj);
- Insert_Before_And_Analyze (Declaration_Node (Obj), Master_Node_Decl);
+ Insert_Before_And_Analyze (Obj_Decl, Master_Node_Decl);
+
+ -- Generate the attachment of the object to the Master_Node
+
+ Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id);
-- Mark the object to avoid double finalization
diff --git a/gcc/ada/exp_ch7.ads b/gcc/ada/exp_ch7.ads
index c606bb9..97fea23 100644
--- a/gcc/ada/exp_ch7.ads
+++ b/gcc/ada/exp_ch7.ads
@@ -35,6 +35,13 @@ package Exp_Ch7 is
-- Finalization Management --
-----------------------------
+ procedure Attach_Object_To_Master_Node
+ (Obj_Decl : Node_Id;
+ Master_Node : Entity_Id);
+ -- Generate code to attach an object denoted by its declaration Obj_Decl
+ -- to a master node denoted by Master_Node. The code is inserted after
+ -- the object is initialized.
+
procedure Build_Anonymous_Master (Ptr_Typ : Entity_Id);
-- Build a finalization master for an anonymous access-to-controlled type
-- denoted by Ptr_Typ. The master is inserted in the declarations of the
diff --git a/gcc/ada/exp_util.adb b/gcc/ada/exp_util.adb
index e757327..732a02f 100644
--- a/gcc/ada/exp_util.adb
+++ b/gcc/ada/exp_util.adb
@@ -12953,11 +12953,10 @@ package body Exp_Util is
-- Conversely, if one of the above cases created a Master_Node,
-- finalization actions are required for the associated object.
- -- Note that we need to make sure that we will not process both
- -- the Master_Node and the associated object here.
- elsif Present (Finalization_Master_Node_Or_Object (Obj_Id)) then
- pragma Assert (Is_RTE (Obj_Typ, RE_Master_Node));
+ elsif Ekind (Obj_Id) = E_Variable
+ and then Is_RTE (Obj_Typ, RE_Master_Node)
+ then
return True;
-- Ignored Ghost objects do not need any cleanup actions because
diff --git a/gcc/ada/gen_il-fields.ads b/gcc/ada/gen_il-fields.ads
index 7cf6a38..ac1e0c9 100644
--- a/gcc/ada/gen_il-fields.ads
+++ b/gcc/ada/gen_il-fields.ads
@@ -538,7 +538,7 @@ package Gen_IL.Fields is
Extra_Formal,
Extra_Formals,
Finalization_Master,
- Finalization_Master_Node_Or_Object,
+ Finalization_Master_Node,
Finalize_Storage_Only,
Finalizer,
First_Entity,
diff --git a/gcc/ada/gen_il-gen-gen_entities.adb b/gcc/ada/gen_il-gen-gen_entities.adb
index a30013a..cde016c 100644
--- a/gcc/ada/gen_il-gen-gen_entities.adb
+++ b/gcc/ada/gen_il-gen-gen_entities.adb
@@ -335,7 +335,7 @@ begin -- Gen_IL.Gen.Gen_Entities
(Sm (Activation_Record_Component, Node_Id),
Sm (Alignment, Unat),
Sm (Esize, Uint),
- Sm (Finalization_Master_Node_Or_Object, Node_Id),
+ Sm (Finalization_Master_Node, Node_Id),
Sm (Interface_Name, Node_Id),
Sm (Is_Finalized_Transient, Flag),
Sm (Is_Ignored_For_Finalization, Flag),
diff --git a/gcc/ada/libgnat/s-finpri.adb b/gcc/ada/libgnat/s-finpri.adb
index 50f49d7..7dc08a9 100644
--- a/gcc/ada/libgnat/s-finpri.adb
+++ b/gcc/ada/libgnat/s-finpri.adb
@@ -47,9 +47,7 @@ package body System.Finalization_Primitives is
is
begin
Attach_Object_To_Node (Object_Address, Finalize_Address, Node.all);
-
- Node.Next := Master.Head;
- Master.Head := Node;
+ Chain_Node_To_Master (Node, Master);
end Attach_Object_To_Master;
---------------------------
@@ -69,6 +67,19 @@ package body System.Finalization_Primitives is
Node.Finalize_Address := Finalize_Address;
end Attach_Object_To_Node;
+ --------------------------
+ -- Chain_Node_To_Master --
+ --------------------------
+
+ procedure Chain_Node_To_Master
+ (Node : not null Master_Node_Ptr;
+ Master : in out Finalization_Scope_Master)
+ is
+ begin
+ Node.Next := Master.Head;
+ Master.Head := Node;
+ end Chain_Node_To_Master;
+
---------------------
-- Finalize_Master --
---------------------
@@ -90,12 +101,6 @@ package body System.Finalization_Primitives is
if Master.Exceptions_OK then
while Node /= null loop
- -- Check that the Master_Node has a nonnull address
-
- if Node.Object_Address = System.Null_Address then
- raise Program_Error with "finalize with null address";
- end if;
-
begin
Finalize_Object (Node.all);
@@ -124,12 +129,6 @@ package body System.Finalization_Primitives is
else
while Node /= null loop
- -- Check that the Master_Node has a nonnull address
-
- if Node.Object_Address = System.Null_Address then
- raise Program_Error with "finalize with null address";
- end if;
-
Finalize_Object (Node.all);
Node := Node.Next;
@@ -159,7 +158,10 @@ package body System.Finalization_Primitives is
begin
if FA /= null then
+ pragma Assert (Node.Object_Address /= System.Null_Address);
+
Node.Finalize_Address := null;
+
FA (Node.Object_Address);
end if;
end Finalize_Object;
diff --git a/gcc/ada/libgnat/s-finpri.ads b/gcc/ada/libgnat/s-finpri.ads
index 1ffe24b..de775ca 100644
--- a/gcc/ada/libgnat/s-finpri.ads
+++ b/gcc/ada/libgnat/s-finpri.ads
@@ -79,7 +79,16 @@ package System.Finalization_Primitives with Preelaborate is
Finalize_Address : not null Finalize_Address_Ptr;
Node : in out Master_Node);
-- Associates a controlled object with its master node only. This is used
- -- when there is a single object to be finalized in the context.
+ -- when there is a single object to be finalized in the context, as well as
+ -- for objects that need special processing (return object in an extended
+ -- return statement or transient objects).
+
+ procedure Chain_Node_To_Master
+ (Node : not null Master_Node_Ptr;
+ Master : in out Finalization_Scope_Master);
+ -- Chain a master node to the given master. This is used to chain the node
+ -- to the master of the enclosing scope for the objects that need special
+ -- processing mentioned for Attach_Object_To_Node.
procedure Finalize_Master (Master : in out Finalization_Scope_Master);
-- Finalizes each of the controlled objects associated with Master, in the
@@ -125,6 +134,7 @@ private
pragma Inline (Attach_Object_To_Master);
pragma Inline (Attach_Object_To_Node);
+ pragma Inline (Chain_Node_To_Master);
pragma Inline (Finalize_Object);
pragma Inline (Suppress_Object_Finalize_At_End);
diff --git a/gcc/ada/rtsfind.ads b/gcc/ada/rtsfind.ads
index f36713b..dc06bff 100644
--- a/gcc/ada/rtsfind.ads
+++ b/gcc/ada/rtsfind.ads
@@ -927,6 +927,7 @@ package Rtsfind is
RE_Attach_Object_To_Master, -- System.Finalization_Primitives
RE_Attach_Object_To_Node, -- System.Finalization_Primitives
+ RE_Chain_Node_To_Master, -- System.Finalization_Primitives
RE_Finalize_Master, -- System.Finalization_Primitives
RE_Finalize_Object, -- System.Finalization_Primitives
RE_Finalization_Scope_Master, -- System.Finalization_Primitives
@@ -2579,6 +2580,7 @@ package Rtsfind is
RE_Attach_Object_To_Master => System_Finalization_Primitives,
RE_Attach_Object_To_Node => System_Finalization_Primitives,
+ RE_Chain_Node_To_Master => System_Finalization_Primitives,
RE_Finalize_Master => System_Finalization_Primitives,
RE_Finalize_Object => System_Finalization_Primitives,
RE_Finalization_Scope_Master => System_Finalization_Primitives,