1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
|
------------------------------------------------------------------------------
-- --
-- GNAT COMPILER COMPONENTS --
-- --
-- E X P _ C H 7 --
-- --
-- S p e c --
-- --
-- Copyright (C) 1992-2024, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
-- ware Foundation; either version 3, or (at your option) any later ver- --
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
-- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
-- for more details. You should have received a copy of the GNU General --
-- Public License distributed with GNAT; see file COPYING3. If not, go to --
-- http://www.gnu.org/licenses for a complete copy of the license. --
-- --
-- GNAT was originally developed by the GNAT team at New York University. --
-- Extensive contributions were provided by Ada Core Technologies Inc. --
-- --
------------------------------------------------------------------------------
with Namet; use Namet;
with Types; use Types;
package Exp_Ch7 is
procedure Expand_N_Package_Body (N : Node_Id);
procedure Expand_N_Package_Declaration (N : Node_Id);
-----------------------------
-- 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_Collection (Ptr_Typ : Entity_Id);
-- Build a finalization collection for an anonymous access-to-controlled
-- type denoted by Ptr_Typ. The collection is inserted in the declarations
-- of the current unit.
procedure Build_Controlling_Procs (Typ : Entity_Id);
-- Typ is a record, and array type having controlled components.
-- Create the procedures Deep_Initialize, Deep_Adjust and Deep_Finalize
-- that take care of finalization management at run-time.
-- Support of exceptions from user finalization procedures
-- There is a specific mechanism to handle these exceptions, continue
-- finalization and then raise PE. This mechanism is used by this package
-- but also by exp_intr for Ada.Unchecked_Deallocation.
-- There are 3 subprograms to use this mechanism, and the type
-- Finalization_Exception_Data carries internal data between these
-- subprograms:
--
-- 1. Build_Object_Declaration: create the variables for the next two
-- subprograms.
-- 2. Build_Exception_Handler: create the exception handler for a call
-- to a user finalization procedure.
-- 3. Build_Raise_Stmt: create code to potentially raise a PE exception
-- if an exception was raise in a user finalization procedure.
type Finalization_Exception_Data is record
Loc : Source_Ptr;
-- Sloc for the added nodes
Abort_Id : Entity_Id;
-- Boolean variable set to true if the finalization was triggered by
-- an abort.
E_Id : Entity_Id;
-- Variable containing the exception occurrence raised by user code
Raised_Id : Entity_Id;
-- Boolean variable set to true if an exception was raised in user code
end record;
function Build_Exception_Handler
(Data : Finalization_Exception_Data;
For_Library : Boolean := False) return Node_Id;
-- Subsidiary to Build_Finalizer, Make_Deep_Array_Body and Make_Deep_Record
-- _Body. Create an exception handler of the following form:
--
-- when others =>
-- if not Raised_Id then
-- Raised_Id := True;
-- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
-- end if;
--
-- If flag For_Library is set (and not in restricted profile):
--
-- when others =>
-- if not Raised_Id then
-- Raised_Id := True;
-- Save_Library_Occurrence (Get_Current_Excep.all);
-- end if;
--
-- E_Id denotes the defining identifier of a local exception occurrence.
-- Raised_Id is the entity of a local boolean flag. Flag For_Library is
-- used when operating at the library level, when enabled the current
-- exception will be saved to a global location.
procedure Build_Finalization_Collection
(Typ : Entity_Id;
For_Lib_Level : Boolean := False;
For_Private : Boolean := False;
Context_Scope : Entity_Id := Empty;
Insertion_Node : Node_Id := Empty);
-- Build a finalization collection for an access type. The designated type
-- may not necessarily be controlled or need finalization actions depending
-- on the context. For_Lib_Level must be set when creating a collection for
-- a build-in-place function call access result type. Flag For_Private must
-- be set when the designated type contains a private component. Parameters
-- Context_Scope and Insertion_Node must be used in conjunction with flag
-- For_Private. Context_Scope is the scope of the context where the newly
-- built collection must be analyzed. Insertion_Node is the insertion point
-- before which the collection is to be inserted.
procedure Build_Finalizer
(N : Node_Id;
Clean_Stmts : List_Id;
Mark_Id : Entity_Id;
Top_Decls : List_Id;
Defer_Abort : Boolean;
Fin_Id : out Entity_Id);
-- N may denote an accept statement, block, entry body, package body,
-- package spec, protected body, subprogram body, or a task body. Create
-- a procedure which contains finalization calls for all controlled objects
-- declared in the declarative or statement region of N. The calls are
-- built in reverse order relative to the original declarations. In the
-- case of a task body, the routine delays the creation of the finalizer
-- until all statements have been moved to the task body procedure.
-- Clean_Stmts may contain additional context-dependent code used to abort
-- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
-- Mark_Id is the secondary stack used in the current context or Empty if
-- missing. Top_Decls is the list on which the declaration of the finalizer
-- is attached in the non-package case. Defer_Abort indicates that the
-- statements passed in perform actions that require abort to be deferred,
-- such as for task termination. Fin_Id is the finalizer declaration
-- entity.
procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id);
-- Build one controlling procedure when a late body overrides one of the
-- controlling operations.
procedure Build_Object_Declarations
(Data : out Finalization_Exception_Data;
Decls : List_Id;
Loc : Source_Ptr;
For_Package : Boolean := False);
-- Subsidiary to Make_Deep_Array_Body and Make_Deep_Record_Body. Create the
-- list List containing the object declarations of boolean flag Abort_Id,
-- the exception occurrence E_Id and boolean flag Raised_Id.
--
-- Abort_Id : constant Boolean :=
-- Exception_Identity (Get_Current_Excep.all) =
-- Standard'Abort_Signal'Identity;
-- <or>
-- Abort_Id : constant Boolean := False; -- no abort or For_Package
--
-- E_Id : Exception_Occurrence;
-- Raised_Id : Boolean := False;
function Build_Raise_Statement
(Data : Finalization_Exception_Data) return Node_Id;
-- Subsidiary to routines Build_Finalizer, Make_Deep_Array_Body and Make_
-- Deep_Record_Body. Generate the following conditional raise statement:
--
-- if Raised_Id and then not Abort_Id then
-- Raise_From_Controlled_Operation (E_Id);
-- end if;
--
-- Abort_Id is a local boolean flag which is set when the finalization was
-- triggered by an abort, E_Id denotes the defining identifier of a local
-- exception occurrence, Raised_Id is the entity of a local boolean flag.
procedure Expand_Cleanup_Actions (N : Node_Id);
-- Expand the necessary stuff into a scope to enable finalization of local
-- objects and deallocation of transient data when exiting the scope. N is
-- one of N_Block_Statement, N_Subprogram_Body, N_Task_Body, N_Entry_Body,
-- or N_Extended_Return_Statement.
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_Adjust_Call
(Obj_Ref : Node_Id;
Typ : Entity_Id;
Skip_Self : Boolean := False) return Node_Id;
-- Create a call to either Adjust or Deep_Adjust depending on the structure
-- of type Typ. Obj_Ref is an expression with no side effects (not required
-- to have been previously analyzed) that references the object to be
-- adjusted. Typ is the expected type of Obj_Ref. When Skip_Self is set,
-- only the components (if any) are adjusted. Return Empty if Adjust or
-- Deep_Adjust is not available, possibly due to previous errors.
function Make_Final_Call
(Obj_Ref : Node_Id;
Typ : Entity_Id;
Skip_Self : Boolean := False) return Node_Id;
-- Create a call to either Finalize or Deep_Finalize, depending on the
-- structure of type Typ. Obj_Ref is an expression (with no side effects
-- and is not required to have been previously analyzed) that references
-- the object to be finalized. Typ is the expected type of Obj_Ref. When
-- Skip_Self is set, only the components (if any) are finalized. Return
-- Empty if Finalize or Deep_Finalize is not available, possibly due to
-- previous errors.
procedure Make_Finalize_Address_Body (Typ : Entity_Id);
-- Create the body of TSS routine Finalize_Address if Typ is controlled and
-- does not have a TSS entry for Finalize_Address. The procedure converts
-- an address into a pointer and subsequently calls Deep_Finalize on the
-- dereference.
function Make_Init_Call
(Obj_Ref : Node_Id;
Typ : Entity_Id) return Node_Id;
-- Create a call to either Initialize or Deep_Initialize, depending on the
-- structure of type Typ. Obj_Ref is an expression with no side effects
-- (not required to have been previously analyzed) that references the
-- object to be initialized. Typ is the expected type of Obj_Ref. Return
-- Empty if Initialize or Deep_Initialize is not available, possibly due to
-- previous errors.
function Make_Handler_For_Ctrl_Operation (Loc : Source_Ptr) return Node_Id;
-- Generate an implicit exception handler with an 'others' choice,
-- converting any occurrence to a raise of Program_Error.
function Make_Local_Deep_Finalize
(Typ : Entity_Id;
Nam : Entity_Id) return Node_Id;
-- Create a special version of Deep_Finalize with identifier Nam. The
-- routine has state information and can perform partial finalization.
function Make_Master_Node_Declaration
(Loc : Source_Ptr;
Master_Node : Entity_Id;
Obj : Entity_Id) return Node_Id;
-- Build the declaration of the Master_Node for the object Obj
function Make_Suppress_Object_Finalize_Call
(Loc : Source_Ptr;
Obj : Entity_Id) return Node_Id;
-- Build a call to suppress the finalization of the object Obj, only after
-- creating the Master_Node of Obj if it does not already exist.
procedure Preload_Finalization_Collection (Compilation_Unit : Node_Id);
-- Call RTE (RE_Finalization_Collection) if necessary to load the packages
-- involved in finalization support. We need to do this explicitly, fairly
-- early during compilation, because otherwise it happens during freezing,
-- which triggers visibility bugs in generic instantiations.
--------------------------------------------
-- Task and Protected Object finalization --
--------------------------------------------
function Cleanup_Array
(N : Node_Id;
Obj : Node_Id;
Typ : Entity_Id) return List_Id;
-- Generate loops to finalize any tasks or simple protected objects that
-- are subcomponents of an array.
function Cleanup_Protected_Object
(N : Node_Id;
Ref : Node_Id) return Node_Id;
-- Generate code to finalize a protected object without entries
function Cleanup_Record
(N : Node_Id;
Obj : Node_Id;
Typ : Entity_Id) return List_Id;
-- For each subcomponent of a record that contains tasks or simple
-- protected objects, generate the appropriate finalization call.
function Cleanup_Task
(N : Node_Id;
Ref : Node_Id) return Node_Id;
-- Generate code to finalize a task
function Has_Simple_Protected_Object (T : Entity_Id) return Boolean;
-- Check whether composite type contains a simple protected component
function Is_Simple_Protected_Type (T : Entity_Id) return Boolean;
-- Determine whether T denotes a protected type without entries whose
-- _object field is of type System.Tasking.Protected_Objects.Protection.
-- Something wrong here, implementation was changed to test Lock_Free
-- but this spec does not mention that ???
--------------------------------
-- Transient Scope Management --
--------------------------------
procedure Establish_Transient_Scope
(N : Node_Id;
Manage_Sec_Stack : Boolean);
-- Push a new transient scope on the scope stack. N is the node which must
-- be serviced by the transient scope. Set Manage_Sec_Stack when the scope
-- must mark and release the secondary stack.
function Node_To_Be_Wrapped return Node_Id;
-- Return the node to be wrapped if the current scope is transient
procedure Store_Before_Actions_In_Scope (L : List_Id);
-- Append the list L of actions to the end of the before-actions store in
-- the top of the scope stack (also analyzes these actions).
procedure Store_After_Actions_In_Scope (L : List_Id);
-- Prepend the list L of actions to the beginning of the after-actions
-- stored in the top of the scope stack (also analyzes these actions).
--
-- Note that we are prepending here rather than appending. This means that
-- if several calls are made to this procedure for the same scope, the
-- actions will be executed in reverse order of the calls (actions for the
-- last call executed first). Within the list L for a single call, the
-- actions are executed in the order in which they appear in this list.
procedure Store_Cleanup_Actions_In_Scope (L : List_Id);
-- Prepend the list L of actions to the beginning of the cleanup-actions
-- store in the top of the scope stack.
procedure Wrap_Transient_Declaration (N : Node_Id);
-- N is an object declaration. Expand the finalization calls after the
-- declaration and make the outer scope being the transient one.
procedure Wrap_Transient_Expression (N : Node_Id);
-- N is a sub-expression. Expand a transient block around an expression
procedure Wrap_Transient_Statement (N : Node_Id);
-- N is a statement. Expand a transient block around an instruction
end Exp_Ch7;
|