aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/exp_ch7.adb
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ada/exp_ch7.adb')
-rw-r--r--gcc/ada/exp_ch7.adb118
1 files changed, 102 insertions, 16 deletions
diff --git a/gcc/ada/exp_ch7.adb b/gcc/ada/exp_ch7.adb
index 9a648e5..678948a 100644
--- a/gcc/ada/exp_ch7.adb
+++ b/gcc/ada/exp_ch7.adb
@@ -297,8 +297,11 @@ package body Exp_Ch7 is
function Build_Cleanup_Statements (N : Node_Id) return List_Id;
-- Create the clean up calls for an asynchronous call block, task master,
- -- protected subprogram body, task allocation block or task body. If N is
- -- neither of these constructs, the routine returns a new list.
+ -- protected subprogram body, task allocation block or task body. Generate
+ -- code to unregister the external tags of all library-level tagged types
+ -- found in the declarations and/or statements of N. If the context does
+ -- not contain the above constructs or types, the routine returns an empty
+ -- list.
function Build_Exception_Handler
(Loc : Source_Ptr;
@@ -486,8 +489,11 @@ package body Exp_Ch7 is
Is_Asynchronous_Call : constant Boolean :=
Nkind (N) = N_Block_Statement
and then Is_Asynchronous_Call_Block (N);
+
Is_Master : constant Boolean :=
- Nkind (N) /= N_Entry_Body
+ not Nkind_In (N, N_Entry_Body,
+ N_Package_Body,
+ N_Package_Declaration)
and then Is_Task_Master (N);
Is_Protected_Body : constant Boolean :=
Nkind (N) = N_Subprogram_Body
@@ -501,6 +507,59 @@ package body Exp_Ch7 is
Loc : constant Source_Ptr := Sloc (N);
Stmts : constant List_Id := New_List;
+ procedure Unregister_Tagged_Types (Decls : List_Id);
+ -- Unregister the external tag of each tagged type found in the list
+ -- Decls. The generated statements are added to list Stmts.
+
+ -----------------------------
+ -- Unregister_Tagged_Types --
+ -----------------------------
+
+ procedure Unregister_Tagged_Types (Decls : List_Id) is
+ Decl : Node_Id;
+ DT_Ptr : Entity_Id;
+ Typ : Entity_Id;
+
+ begin
+ if No (Decls) or else Is_Empty_List (Decls) then
+ return;
+ end if;
+
+ -- Process all declarations or statements in reverse order
+
+ Decl := Last_Non_Pragma (Decls);
+ while Present (Decl) loop
+ if Nkind (Decl) = N_Full_Type_Declaration then
+ Typ := Defining_Identifier (Decl);
+
+ if Is_Tagged_Type (Typ)
+ and then Is_Library_Level_Entity (Typ)
+ and then Convention (Typ) = Convention_Ada
+ and then Present (Access_Disp_Table (Typ))
+ and then RTE_Available (RE_Unregister_Tag)
+ and then not No_Run_Time_Mode
+ and then not Is_Abstract_Type (Typ)
+ then
+ DT_Ptr := Node (First_Elmt (Access_Disp_Table (Typ)));
+
+ -- Generate:
+ -- Ada.Tags.Unregister_Tag (<Typ>P);
+
+ Append_To (Stmts,
+ Make_Procedure_Call_Statement (Loc,
+ Name =>
+ New_Reference_To (RTE (RE_Unregister_Tag), Loc),
+ Parameter_Associations => New_List (
+ New_Reference_To (DT_Ptr, Loc))));
+ end if;
+ end if;
+
+ Prev_Non_Pragma (Decl);
+ end loop;
+ end Unregister_Tagged_Types;
+
+ -- Start of processing for Build_Cleanup_Statements
+
begin
if Is_Task_Body then
if Restricted_Profile then
@@ -711,6 +770,26 @@ package body Exp_Ch7 is
end;
end if;
+ -- Inspect all declaration and/or statement lists of N for library-level
+ -- tagged types. Generate code to unregister the external tag of such a
+ -- type.
+
+ if Nkind (N) = N_Package_Declaration then
+ Unregister_Tagged_Types (Private_Declarations (Specification (N)));
+ Unregister_Tagged_Types (Visible_Declarations (Specification (N)));
+
+ -- Accept statement, block, entry body, package body, protected body,
+ -- subprogram body or task body.
+
+ else
+ if Present (Handled_Statement_Sequence (N)) then
+ Unregister_Tagged_Types
+ (Statements (Handled_Statement_Sequence (N)));
+ end if;
+
+ Unregister_Tagged_Types (Declarations (N));
+ end if;
+
return Stmts;
end Build_Cleanup_Statements;
@@ -2686,22 +2765,29 @@ package body Exp_Ch7 is
if For_Package_Spec then
Process_Declarations
(Priv_Decls, Preprocess => True, Top_Level => True);
+ end if;
- -- The preprocessing has determined that the context has objects
- -- that need finalization actions. Private declarations are
- -- processed first in order to preserve possible dependencies
- -- between public and private objects.
+ -- The current context may lack controlled objects, but require some
+ -- other form of completion (task termination for instance). In such
+ -- cases, the finalizer must be created and carry the additional
+ -- statements.
- if Has_Ctrl_Objs then
- Build_Components;
- Process_Declarations (Priv_Decls);
- end if;
+ if Acts_As_Clean or else Has_Ctrl_Objs then
+ Build_Components;
end if;
- -- Process the public declarations
+ -- The preprocessing has determined that the context has objects that
+ -- need finalization actions.
if Has_Ctrl_Objs then
- Build_Components;
+
+ -- Private declarations are processed first in order to preserve
+ -- possible dependencies between public and private objects.
+
+ if For_Package_Spec then
+ Process_Declarations (Priv_Decls);
+ end if;
+
Process_Declarations (Decls);
end if;
@@ -3495,7 +3581,7 @@ package body Exp_Ch7 is
and then VM_Target = No_VM;
Actions_Required : constant Boolean :=
- Has_Controlled_Objects (N)
+ Requires_Cleanup_Actions (N)
or else Is_Asynchronous_Call
or else Is_Master
or else Is_Protected_Body
@@ -3770,7 +3856,7 @@ package body Exp_Ch7 is
if Ekind (Spec_Ent) /= E_Generic_Package then
Build_Finalizer
(N => N,
- Clean_Stmts => No_List,
+ Clean_Stmts => Build_Cleanup_Statements (N),
Mark_Id => Empty,
Top_Decls => No_List,
Defer_Abort => False,
@@ -3924,7 +4010,7 @@ package body Exp_Ch7 is
if Ekind (Id) /= E_Generic_Package then
Build_Finalizer
(N => N,
- Clean_Stmts => No_List,
+ Clean_Stmts => Build_Cleanup_Statements (N),
Mark_Id => Empty,
Top_Decls => No_List,
Defer_Abort => False,