c++: repeated export using
[official-gcc.git] / gcc / ada / exp_ch7.adb
blobfd1d9db06544e3d2e6660b603268cd4ff9469bad
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 7 --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2024, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- This package contains virtually all expansion mechanisms related to
27 -- - controlled types
28 -- - transient scopes
30 with Atree; use Atree;
31 with Debug; use Debug;
32 with Einfo; use Einfo;
33 with Einfo.Entities; use Einfo.Entities;
34 with Einfo.Utils; use Einfo.Utils;
35 with Elists; use Elists;
36 with Errout; use Errout;
37 with Exp_Ch6; use Exp_Ch6;
38 with Exp_Ch9; use Exp_Ch9;
39 with Exp_Ch11; use Exp_Ch11;
40 with Exp_Dbug; use Exp_Dbug;
41 with Exp_Dist; use Exp_Dist;
42 with Exp_Disp; use Exp_Disp;
43 with Exp_Prag; use Exp_Prag;
44 with Exp_Tss; use Exp_Tss;
45 with Exp_Util; use Exp_Util;
46 with Freeze; use Freeze;
47 with GNAT_CUDA; use GNAT_CUDA;
48 with Lib; use Lib;
49 with Nlists; use Nlists;
50 with Nmake; use Nmake;
51 with Opt; use Opt;
52 with Output; use Output;
53 with Restrict; use Restrict;
54 with Rident; use Rident;
55 with Rtsfind; use Rtsfind;
56 with Sinfo; use Sinfo;
57 with Sinfo.Nodes; use Sinfo.Nodes;
58 with Sinfo.Utils; use Sinfo.Utils;
59 with Sem; use Sem;
60 with Sem_Aux; use Sem_Aux;
61 with Sem_Ch7; use Sem_Ch7;
62 with Sem_Ch8; use Sem_Ch8;
63 with Sem_Res; use Sem_Res;
64 with Sem_Util; use Sem_Util;
65 with Snames; use Snames;
66 with Stand; use Stand;
67 with Tbuild; use Tbuild;
68 with Ttypes; use Ttypes;
69 with Uintp; use Uintp;
71 package body Exp_Ch7 is
73 -----------------------------
74 -- Finalization Management --
75 -----------------------------
77 -- This paragraph describes how Initialization/Adjustment/Finalization
78 -- procedures are generated and called. Two cases must be considered: types
79 -- that are controlled (Is_Controlled flag set) and composite types that
80 -- contain controlled components (Has_Controlled_Component flag set). In
81 -- the first case the procedures to call are the user-defined primitive
82 -- operations Initialize/Adjust/Finalize. In the second case, the compiler
83 -- generates Deep_Initialize, Deep_Adjust and Deep_Finalize that are in
84 -- charge of calling the former procedures on the controlled components.
86 -- Initialize calls: they are generated for either declarations or dynamic
87 -- allocations of controlled objects with no initial value. They are always
88 -- followed by an attachment to some finalization chain. For the dynamic
89 -- dynamic allocation case, this is the collection attached to the access
90 -- type definition; otherwise, this is the master of the current scope.
92 -- Adjust calls: they are generated on two occasions: (1) for declarations
93 -- or dynamic allocations of controlled objects with an initial value (with
94 -- the exception of function calls), (2) after an assignment. In the first
95 -- case they are followed by an attachment to the finalization chain, in
96 -- the second case they are not.
98 -- Finalization calls: they are generated on three occasions: (1) on scope
99 -- exit, (2) assignments, (3) unchecked deallocations. In case (3) objects
100 -- have to be detached from the finalization chain, in case (2) they must
101 -- not and in case (1) this is optional as we are exiting the scope anyway.
103 -- There are two kinds of finalization chain to which objects are attached,
104 -- depending on the way they are created. For objects (statically) declared
105 -- in a scope, the finalization chain is that of the master of the scope,
106 -- which is embodied in a Finalization_Master object. As per RM 7.6.1(11/3)
107 -- the finalization of the master (on scope exit) performs the finalization
108 -- of objects attached to its chain in the reverse order of their creation.
110 -- For dynamically allocated objects, the finalization chain is that of the
111 -- finalization collection of the access type through which the objects are
112 -- allocated, which is embodied in a Finalization_Collection object. As per
113 -- RM 7.6.1(11.1/3), the finalization of the collection performs the
114 -- finalization of objects attached to its chain in an arbitrary order.
116 -- A Finalization_Collection object is implemented as a controlled object
117 -- and its finalization is therefore driven by the finalization master of
118 -- the scope where it is declared. As per RM 7.6.1(11.2/3), for a named
119 -- access type, the Finalization_Collection object is declared in the list
120 -- of actions of its freeze node.
122 -- ??? For an anonymous access type, the implementation deviates from the
123 -- RM 7.6.1 clause as follows: all the anonymous access types with the same
124 -- designated type that are (implicitly) declared in a library unit share a
125 -- single Finalization_Collection object declared in the outermost scope of
126 -- the library unit, except if the designated type is declared in a dynamic
127 -- scope nested in the unit; in this case no Finalization_Collection object
128 -- is created. As a result, in the first case, objects allocated through
129 -- the anonymous access types are finalized when the library unit goes out
130 -- of scope, while in the second case, they are not finalized at all.
132 -- Here is a simple example of the expansion of a controlled block:
134 -- declare
135 -- X : Ctrl;
136 -- Y : Ctrl := Init;
138 -- type Rec is record
139 -- C : Ctrl;
140 -- end record;
142 -- W : Rec;
143 -- Z : Rec := Init;
145 -- begin
146 -- X := Y;
147 -- W := Z;
148 -- end;
150 -- is expanded into:
152 -- declare
153 -- Mnn : System.Finalization_Primitives.Finalization_Master;
155 -- XMN : aliased System.Finalization_Primitives.Master_Node;
156 -- X : Ctrl;
157 -- Bnn : begin
158 -- Abort_Defer;
159 -- Initialize (X);
160 -- System.Finalization_Primitives.Attach_To_Master
161 -- (X'address,
162 -- CtrlFD'unrestricted_access,
163 -- XMN'unrestricted_access,
164 -- Mnn);
165 -- at end
166 -- Abort_Undefer;
167 -- end Bnn;
169 -- YMN : aliased System.Finalization_Primitives.Master_Node;
170 -- Y : Ctrl := Init;
171 -- System.Finalization_Primitives.Attach_To_Master
172 -- (Y'address,
173 -- CtrlFD'unrestricted_access,
174 -- YMN'unrestricted_access,
175 -- Mnn);
177 -- type Rec is record
178 -- C : Ctrl;
179 -- end record;
181 -- WMN : aliased System.Finalization_Primitives.Master_Node;
182 -- W : Rec;
183 -- Bnn : begin
184 -- Abort_Defer;
185 -- Bnn : begin
186 -- Deep_Initialize (W);
187 -- System.Finalization_Primitives.Attach_To_Master
188 -- (W'address,
189 -- Rec_FD'unrestricted_access,
190 -- WMN'unrestricted_access,
191 -- Mnn);
192 -- exception
193 -- when others =>
194 -- Deep_Finalize (W);
195 -- end Bnn;
196 -- at end
197 -- Abort_Undefer;
198 -- end Bnn;
200 -- ZMN : aliaed System.Finalization_Primitives.Master_Node;
201 -- Z : Rec := Init;
202 -- System.Finalization_Primitives.Attach_To_Master
203 -- (Z'address,
204 -- Rec_FD'unrestricted_access,
205 -- ZMN'unrestricted_access,
206 -- Mnn);
208 -- procedure _Finalizer is
209 -- Ann : constant Boolean := Ada.Exceptions.Triggered_By_Abort;
210 -- Rnn : boolean := False;
211 -- begin
212 -- Abort_Defer;
213 -- Bnn : begin
214 -- System.Finalization_Primitives.Finalize_Master (Mnn);
215 -- exceptions
216 -- when others =>
217 -- Rnn := True;
218 -- end Bnn;
219 -- Abort_Undefer;
220 -- if Rnn and then not Ann then
221 -- [program_error "finalize raised exception"]
222 -- end if;
223 -- end _Finalizer;
225 -- begin
226 -- _Assign (X, Y);
227 -- Deep_Finalize (W);
228 -- W := Z;
229 -- Deep_Adjust (W);
230 -- end;
231 -- at end
232 -- _Finalizer;
234 -- In the case of a block containing a single controlled object, the master
235 -- degenerates into a single master node:
237 -- declare
238 -- X : Ctrl := Init;
240 -- begin
241 -- null;
242 -- end;
244 -- is expanded into:
246 -- declare
247 -- XMN : aliased System.Finalization_Primitives.Master_Node;
248 -- X : Ctrl := Init;
249 -- System.Finalization_Primitives.Attach_To_Node
250 -- (X'address,
251 -- CtrlFD'unrestricted_access,
252 -- XMN'unrestricted_access);
254 -- procedure _Finalizer is
255 -- Ann : constant Boolean := Ada.Exceptions.Triggered_By_Abort;
256 -- Rnn : boolean := False;
257 -- begin
258 -- Abort_Defer;
259 -- Bnn : begin
260 -- System.Finalization_Primitives.Finalize_Object (XMN);
261 -- exceptions
262 -- when others =>
263 -- Rnn := True;
264 -- end Bnn;
265 -- Abort_Undefer;
266 -- if Rnn and then not Ann then
267 -- [program_error "finalize raised exception"]
268 -- end if;
269 -- end _Finalizer;
271 -- begin
272 -- null;
273 -- end;
274 -- at end
275 -- _Finalizer;
277 -- Here is the version with a dynamically allocated object:
279 -- declare
280 -- X : P_Ctrl := new Ctrl;
282 -- begin
283 -- null;
284 -- end;
286 -- is expanded into:
288 -- declare
289 -- Cnn : System.Finalization_Primitives.Finalization_Collection_Ptr :=
290 -- P_CtrlFC'unrestricted_access;
291 -- [...]
292 -- Pnn : constant P_Ctrl := new Ctrl[...][...];
293 -- Bnn : begin
294 -- Abort_Defer;
295 -- Initialize (Pnn.all);
296 -- System.Finalization_Primitives.Attach_To_Collection
297 -- (Pnn.all'address,
298 -- CtrlFD'unrestricted_access,
299 -- Cnn.all);
300 -- at end
301 -- Abort_Undefer;
302 -- end Bnn;
303 -- X : P_Ctrl := Pnn;
305 -- The implementation uses two different strategies for the finalization
306 -- of (statically) declared objects and of dynamically allocated objects.
308 -- For (statically) declared objects, the attachment to the finalization
309 -- chain of the current scope and the call to the finalization procedure
310 -- are generated during a post-processing phase of the expansion. These
311 -- objects are first spotted in declarative parts and statement lists by
312 -- Requires_Cleanup_Actions; then Build_Finalizer is called on the parent
313 -- node to generate both the attachment and the finalization actions.
315 -- This post processing is fully transparent for the rest of the expansion
316 -- activities, in other words those have nothing to do or to care about.
317 -- However this default processing may not be sufficient in specific cases,
318 -- e.g. for the return object of an extended return statement in a function
319 -- whose result type is controlled: in this case, the return object must be
320 -- finalized only if the function returns abnormally. In order to deal with
321 -- these cases, it is possible to directly generate detachment actions (for
322 -- the return object case) or finalization actions (for transient objects)
323 -- during the rest of expansion activities.
325 -- These direct actions must be signalled to the post-processing machinery
326 -- and this is achieved through the handling of Master_Node objects, which
327 -- are the items actually chained in the finalization chains of masters.
328 -- With the default processing, they are created by Build_Finalizer for the
329 -- controlled objects spotted by Requires_Cleanup_Actions. But when direct
330 -- actions are carried out, they are generated by these actions and later
331 -- recognized by Requires_Cleanup_Actions and picked up by Build_Finalizer.
333 -- For dynamically allocated objects, there is no post-processing phase and
334 -- the attachment to the finalization chain of the access type, as well the
335 -- the detachment from this chain for unchecked deallocation, are generated
336 -- directly by the compiler during the expansion of allocators and calls to
337 -- instances of the Unchecked_Deallocation procedure.
339 type Final_Primitives is
340 (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
341 -- This enumeration type is defined in order to ease sharing code for
342 -- building finalization procedures for composite types.
344 Name_Of : constant array (Final_Primitives) of Name_Id :=
345 (Initialize_Case => Name_Initialize,
346 Adjust_Case => Name_Adjust,
347 Finalize_Case => Name_Finalize,
348 Address_Case => Name_Finalize_Address);
349 Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
350 (Initialize_Case => TSS_Deep_Initialize,
351 Adjust_Case => TSS_Deep_Adjust,
352 Finalize_Case => TSS_Deep_Finalize,
353 Address_Case => TSS_Finalize_Address);
355 function Allows_Finalization_Collection (Typ : Entity_Id) return Boolean;
356 -- Determine whether access type Typ may have a finalization collection
358 procedure Build_Array_Deep_Procs (Typ : Entity_Id);
359 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
360 -- Has_Controlled_Component set and store them using the TSS mechanism.
362 function Build_Cleanup_Statements
363 (N : Node_Id;
364 Additional_Cleanup : List_Id) return List_Id;
365 -- Create the cleanup calls for an asynchronous call block, task master,
366 -- protected subprogram body, task allocation block or task body, or
367 -- additional cleanup actions parked on a transient block. If the context
368 -- does not contain the above constructs, the routine returns an empty
369 -- list.
371 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
372 -- N is a construct that contains a handled sequence of statements, Fin_Id
373 -- is the entity of a finalizer. Create an At_End handler that covers the
374 -- statements of N and calls Fin_Id. If the handled statement sequence has
375 -- an exception handler, the statements will be wrapped in a block to avoid
376 -- unwanted interaction with the new At_End handler.
378 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
379 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
380 -- Has_Component_Component set and store them using the TSS mechanism.
382 --------------------------------
383 -- Transient Scope Management --
384 --------------------------------
386 -- A transient scope is needed when certain temporary objects are created
387 -- by the compiler. These temporary objects are allocated on the secondary
388 -- stack and/or need finalization, and the transient scope is responsible
389 -- for finalizing the objects and reclaiming the memory of the secondary
390 -- stack at the appropriate time. They are generally objects allocated to
391 -- store the result of a function returning an unconstrained or controlled
392 -- value. Expressions needing to be wrapped in a transient scope may appear
393 -- in three different contexts, which lead to different kinds of transient
394 -- scope expansion:
396 -- 1. In a simple statement (procedure call, assignment, ...). In this
397 -- case the statement is wrapped into a transient block, which takes
398 -- care of the finalization actions as well as the secondary stack
399 -- deallocation, See Wrap_Transient_Statement for details.
401 -- 2. In an expression of a control structure (test in a If statement,
402 -- expression in a Case statement, ...). In this case the expression
403 -- is replaced by a temporary and the enclosing statement is wrapped
404 -- into a transient block, which takes care of the finalization actions
405 -- and the secondary stack deallocation. See Wrap_Transient_Expression
406 -- for details.
408 -- 3. In an expression of an object declaration. No wrapping is possible
409 -- here, so the finalization actions performed on the normal path, if
410 -- any, are done right after the declaration, and those performed on
411 -- the exceptional path, as well as the secondary stack deallocation,
412 -- are deferred to the enclosing scope. See Wrap_Transient_Declaration
413 -- for details.
415 -- A transient scope is created by calling Establish_Transient_Scope on the
416 -- node that needs to be serviced by it (the serviced node can subsequently
417 -- be retrieved by invoking Node_To_Be_Wrapped when the current scope is a
418 -- transient scope). Once this has been done, the normal processing of the
419 -- Insert_Actions procedures is blocked and the procedures are redirected
420 -- to the Store_xxx_Actions_In_Scope procedures and Store_Actions_In_Scope
421 -- is ultimately invoked to store the pending actions.
423 -- A transient scope is finalized by calling one of the Wrap_Transient_xxx
424 -- procedures depending on the context as explained above. They ultimately
425 -- invoke Insert_Actions_In_Scope_Around as per the following picture:
427 -- Wrap_Transient_Expression Wrap_Transient_Statement
428 -- | |
429 -- V V
430 -- Make_Transient_Block
431 -- |
432 -- Wrap_Transient_Declaration |
433 -- | |
434 -- V V
435 -- Insert_Actions_In_Scope_Around
437 procedure Insert_Actions_In_Scope_Around
438 (N : Node_Id;
439 Clean : Boolean;
440 Manage_SS : Boolean);
441 -- Insert the before-actions kept in the scope stack before N, and the
442 -- after-actions after N, which must be a member of a list. If Clean is
443 -- true, insert any cleanup actions kept in the scope stack and generate
444 -- required finalization actions for the before-actions and after-actions.
445 -- If Manage_SS is true, insert calls to mark/release the secondary stack.
447 function Make_Transient_Block
448 (Loc : Source_Ptr;
449 Action : Node_Id;
450 Par : Node_Id) return Node_Id;
451 -- Action is a single statement or object declaration. Par is the proper
452 -- parent of the generated block. Create a transient block whose name is
453 -- the current scope and the only handled statement is Action. If Action
454 -- involves controlled objects or secondary stack usage, the corresponding
455 -- cleanup actions are performed at the end of the block.
457 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
458 -- Shared processing for Store_xxx_Actions_In_Scope
460 -------------------------------------------
461 -- Unnesting procedures for CCG and LLVM --
462 -------------------------------------------
464 -- Expansion generates subprograms for controlled types management that
465 -- may appear in declarative lists in package declarations and bodies.
466 -- These subprograms appear within generated blocks that contain local
467 -- declarations and a call to finalization procedures. To ensure that
468 -- such subprograms get activation records when needed, we transform the
469 -- block into a procedure body, followed by a call to it in the same
470 -- declarative list.
472 procedure Check_Unnesting_Elaboration_Code (N : Node_Id);
473 -- The statement part of a package body that is a compilation unit may
474 -- contain blocks that declare local subprograms. In Subprogram_Unnesting_
475 -- Mode such subprograms must be handled as nested inside the (implicit)
476 -- elaboration procedure that executes that statement part. To handle
477 -- properly uplevel references we construct that subprogram explicitly,
478 -- to contain blocks and inner subprograms, the statement part becomes
479 -- a call to this subprogram. This is only done if blocks are present
480 -- in the statement list of the body. (It would be nice to unify this
481 -- procedure with Check_Unnesting_In_Decls_Or_Stmts, if possible, since
482 -- they're doing very similar work, but are structured differently. ???)
484 procedure Check_Unnesting_In_Decls_Or_Stmts (Decls_Or_Stmts : List_Id);
485 -- Similarly, the declarations or statements in library-level packages may
486 -- have created blocks with nested subprograms. Such a block must be
487 -- transformed into a procedure followed by a call to it, so that unnesting
488 -- can handle uplevel references within these nested subprograms (typically
489 -- subprograms that handle finalization actions). This also applies to
490 -- nested packages, including instantiations, in which case it must
491 -- recursively process inner bodies.
493 procedure Check_Unnesting_In_Handlers (N : Node_Id);
494 -- Similarly, check for blocks with nested subprograms occurring within
495 -- a set of exception handlers associated with a package body N.
497 procedure Unnest_Block (Decl : Node_Id);
498 -- Blocks that contain nested subprograms with up-level references need to
499 -- create activation records for them. We do this by rewriting the block as
500 -- a procedure, followed by a call to it in the same declarative list, to
501 -- replicate the semantics of the original block.
503 -- A common source for such block is a transient block created for a
504 -- construct (declaration, assignment, etc.) that involves controlled
505 -- actions or secondary-stack management, in which case the nested
506 -- subprogram is a finalizer.
508 procedure Unnest_If_Statement (If_Stmt : Node_Id);
509 -- The separate statement lists associated with an if-statement (then part,
510 -- elsif parts, else part) may require unnesting if they directly contain
511 -- a subprogram body that references up-level objects. Each statement list
512 -- is traversed to locate such subprogram bodies, and if a part's statement
513 -- list contains a body, then the list is replaced with a new procedure
514 -- containing the part's statements followed by a call to the procedure.
515 -- Furthermore, any nested blocks, loops, or if statements will also be
516 -- traversed to determine the need for further unnesting transformations.
518 procedure Unnest_Statement_List (Stmts : in out List_Id);
519 -- A list of statements that directly contains a subprogram at its outer
520 -- level, that may reference objects declared in that same statement list,
521 -- is rewritten as a procedure containing the statement list Stmts (which
522 -- includes any such objects as well as the nested subprogram), followed by
523 -- a call to the new procedure, and Stmts becomes the list containing the
524 -- procedure and the call. This ensures that Unnest_Subprogram will later
525 -- properly handle up-level references from the nested subprogram to
526 -- objects declared earlier in statement list, by creating an activation
527 -- record and passing it to the nested subprogram. This procedure also
528 -- resets the Scope of objects declared in the statement list, as well as
529 -- the Scope of the nested subprogram, to refer to the new procedure.
530 -- Also, the new procedure is marked Has_Nested_Subprogram, so this should
531 -- only be called when known that the statement list contains a subprogram.
533 procedure Unnest_Loop (Loop_Stmt : Node_Id);
534 -- Top-level Loops that contain nested subprograms with up-level references
535 -- need to have activation records. We do this by rewriting the loop as a
536 -- procedure containing the loop, followed by a call to the procedure in
537 -- the same library-level declarative list, to replicate the semantics of
538 -- the original loop. Such loops can occur due to aggregate expansions and
539 -- other constructs.
541 -----------------------
542 -- Local Subprograms --
543 -----------------------
545 procedure Check_Visibly_Controlled
546 (Prim : Final_Primitives;
547 Typ : Entity_Id;
548 E : in out Entity_Id;
549 Cref : in out Node_Id);
550 -- The controlled operation declared for a derived type may not be
551 -- overriding, if the controlled operations of the parent type are hidden,
552 -- for example when the parent is a private type whose full view is
553 -- controlled. For other primitive operations we modify the name of the
554 -- operation to indicate that it is not overriding, but this is not
555 -- possible for Initialize, etc. because they have to be retrievable by
556 -- name. Before generating the proper call to one of these operations we
557 -- check whether Typ is known to be controlled at the point of definition.
558 -- If it is not then we must retrieve the hidden operation of the parent
559 -- and use it instead. This is one case that might be solved more cleanly
560 -- once Overriding pragmas or declarations are in place.
562 function Contains_Subprogram (Blk : Entity_Id) return Boolean;
563 -- Check recursively whether a loop or block contains a subprogram that
564 -- may need an activation record.
566 function Convert_View (Proc : Entity_Id; Arg : Node_Id) return Node_Id;
567 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
568 -- argument being passed to it. This function will, if necessary, generate
569 -- a conversion between the partial and full view of Arg to match the type
570 -- of the formal of Proc, or force a conversion to the class-wide type in
571 -- the case where the operation is abstract.
573 function Make_Call
574 (Loc : Source_Ptr;
575 Proc_Id : Entity_Id;
576 Param : Node_Id;
577 Skip_Self : Boolean := False) return Node_Id;
578 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
579 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
580 -- an adjust or finalization call. When flag Skip_Self is set, the related
581 -- action has an effect on the components only (if any).
583 function Make_Deep_Proc
584 (Prim : Final_Primitives;
585 Typ : Entity_Id;
586 Stmts : List_Id) return Entity_Id;
587 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
588 -- Deep_Finalize procedures according to the first parameter. These
589 -- procedures operate on the type Typ. The Stmts parameter gives the
590 -- body of the procedure.
592 function Make_Deep_Array_Body
593 (Prim : Final_Primitives;
594 Typ : Entity_Id) return List_Id;
595 -- This function generates the list of statements for implementing
596 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
597 -- the first parameter, these procedures operate on the array type Typ.
599 function Make_Deep_Record_Body
600 (Prim : Final_Primitives;
601 Typ : Entity_Id;
602 Is_Local : Boolean := False) return List_Id;
603 -- This function generates the list of statements for implementing
604 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
605 -- the first parameter, these procedures operate on the record type Typ.
606 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
607 -- whether the inner logic should be dictated by state counters.
609 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
610 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
611 -- Make_Deep_Record_Body. Generate the following statements:
613 -- declare
614 -- type Acc_Typ is access all Typ;
615 -- for Acc_Typ'Storage_Size use 0;
616 -- begin
617 -- [Deep_]Finalize (Acc_Typ (V).all);
618 -- end;
620 ----------------------------------
621 -- Attach_Object_To_Master_Node --
622 ----------------------------------
624 procedure Attach_Object_To_Master_Node
625 (Obj_Decl : Node_Id;
626 Master_Node : Entity_Id)
628 Loc : constant Source_Ptr := Sloc (Obj_Decl);
629 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
630 Func_Id : constant Entity_Id :=
631 (if Is_Return_Object (Obj_Id)
632 then Return_Applies_To (Scope (Obj_Id))
633 else Empty);
635 function Build_BIP_Cleanup_Stmts
636 (Func_Id : Entity_Id;
637 Obj_Addr : Node_Id) return Node_Id;
638 -- Func_Id denotes a build-in-place function. Generate the following
639 -- cleanup code:
641 -- if BIPallocform > Secondary_Stack'Pos
642 -- and then BIPcollection /= null
643 -- then
644 -- declare
645 -- type Ptr_Typ is access Fun_Typ;
646 -- for Ptr_Typ'Storage_Pool use BIPstoragepool.all;
648 -- begin
649 -- Free (Ptr_Typ (Obj_Addr));
650 -- end;
651 -- end if;
653 -- Fun_Typ is the return type of the Func_Id.
655 -----------------------------
656 -- Build_BIP_Cleanup_Stmts --
657 -----------------------------
659 function Build_BIP_Cleanup_Stmts
660 (Func_Id : Entity_Id;
661 Obj_Addr : Node_Id) return Node_Id
663 Alloc_Id : constant Entity_Id :=
664 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
665 Decls : constant List_Id := New_List;
666 Fin_Coll_Id : constant Entity_Id :=
667 Build_In_Place_Formal (Func_Id, BIP_Collection);
668 Func_Typ : constant Entity_Id := Etype (Func_Id);
670 Cond : Node_Id;
671 Free_Blk : Node_Id;
672 Free_Stmt : Node_Id;
673 Pool_Id : Entity_Id;
674 Ptr_Typ : Entity_Id;
676 begin
677 -- Generate:
678 -- Pool_Id renames BIPstoragepool.all;
680 -- This formal is not added on ZFP as those targets do not
681 -- support pools.
683 if RTE_Available (RE_Root_Storage_Pool_Ptr) then
684 Pool_Id := Make_Temporary (Loc, 'P');
686 Append_To (Decls,
687 Make_Object_Renaming_Declaration (Loc,
688 Defining_Identifier => Pool_Id,
689 Subtype_Mark =>
690 New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
691 Name =>
692 Make_Explicit_Dereference (Loc,
693 New_Occurrence_Of
694 (Build_In_Place_Formal
695 (Func_Id, BIP_Storage_Pool), Loc))));
697 if Debug_Generated_Code then
698 Set_Debug_Info_Needed (Pool_Id);
699 end if;
701 else
702 Pool_Id := Empty;
703 end if;
705 -- Create an access type which uses the storage pool of the caller
707 -- Generate:
708 -- type Ptr_Typ is access Func_Typ;
710 Ptr_Typ := Make_Temporary (Loc, 'P');
712 Append_To (Decls,
713 Make_Full_Type_Declaration (Loc,
714 Defining_Identifier => Ptr_Typ,
715 Type_Definition =>
716 Make_Access_To_Object_Definition (Loc,
717 Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
719 -- Perform minor decoration in order to set the collection and the
720 -- storage pool attributes.
722 Mutate_Ekind (Ptr_Typ, E_Access_Type);
723 Set_Finalization_Collection (Ptr_Typ, Fin_Coll_Id);
724 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
726 -- Create an explicit free statement. Note that the free uses the
727 -- caller's pool expressed as a renaming.
729 Free_Stmt :=
730 Make_Free_Statement (Loc,
731 Expression =>
732 Unchecked_Convert_To (Ptr_Typ, Obj_Addr));
734 Set_Storage_Pool (Free_Stmt, Pool_Id);
736 -- Create a block to house the dummy type and the instantiation as
737 -- well as to perform the cleanup the temporary.
739 -- Generate:
740 -- declare
741 -- <Decls>
742 -- begin
743 -- Free (Ptr_Typ (Obj_Addr));
744 -- end;
746 Free_Blk :=
747 Make_Block_Statement (Loc,
748 Declarations => Decls,
749 Handled_Statement_Sequence =>
750 Make_Handled_Sequence_Of_Statements (Loc,
751 Statements => New_List (Free_Stmt)));
753 -- Generate:
754 -- if BIPallocform > Secondary_Stack'Pos
755 -- and then BIPcollection /= null
756 -- then
758 Cond :=
759 Make_And_Then (Loc,
760 Left_Opnd =>
761 Make_Op_Gt (Loc,
762 Left_Opnd => New_Occurrence_Of (Alloc_Id, Loc),
763 Right_Opnd =>
764 Make_Integer_Literal (Loc,
765 UI_From_Int (BIP_Allocation_Form'Pos (Secondary_Stack)))),
766 Right_Opnd =>
767 Make_Op_Ne (Loc,
768 Left_Opnd => New_Occurrence_Of (Fin_Coll_Id, Loc),
769 Right_Opnd => Make_Null (Loc)));
771 -- Generate:
772 -- if <Cond> then
773 -- <Free_Blk>
774 -- end if;
776 return
777 Make_If_Statement (Loc,
778 Condition => Cond,
779 Then_Statements => New_List (Free_Blk));
780 end Build_BIP_Cleanup_Stmts;
782 -- Local variables
784 Fin_Id : Entity_Id;
785 Master_Node_Attach : Node_Id;
786 Master_Node_Ins : Node_Id;
787 Obj_Ref : Node_Id;
788 Obj_Typ : Entity_Id;
790 -- Start of processing for Attach_Object_To_Master_Node
792 begin
793 -- Finalize_Address is not generated in CodePeer mode because the
794 -- body contains address arithmetic. So we don't want to generate
795 -- the attach in this case.
797 if CodePeer_Mode then
798 return;
799 end if;
801 -- When the object is initialized by an aggregate, the attachment must
802 -- occur after the last aggregate assignment takes place; only then is
803 -- the object considered initialized. Likewise if it is initialized by
804 -- a build-in-place call: we must attach only after the call.
806 if Ekind (Obj_Id) in E_Constant | E_Variable then
807 if Present (Last_Aggregate_Assignment (Obj_Id)) then
808 Master_Node_Ins := Last_Aggregate_Assignment (Obj_Id);
809 elsif Present (BIP_Initialization_Call (Obj_Id)) then
810 Master_Node_Ins := BIP_Initialization_Call (Obj_Id);
811 else
812 Master_Node_Ins := Obj_Decl;
813 end if;
815 else
816 Master_Node_Ins := Obj_Decl;
817 end if;
819 -- Handle the object type and the reference to the object
821 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
822 Obj_Typ := Etype (Obj_Id);
823 if not Is_Class_Wide_Type (Obj_Typ) then
824 Obj_Typ := Base_Type (Obj_Typ);
825 end if;
827 if Is_Access_Type (Obj_Typ) then
828 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
829 Obj_Typ := Available_View (Designated_Type (Obj_Typ));
830 end if;
832 -- If we are dealing with a return object of a build-in-place function
833 -- and its allocation has been done in the function, we additionally
834 -- need to detach it from the caller's finalization collection in order
835 -- to prevent double finalization.
837 if Present (Func_Id)
838 and then Is_Build_In_Place_Function (Func_Id)
839 and then Needs_BIP_Collection (Func_Id)
840 then
841 declare
842 Ptr_Typ : constant Node_Id := Make_Temporary (Loc, 'P');
843 Param : constant Entity_Id :=
844 Make_Defining_Identifier (Loc, Name_V);
846 Fin_Body : Node_Id;
847 Fin_Stmts : List_Id;
849 begin
850 Fin_Stmts := Make_Finalize_Address_Stmts (Obj_Typ);
852 Append_To (Fin_Stmts,
853 Build_BIP_Cleanup_Stmts
854 (Func_Id, New_Occurrence_Of (Param, Loc)));
856 Fin_Id :=
857 Make_Defining_Identifier (Loc,
858 Make_TSS_Name_Local
859 (Obj_Typ, TSS_Finalize_Address));
861 Fin_Body :=
862 Make_Subprogram_Body (Loc,
863 Specification =>
864 Make_Procedure_Specification (Loc,
865 Defining_Unit_Name => Fin_Id,
867 Parameter_Specifications => New_List (
868 Make_Parameter_Specification (Loc,
869 Defining_Identifier => Param,
870 Parameter_Type =>
871 New_Occurrence_Of (RTE (RE_Address), Loc)))),
873 Declarations => New_List (
874 Make_Full_Type_Declaration (Loc,
875 Defining_Identifier => Ptr_Typ,
876 Type_Definition =>
877 Make_Access_To_Object_Definition (Loc,
878 All_Present => True,
879 Subtype_Indication =>
880 New_Occurrence_Of (Obj_Typ, Loc)))),
882 Handled_Statement_Sequence =>
883 Make_Handled_Sequence_Of_Statements (Loc,
884 Statements => Fin_Stmts));
886 Insert_After_And_Analyze
887 (Master_Node_Ins, Fin_Body, Suppress => All_Checks);
889 Master_Node_Ins := Fin_Body;
890 end;
892 else
893 Fin_Id := Finalize_Address (Obj_Typ);
895 if No (Fin_Id) and then Ekind (Obj_Typ) = E_Class_Wide_Subtype then
896 Fin_Id := TSS (Obj_Typ, TSS_Finalize_Address);
897 end if;
898 end if;
900 -- Now build the attachment call that will initialize the object's
901 -- Master_Node using the object's address and finalization procedure.
903 Master_Node_Attach :=
904 Make_Procedure_Call_Statement (Loc,
905 Name =>
906 New_Occurrence_Of (RTE (RE_Attach_Object_To_Node), Loc),
907 Parameter_Associations => New_List (
908 Make_Address_For_Finalize (Loc, Obj_Ref, Obj_Typ),
909 Make_Attribute_Reference (Loc,
910 Prefix =>
911 New_Occurrence_Of (Fin_Id, Loc),
912 Attribute_Name => Name_Unrestricted_Access),
913 New_Occurrence_Of (Master_Node, Loc)));
915 Insert_After_And_Analyze
916 (Master_Node_Ins, Master_Node_Attach, Suppress => All_Checks);
917 end Attach_Object_To_Master_Node;
919 ------------------------------------
920 -- Allows_Finalization_Collection --
921 ------------------------------------
923 function Allows_Finalization_Collection (Typ : Entity_Id) return Boolean is
924 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
925 -- Determine whether entity E is inside a wrapper package created for
926 -- an instance of Ada.Unchecked_Deallocation.
928 ------------------------------
929 -- In_Deallocation_Instance --
930 ------------------------------
932 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
933 Pkg : constant Entity_Id := Scope (E);
934 Par : Node_Id := Empty;
936 begin
937 if Ekind (Pkg) = E_Package
938 and then Present (Related_Instance (Pkg))
939 and then Ekind (Related_Instance (Pkg)) = E_Procedure
940 then
941 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
943 return
944 Present (Par)
945 and then Chars (Par) = Name_Unchecked_Deallocation
946 and then Chars (Scope (Par)) = Name_Ada
947 and then Scope (Scope (Par)) = Standard_Standard;
948 end if;
950 return False;
951 end In_Deallocation_Instance;
953 -- Local variables
955 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
956 Ptr_Typ : constant Entity_Id :=
957 Root_Type_Of_Full_View (Base_Type (Typ));
959 -- Start of processing for Allows_Finalization_Collection
961 begin
962 -- Certain run-time configurations and targets do not provide support
963 -- for controlled types and therefore do not need collections.
965 if Restriction_Active (No_Finalization) then
966 return False;
968 -- Do not consider C and C++ types since it is assumed that the non-Ada
969 -- side will handle their cleanup.
971 elsif Convention (Desig_Typ) = Convention_C
972 or else Convention (Desig_Typ) = Convention_CPP
973 then
974 return False;
976 -- Do not consider an access type that returns on the secondary stack
978 elsif Present (Associated_Storage_Pool (Ptr_Typ))
979 and then Is_RTE (Associated_Storage_Pool (Ptr_Typ), RE_SS_Pool)
980 then
981 return False;
983 -- Do not consider an access type that can never allocate an object
985 elsif No_Pool_Assigned (Ptr_Typ) then
986 return False;
988 -- Do not consider an access type coming from an Unchecked_Deallocation
989 -- instance. Even though the designated type may be controlled, the
990 -- access type will never participate in any allocations.
992 elsif In_Deallocation_Instance (Ptr_Typ) then
993 return False;
995 -- Do not consider a non-library access type when No_Nested_Finalization
996 -- is in effect, because finalization collections are controlled objects
997 -- and, if created, will violate the restriction.
999 elsif Restriction_Active (No_Nested_Finalization)
1000 and then not Is_Library_Level_Entity (Ptr_Typ)
1001 then
1002 return False;
1004 -- Do not consider an access type subject to pragma No_Heap_Finalization
1005 -- because objects allocated through such a type are not to be finalized
1006 -- when the access type goes out of scope.
1008 elsif No_Heap_Finalization (Ptr_Typ) then
1009 return False;
1011 -- Do not create finalization collections in GNATprove mode because this
1012 -- causes unwanted extra expansion. Compilation in this mode must always
1013 -- keep the tree as close as possible to the original sources.
1015 elsif GNATprove_Mode then
1016 return False;
1018 -- Otherwise the access type may use a finalization collection
1020 else
1021 return True;
1022 end if;
1023 end Allows_Finalization_Collection;
1025 --------------------------------
1026 -- Build_Anonymous_Collection --
1027 --------------------------------
1029 procedure Build_Anonymous_Collection (Ptr_Typ : Entity_Id) is
1030 function Create_Anonymous_Collection
1031 (Desig_Typ : Entity_Id;
1032 Unit_Id : Entity_Id;
1033 Unit_Decl : Node_Id) return Entity_Id;
1034 -- Create a new anonymous collection for access type Ptr_Typ with
1035 -- designated type Desig_Typ. The declaration of the collection and
1036 -- its initialization are inserted in the declarative part of unit
1037 -- Unit_Decl. Unit_Id is the entity of Unit_Decl.
1039 function Current_Anonymous_Collection
1040 (Desig_Typ : Entity_Id;
1041 Unit_Id : Entity_Id) return Entity_Id;
1042 -- Find an anonymous collection declared in unit Unit_Id which services
1043 -- designated type Desig_Typ. If there is none, return Empty.
1045 ---------------------------------
1046 -- Create_Anonymous_Collection --
1047 ---------------------------------
1049 function Create_Anonymous_Collection
1050 (Desig_Typ : Entity_Id;
1051 Unit_Id : Entity_Id;
1052 Unit_Decl : Node_Id) return Entity_Id
1054 Loc : constant Source_Ptr := Sloc (Unit_Id);
1056 All_FCs : Elist_Id;
1057 Decls : List_Id;
1058 FC_Decl : Node_Id;
1059 FC_Id : Entity_Id;
1060 Unit_Spec : Node_Id;
1062 begin
1063 -- Generate:
1064 -- <FC_Id> : Finalization_Collection;
1066 FC_Id := Make_Temporary (Loc, 'A');
1068 FC_Decl :=
1069 Make_Object_Declaration (Loc,
1070 Defining_Identifier => FC_Id,
1071 Object_Definition =>
1072 New_Occurrence_Of (RTE (RE_Finalization_Collection), Loc));
1074 -- Find the declarative list of the unit
1076 if Nkind (Unit_Decl) = N_Package_Declaration then
1077 Unit_Spec := Specification (Unit_Decl);
1078 Decls := Visible_Declarations (Unit_Spec);
1080 if No (Decls) then
1081 Decls := New_List;
1082 Set_Visible_Declarations (Unit_Spec, Decls);
1083 end if;
1085 -- Package body or subprogram case
1087 -- ??? A subprogram spec or body that acts as a compilation unit may
1088 -- contain a formal parameter of an anonymous access-to-controlled
1089 -- type initialized by an allocator.
1091 -- procedure Comp_Unit_Proc (Param : access Ctrl := new Ctrl);
1093 -- There is no suitable place to create the collection because the
1094 -- subprogram is not in a declarative list.
1096 else
1097 Decls := Declarations (Unit_Decl);
1099 if No (Decls) then
1100 Decls := New_List;
1101 Set_Declarations (Unit_Decl, Decls);
1102 end if;
1103 end if;
1105 Prepend_To (Decls, FC_Decl);
1107 -- Use the scope of the unit when analyzing the declaration of the
1108 -- collection and its initialization actions.
1110 Push_Scope (Unit_Id);
1111 Analyze (FC_Decl);
1112 Pop_Scope;
1114 -- Mark the collection as servicing this specific designated type
1116 Set_Anonymous_Designated_Type (FC_Id, Desig_Typ);
1118 -- Include it in the list of existing anonymous collections which
1119 -- appear in this unit. This effectively creates a mapping between
1120 -- collections and designated types, which in turn allows for the
1121 -- reuse of collections on a per-unit basis.
1123 All_FCs := Anonymous_Collections (Unit_Id);
1125 if No (All_FCs) then
1126 All_FCs := New_Elmt_List;
1127 Set_Anonymous_Collections (Unit_Id, All_FCs);
1128 end if;
1130 Prepend_Elmt (FC_Id, All_FCs);
1132 return FC_Id;
1133 end Create_Anonymous_Collection;
1135 ----------------------------------
1136 -- Current_Anonymous_Collection --
1137 ----------------------------------
1139 function Current_Anonymous_Collection
1140 (Desig_Typ : Entity_Id;
1141 Unit_Id : Entity_Id) return Entity_Id
1143 All_FCs : constant Elist_Id := Anonymous_Collections (Unit_Id);
1144 FC_Elmt : Elmt_Id;
1145 FC_Id : Entity_Id;
1147 begin
1148 -- Inspect the list of anonymous collections declared within the unit
1149 -- looking for an existing collection which services the designated
1150 -- type.
1152 if Present (All_FCs) then
1153 FC_Elmt := First_Elmt (All_FCs);
1154 while Present (FC_Elmt) loop
1155 FC_Id := Node (FC_Elmt);
1157 -- The current collection services the same designated type.
1158 -- As a result, the collection can be reused and associated
1159 -- with another anonymous access-to-controlled type.
1161 if Anonymous_Designated_Type (FC_Id) = Desig_Typ then
1162 return FC_Id;
1163 end if;
1165 Next_Elmt (FC_Elmt);
1166 end loop;
1167 end if;
1169 return Empty;
1170 end Current_Anonymous_Collection;
1172 -- Local variables
1174 Desig_Typ : Entity_Id;
1175 FC_Id : Entity_Id;
1176 Priv_View : Entity_Id;
1177 Scop : Entity_Id;
1178 Unit_Decl : Node_Id;
1179 Unit_Id : Entity_Id;
1181 -- Start of processing for Build_Anonymous_Collection
1183 begin
1184 -- Nothing to do if the circumstances do not allow for a finalization
1185 -- collection.
1187 if not Allows_Finalization_Collection (Ptr_Typ) then
1188 return;
1189 end if;
1191 Unit_Decl := Unit (Cunit (Current_Sem_Unit));
1192 Unit_Id := Unique_Defining_Entity (Unit_Decl);
1194 -- The compilation unit is a package instantiation. In this case the
1195 -- anonymous collection is associated with the package spec, as both
1196 -- the spec and body appear at the same level.
1198 if Nkind (Unit_Decl) = N_Package_Body
1199 and then Nkind (Original_Node (Unit_Decl)) = N_Package_Instantiation
1200 then
1201 Unit_Id := Corresponding_Spec (Unit_Decl);
1202 Unit_Decl := Unit_Declaration_Node (Unit_Id);
1203 end if;
1205 -- Use the initial declaration of the designated type when it denotes
1206 -- the full view of an incomplete or private type. This ensures that
1207 -- types with one and two views are treated the same.
1209 Desig_Typ := Directly_Designated_Type (Ptr_Typ);
1210 Priv_View := Incomplete_Or_Partial_View (Desig_Typ);
1212 if Present (Priv_View) then
1213 Desig_Typ := Priv_View;
1214 end if;
1216 -- For a designated type not declared at library level, we cannot create
1217 -- a finalization collection attached to an outer unit since this would
1218 -- generate dangling references to the dynamic scope through access-to-
1219 -- procedure values designating the local Finalize_Address primitive.
1221 Scop := Enclosing_Dynamic_Scope (Desig_Typ);
1222 if Scop /= Standard_Standard
1223 and then Scope_Depth (Scop) > Scope_Depth (Unit_Id)
1224 then
1225 return;
1226 end if;
1228 -- Determine whether the current semantic unit already has an anonymous
1229 -- collection which services the designated type.
1231 FC_Id := Current_Anonymous_Collection (Desig_Typ, Unit_Id);
1233 -- If this is not the case, create a new collection
1235 if No (FC_Id) then
1236 FC_Id := Create_Anonymous_Collection (Desig_Typ, Unit_Id, Unit_Decl);
1237 end if;
1239 Set_Finalization_Collection (Ptr_Typ, FC_Id);
1240 end Build_Anonymous_Collection;
1242 ----------------------------
1243 -- Build_Array_Deep_Procs --
1244 ----------------------------
1246 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
1247 begin
1248 Set_TSS (Typ,
1249 Make_Deep_Proc
1250 (Prim => Initialize_Case,
1251 Typ => Typ,
1252 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
1254 if not Is_Inherently_Limited_Type (Typ) then
1255 Set_TSS (Typ,
1256 Make_Deep_Proc
1257 (Prim => Adjust_Case,
1258 Typ => Typ,
1259 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
1260 end if;
1262 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
1263 -- suppressed since these routine will not be used.
1265 if not Restriction_Active (No_Finalization) then
1266 Set_TSS (Typ,
1267 Make_Deep_Proc
1268 (Prim => Finalize_Case,
1269 Typ => Typ,
1270 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
1272 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
1274 if not CodePeer_Mode then
1275 Set_TSS (Typ,
1276 Make_Deep_Proc
1277 (Prim => Address_Case,
1278 Typ => Typ,
1279 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
1280 end if;
1281 end if;
1282 end Build_Array_Deep_Procs;
1284 ------------------------------
1285 -- Build_Cleanup_Statements --
1286 ------------------------------
1288 function Build_Cleanup_Statements
1289 (N : Node_Id;
1290 Additional_Cleanup : List_Id) return List_Id
1292 Is_Asynchronous_Call : constant Boolean :=
1293 Nkind (N) = N_Block_Statement and then Is_Asynchronous_Call_Block (N);
1294 Is_Master : constant Boolean :=
1295 Nkind (N) /= N_Entry_Body and then Is_Task_Master (N);
1296 Is_Protected_Subp_Body : constant Boolean :=
1297 Nkind (N) = N_Subprogram_Body
1298 and then Is_Protected_Subprogram_Body (N);
1299 Is_Task_Allocation : constant Boolean :=
1300 Nkind (N) = N_Block_Statement and then Is_Task_Allocation_Block (N);
1301 Is_Task_Body : constant Boolean :=
1302 Nkind (Original_Node (N)) = N_Task_Body;
1304 Loc : constant Source_Ptr := Sloc (N);
1305 Stmts : constant List_Id := New_List;
1307 begin
1308 if Is_Task_Body then
1309 if Restricted_Profile then
1310 Append_To (Stmts,
1311 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
1312 else
1313 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
1314 end if;
1316 elsif Is_Master then
1317 if Restriction_Active (No_Task_Hierarchy) = False then
1318 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
1319 end if;
1321 -- Add statements to unlock the protected object parameter and to
1322 -- undefer abort. If the context is a protected procedure and the object
1323 -- has entries, call the entry service routine.
1325 -- NOTE: The generated code references _object, a parameter to the
1326 -- procedure.
1328 elsif Is_Protected_Subp_Body then
1329 declare
1330 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
1331 Conc_Typ : Entity_Id := Empty;
1332 Param : Node_Id;
1333 Param_Typ : Entity_Id;
1335 begin
1336 -- Find the _object parameter representing the protected object
1338 Param := First (Parameter_Specifications (Spec));
1339 loop
1340 Param_Typ := Etype (Parameter_Type (Param));
1342 if Ekind (Param_Typ) = E_Record_Type then
1343 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
1344 end if;
1346 exit when No (Param) or else Present (Conc_Typ);
1347 Next (Param);
1348 end loop;
1350 pragma Assert (Present (Param));
1351 pragma Assert (Present (Conc_Typ));
1353 Build_Protected_Subprogram_Call_Cleanup
1354 (Specification (N), Conc_Typ, Loc, Stmts);
1355 end;
1357 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
1358 -- tasks. Other unactivated tasks are completed by Complete_Task or
1359 -- Complete_Master.
1361 -- NOTE: The generated code references _chain, a local object
1363 elsif Is_Task_Allocation then
1365 -- Generate:
1366 -- Expunge_Unactivated_Tasks (_chain);
1368 -- where _chain is the list of tasks created by the allocator but not
1369 -- yet activated. This list will be empty unless the block completes
1370 -- abnormally.
1372 Append_To (Stmts,
1373 Make_Procedure_Call_Statement (Loc,
1374 Name =>
1375 New_Occurrence_Of
1376 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
1377 Parameter_Associations => New_List (
1378 New_Occurrence_Of (Activation_Chain_Entity (N), Loc))));
1380 -- Attempt to cancel an asynchronous entry call whenever the block which
1381 -- contains the abortable part is exited.
1383 -- NOTE: The generated code references Cnn, a local object
1385 elsif Is_Asynchronous_Call then
1386 declare
1387 Cancel_Param : constant Entity_Id :=
1388 Entry_Cancel_Parameter (Entity (Identifier (N)));
1390 begin
1391 -- If it is of type Communication_Block, this must be a protected
1392 -- entry call. Generate:
1394 -- if Enqueued (Cancel_Param) then
1395 -- Cancel_Protected_Entry_Call (Cancel_Param);
1396 -- end if;
1398 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
1399 Append_To (Stmts,
1400 Make_If_Statement (Loc,
1401 Condition =>
1402 Make_Function_Call (Loc,
1403 Name =>
1404 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
1405 Parameter_Associations => New_List (
1406 New_Occurrence_Of (Cancel_Param, Loc))),
1408 Then_Statements => New_List (
1409 Make_Procedure_Call_Statement (Loc,
1410 Name =>
1411 New_Occurrence_Of
1412 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
1413 Parameter_Associations => New_List (
1414 New_Occurrence_Of (Cancel_Param, Loc))))));
1416 -- Asynchronous delay, generate:
1417 -- Cancel_Async_Delay (Cancel_Param);
1419 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
1420 Append_To (Stmts,
1421 Make_Procedure_Call_Statement (Loc,
1422 Name =>
1423 New_Occurrence_Of (RTE (RE_Cancel_Async_Delay), Loc),
1424 Parameter_Associations => New_List (
1425 Make_Attribute_Reference (Loc,
1426 Prefix =>
1427 New_Occurrence_Of (Cancel_Param, Loc),
1428 Attribute_Name => Name_Unchecked_Access))));
1430 -- Task entry call, generate:
1431 -- Cancel_Task_Entry_Call (Cancel_Param);
1433 else
1434 Append_To (Stmts,
1435 Make_Procedure_Call_Statement (Loc,
1436 Name =>
1437 New_Occurrence_Of (RTE (RE_Cancel_Task_Entry_Call), Loc),
1438 Parameter_Associations => New_List (
1439 New_Occurrence_Of (Cancel_Param, Loc))));
1440 end if;
1441 end;
1442 end if;
1444 Append_List_To (Stmts, Additional_Cleanup);
1445 return Stmts;
1446 end Build_Cleanup_Statements;
1448 -----------------------------
1449 -- Build_Controlling_Procs --
1450 -----------------------------
1452 procedure Build_Controlling_Procs (Typ : Entity_Id) is
1453 begin
1454 if Is_Array_Type (Typ) then
1455 Build_Array_Deep_Procs (Typ);
1456 else pragma Assert (Is_Record_Type (Typ));
1457 Build_Record_Deep_Procs (Typ);
1458 end if;
1459 end Build_Controlling_Procs;
1461 -----------------------------
1462 -- Build_Exception_Handler --
1463 -----------------------------
1465 function Build_Exception_Handler
1466 (Data : Finalization_Exception_Data;
1467 For_Library : Boolean := False) return Node_Id
1469 Actuals : List_Id;
1470 Proc_To_Call : Entity_Id;
1471 Except : Node_Id;
1472 Stmts : List_Id;
1474 begin
1475 pragma Assert (Present (Data.Raised_Id));
1477 if Exception_Extra_Info
1478 or else (For_Library and not Restricted_Profile)
1479 then
1480 if Exception_Extra_Info then
1482 -- Generate:
1484 -- Get_Current_Excep.all
1486 Except :=
1487 Make_Function_Call (Data.Loc,
1488 Name =>
1489 Make_Explicit_Dereference (Data.Loc,
1490 Prefix =>
1491 New_Occurrence_Of
1492 (RTE (RE_Get_Current_Excep), Data.Loc)));
1494 else
1495 -- Generate:
1497 -- null
1499 Except := Make_Null (Data.Loc);
1500 end if;
1502 if For_Library and then not Restricted_Profile then
1503 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
1504 Actuals := New_List (Except);
1506 else
1507 Proc_To_Call := RTE (RE_Save_Occurrence);
1509 -- The dereference occurs only when Exception_Extra_Info is true,
1510 -- and therefore Except is not null.
1512 Actuals :=
1513 New_List (
1514 New_Occurrence_Of (Data.E_Id, Data.Loc),
1515 Make_Explicit_Dereference (Data.Loc, Except));
1516 end if;
1518 -- Generate:
1520 -- when others =>
1521 -- if not Raised_Id then
1522 -- Raised_Id := True;
1524 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
1525 -- or
1526 -- Save_Library_Occurrence (Get_Current_Excep.all);
1527 -- end if;
1529 Stmts :=
1530 New_List (
1531 Make_If_Statement (Data.Loc,
1532 Condition =>
1533 Make_Op_Not (Data.Loc,
1534 Right_Opnd => New_Occurrence_Of (Data.Raised_Id, Data.Loc)),
1536 Then_Statements => New_List (
1537 Make_Assignment_Statement (Data.Loc,
1538 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1539 Expression => New_Occurrence_Of (Standard_True, Data.Loc)),
1541 Make_Procedure_Call_Statement (Data.Loc,
1542 Name =>
1543 New_Occurrence_Of (Proc_To_Call, Data.Loc),
1544 Parameter_Associations => Actuals))));
1546 else
1547 -- Generate:
1549 -- Raised_Id := True;
1551 Stmts := New_List (
1552 Make_Assignment_Statement (Data.Loc,
1553 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1554 Expression => New_Occurrence_Of (Standard_True, Data.Loc)));
1555 end if;
1557 -- Generate:
1559 -- when others =>
1561 return
1562 Make_Exception_Handler (Data.Loc,
1563 Exception_Choices => New_List (Make_Others_Choice (Data.Loc)),
1564 Statements => Stmts);
1565 end Build_Exception_Handler;
1567 -----------------------------------
1568 -- Build_Finalization_Collection --
1569 -----------------------------------
1571 procedure Build_Finalization_Collection
1572 (Typ : Entity_Id;
1573 For_Lib_Level : Boolean := False;
1574 For_Private : Boolean := False;
1575 Context_Scope : Entity_Id := Empty;
1576 Insertion_Node : Node_Id := Empty)
1578 Ptr_Typ : constant Entity_Id := Root_Type_Of_Full_View (Base_Type (Typ));
1579 -- Finalization collections built for named access types are associated
1580 -- with the full view (if applicable) as a consequence of freezing. The
1581 -- full view criteria does not apply to anonymous access types because
1582 -- those cannot have a private and a full view.
1584 -- Start of processing for Build_Finalization_Collection
1586 begin
1587 -- Nothing to do if the circumstances do not allow for a finalization
1588 -- collection.
1590 if not Allows_Finalization_Collection (Typ) then
1591 return;
1593 -- Various machinery such as freezing may have already created a
1594 -- finalization collection.
1596 elsif Present (Finalization_Collection (Ptr_Typ)) then
1597 return;
1598 end if;
1600 declare
1601 Actions : constant List_Id := New_List;
1602 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
1604 Fin_Coll_Id : Entity_Id;
1605 Pool_Id : Entity_Id;
1607 begin
1608 -- Source access types use fixed names since the collection will be
1609 -- inserted in the same source unit only once. The only exception to
1610 -- this are instances using the same access type as generic actual.
1612 if Comes_From_Source (Ptr_Typ) and then not Inside_A_Generic then
1613 Fin_Coll_Id :=
1614 Make_Defining_Identifier (Loc,
1615 Chars => New_External_Name (Chars (Ptr_Typ), "FC"));
1617 -- Internally generated access types use temporaries as their names
1618 -- due to possible collision with identical names coming from other
1619 -- packages.
1621 else
1622 Fin_Coll_Id := Make_Temporary (Loc, 'F');
1623 end if;
1625 Set_Finalization_Collection (Ptr_Typ, Fin_Coll_Id);
1627 -- Generate:
1628 -- <Ptr_Typ>FC : aliased Finalization_Collection;
1630 Append_To (Actions,
1631 Make_Object_Declaration (Loc,
1632 Defining_Identifier => Fin_Coll_Id,
1633 Aliased_Present => True,
1634 Object_Definition =>
1635 New_Occurrence_Of (RTE (RE_Finalization_Collection), Loc)));
1637 if Debug_Generated_Code then
1638 Set_Debug_Info_Needed (Fin_Coll_Id);
1639 end if;
1641 -- Set the associated pool and primitive Finalize_Address of the new
1642 -- finalization collection.
1644 -- The access type has a user-defined storage pool, use it
1646 if Present (Associated_Storage_Pool (Ptr_Typ)) then
1647 Pool_Id := Associated_Storage_Pool (Ptr_Typ);
1649 -- Otherwise the default choice is the global storage pool
1651 else
1652 Pool_Id := RTE (RE_Global_Pool_Object);
1653 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
1654 end if;
1656 -- A finalization collection created for an access designating a type
1657 -- with private components is inserted before a context-dependent
1658 -- node.
1660 if For_Private then
1662 -- At this point both the scope of the context and the insertion
1663 -- mode must be known.
1665 pragma Assert (Present (Context_Scope));
1666 pragma Assert (Present (Insertion_Node));
1668 Push_Scope (Context_Scope);
1670 -- Treat use clauses as declarations and insert directly in front
1671 -- of them.
1673 if Nkind (Insertion_Node) in
1674 N_Use_Package_Clause | N_Use_Type_Clause
1675 then
1676 Insert_List_Before_And_Analyze (Insertion_Node, Actions);
1677 else
1678 Insert_Actions (Insertion_Node, Actions);
1679 end if;
1681 Pop_Scope;
1683 -- The finalization collection belongs to an access type related
1684 -- to a build-in-place function call used to initialize a library
1685 -- level object. The collection must be inserted in front of the
1686 -- access type declaration denoted by Insertion_Node.
1688 elsif For_Lib_Level then
1689 pragma Assert (Present (Insertion_Node));
1690 Insert_Actions (Insertion_Node, Actions);
1692 -- Otherwise the finalization collection and its initialization
1693 -- become a part of the freeze node.
1695 else
1696 Append_Freeze_Actions (Ptr_Typ, Actions);
1697 end if;
1699 Analyze_List (Actions);
1701 -- When the type the finalization collection is being generated for
1702 -- was created to store a 'Old object, then mark it as such so its
1703 -- finalization can be delayed until after postconditions have been
1704 -- checked.
1706 if Stores_Attribute_Old_Prefix (Ptr_Typ) then
1707 Set_Stores_Attribute_Old_Prefix (Fin_Coll_Id);
1708 end if;
1709 end;
1710 end Build_Finalization_Collection;
1712 ---------------------
1713 -- Build_Finalizer --
1714 ---------------------
1716 procedure Build_Finalizer
1717 (N : Node_Id;
1718 Clean_Stmts : List_Id;
1719 Mark_Id : Entity_Id;
1720 Top_Decls : List_Id;
1721 Defer_Abort : Boolean;
1722 Fin_Id : out Entity_Id)
1724 Acts_As_Clean : constant Boolean :=
1725 Present (Mark_Id)
1726 or else
1727 (Present (Clean_Stmts)
1728 and then Is_Non_Empty_List (Clean_Stmts));
1730 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1731 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1732 For_Package : constant Boolean :=
1733 For_Package_Body or else For_Package_Spec;
1734 Loc : constant Source_Ptr := Sloc (N);
1736 -- NOTE: Local variable declarations are conservative and do not create
1737 -- structures right from the start. Entities and lists are created once
1738 -- it has been established that N has at least one controlled object.
1740 Counter_Val : Nat := 0;
1741 -- Holds the number of controlled objects encountered so far
1743 Decls : List_Id := No_List;
1744 -- Declarative region of N (if available). If N is a package declaration
1745 -- Decls denotes the visible declarations.
1747 Finalizer_Data : Finalization_Exception_Data;
1748 -- Data for the exception
1750 Finalizer_Decls : List_Id := No_List;
1751 -- Local variable declarations
1753 Finalization_Master : Entity_Id;
1754 -- The Finalization Master object
1756 Finalizer_Stmts : List_Id := No_List;
1757 -- The statement list of the finalizer body
1759 Has_Ctrl_Objs : Boolean := False;
1760 -- A general flag which denotes whether N has at least one controlled
1761 -- object.
1763 Has_Tagged_Types : Boolean := False;
1764 -- A general flag which indicates whether N has at least one library-
1765 -- level tagged type declaration.
1767 HSS : Node_Id := Empty;
1768 -- The sequence of statements of N (if available)
1770 Prev_At_End : Entity_Id := Empty;
1771 -- The previous at end procedure of the handled statements block of N
1773 Priv_Decls : List_Id := No_List;
1774 -- The private declarations of N if N is a package declaration
1776 Spec_Id : Entity_Id := Empty;
1777 Spec_Decls : List_Id := Top_Decls;
1778 Stmts : List_Id := No_List;
1780 Tagged_Type_Stmts : List_Id := No_List;
1781 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1782 -- tagged types found in N.
1784 -----------------------
1785 -- Local subprograms --
1786 -----------------------
1788 procedure Build_Components;
1789 -- Create all entites and initialize all lists used in the creation of
1790 -- the finalizer.
1792 procedure Create_Finalizer;
1793 -- Create the spec and body of the finalizer and insert them in the
1794 -- proper place in the tree depending on the context.
1796 function New_Finalizer_Name
1797 (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id;
1798 -- Create a fully qualified name of a package spec or body finalizer.
1799 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1801 procedure Process_Declarations
1802 (Decls : List_Id;
1803 Preprocess : Boolean := False);
1804 -- Inspect a list of declarations or statements which may contain
1805 -- objects that need finalization. When flag Preprocess is set, the
1806 -- routine will simply count the total number of controlled objects in
1807 -- Decls and set Counter_Val accordingly.
1809 procedure Process_Object_Declaration
1810 (Decl : Node_Id;
1811 Is_Protected : Boolean := False);
1812 -- Generate all the machinery associated with the finalization of a
1813 -- single object. Flag Is_Protected is set when Decl denotes a simple
1814 -- protected object.
1816 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1817 -- Generate all the code necessary to unregister the external tag of a
1818 -- tagged type.
1820 ----------------------
1821 -- Build_Components --
1822 ----------------------
1824 procedure Build_Components is
1825 Constraints : List_Id;
1826 Master_Decl : Node_Id;
1827 Master_Name : Name_Id;
1829 begin
1830 pragma Assert (Present (Decls));
1832 -- If the context contains controlled objects, then we create the
1833 -- finalization master, unless there is a single such object: in
1834 -- this common case, we'll directly finalize the object.
1836 if Has_Ctrl_Objs then
1837 if Counter_Val > 1 then
1838 if For_Package_Spec then
1839 Master_Name :=
1840 New_External_Name (Name_uMaster, Suffix => "_spec");
1841 elsif For_Package_Body then
1842 Master_Name :=
1843 New_External_Name (Name_uMaster, Suffix => "_body");
1844 else
1845 Master_Name := New_Internal_Name ('M');
1846 end if;
1848 Finalization_Master :=
1849 Make_Defining_Identifier (Loc, Master_Name);
1851 -- The master is statically parameterized by the context
1853 Constraints := New_List;
1854 Append_To (Constraints,
1855 New_Occurrence_Of (Boolean_Literals (Exceptions_OK), Loc));
1856 Append_To (Constraints,
1857 New_Occurrence_Of
1858 (Boolean_Literals (Exception_Extra_Info), Loc));
1859 Append_To (Constraints,
1860 New_Occurrence_Of (Boolean_Literals (For_Package), Loc));
1862 Master_Decl :=
1863 Make_Object_Declaration (Loc,
1864 Defining_Identifier => Finalization_Master,
1865 Object_Definition =>
1866 Make_Subtype_Indication (Loc,
1867 Subtype_Mark =>
1868 New_Occurrence_Of
1869 (RTE (RE_Finalization_Master), Loc),
1870 Constraint =>
1871 Make_Index_Or_Discriminant_Constraint (Loc,
1872 Constraints => Constraints)));
1874 Prepend_To (Decls, Master_Decl);
1875 Analyze (Master_Decl, Suppress => All_Checks);
1876 end if;
1878 if Exceptions_OK then
1879 Finalizer_Decls := New_List;
1881 Build_Object_Declarations
1882 (Finalizer_Data, Finalizer_Decls, Loc, For_Package);
1884 else
1885 Finalizer_Decls := No_List;
1886 end if;
1887 end if;
1889 -- If the context requires additional cleanup, the finalization
1890 -- machinery is added after the cleanup code.
1892 if Acts_As_Clean then
1893 Finalizer_Stmts := Clean_Stmts;
1894 else
1895 Finalizer_Stmts := New_List;
1896 end if;
1898 if Has_Tagged_Types then
1899 Tagged_Type_Stmts := New_List;
1900 end if;
1901 end Build_Components;
1903 ----------------------
1904 -- Create_Finalizer --
1905 ----------------------
1907 procedure Create_Finalizer is
1908 Body_Id : Entity_Id;
1909 Fin_Body : Node_Id;
1910 Fin_Call : Node_Id;
1911 Fin_Spec : Node_Id;
1913 begin
1914 -- Step 1: Creation of the finalizer name
1916 -- Packages must use a distinct name for their finalizers since the
1917 -- binder will have to generate calls to them by name. The name is
1918 -- of the following form:
1920 -- xx__yy__finalize_[spec|body]
1922 if For_Package then
1923 Fin_Id := Make_Defining_Identifier
1924 (Loc, New_Finalizer_Name (Spec_Id, For_Package_Spec));
1925 Set_Has_Qualified_Name (Fin_Id);
1926 Set_Has_Fully_Qualified_Name (Fin_Id);
1928 -- The default name is _finalizer
1930 else
1931 -- Generation of a finalization procedure exclusively for 'Old
1932 -- interally generated constants requires different name since
1933 -- there will need to be multiple finalization routines in the
1934 -- same scope. See Build_Finalizer for details.
1936 Fin_Id :=
1937 Make_Defining_Identifier (Loc,
1938 Chars => New_External_Name (Name_uFinalizer));
1940 -- Inlining the finalizer produces a substantial speedup at -O2.
1941 -- It is inlined by default at -O3. Either way, it is called
1942 -- exactly twice (once on the normal path, and once for
1943 -- exceptions/abort), so this won't bloat the code too much.
1945 Set_Is_Inlined (Fin_Id);
1946 end if;
1948 if Debug_Generated_Code then
1949 Set_Debug_Info_Needed (Fin_Id);
1950 end if;
1952 -- Step 2: Creation of the finalizer specification
1954 -- Generate:
1955 -- procedure Fin_Id;
1957 Fin_Spec :=
1958 Make_Subprogram_Declaration (Loc,
1959 Specification =>
1960 Make_Procedure_Specification (Loc,
1961 Defining_Unit_Name => Fin_Id));
1963 if For_Package then
1964 Set_Is_Exported (Fin_Id);
1965 Set_Interface_Name (Fin_Id,
1966 Make_String_Literal (Loc,
1967 Strval => Get_Name_String (Chars (Fin_Id))));
1968 end if;
1970 -- Step 3: Creation of the finalizer body
1972 -- Add the library-level tagged type unregistration machinery before
1973 -- the finalization circuitry. This ensures that external tags will
1974 -- be removed even if a finalization exception occurs at some point.
1976 if Has_Tagged_Types then
1977 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1978 end if;
1980 -- Add a call to the previous At_End handler if it exists. The call
1981 -- must always precede the finalization circuitry.
1983 if Present (Prev_At_End) then
1984 Prepend_To (Finalizer_Stmts,
1985 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1987 -- Clear the At_End handler since we have already generated the
1988 -- proper replacement call for it.
1990 Set_At_End_Proc (HSS, Empty);
1991 end if;
1993 -- If there are no controlled objects to be finalized, generate;
1995 -- procedure Fin_Id is
1996 -- begin
1997 -- Abort_Defer; -- Added if abort is allowed
1998 -- <call to Prev_At_End> -- Added if exists
1999 -- <tag unregistration> -- Added if Has_Tagged_Types
2000 -- <cleanup statements> -- Added if Acts_As_Clean
2001 -- <stack release> -- Added if Mark_Id exists
2002 -- Abort_Undefer; -- Added if abort is allowed
2003 -- end Fin_Id;
2005 -- If there are controlled objects to be finalized, generate:
2007 -- procedure Fin_Id is
2008 -- Abort : constant Boolean := Triggered_By_Abort;
2009 -- E : Exception_Occurrence;
2010 -- Raised : Boolean := False;
2011 -- begin
2012 -- Abort_Defer; -- Added if abort is allowed
2013 -- <call to Prev_At_End> -- Added if exists
2014 -- <tag unregistration> -- Added if Has_Tagged_Types
2015 -- <cleanup statements> -- Added if Acts_As_Clean
2016 -- <finalization statements>
2017 -- <stack release> -- Added if Mark_Id exists
2018 -- Abort_Undefer; -- Added if abort is allowed
2019 -- end Fin_Id;
2021 if Has_Ctrl_Objs and then Counter_Val > 1 then
2022 Fin_Call :=
2023 Make_Procedure_Call_Statement (Loc,
2024 Name =>
2025 New_Occurrence_Of (RTE (RE_Finalize_Master), Loc),
2026 Parameter_Associations =>
2027 New_List (New_Occurrence_Of (Finalization_Master, Loc)));
2029 -- For CodePeer, the exception handlers normally generated here
2030 -- generate complex flowgraphs which result in capacity problems.
2031 -- Omitting these handlers for CodePeer is justified as follows:
2033 -- If a handler is dead, then omitting it is surely ok
2035 -- If a handler is live, then CodePeer should flag the
2036 -- potentially-exception-raising construct that causes it
2037 -- to be live. That is what we are interested in, not what
2038 -- happens after the exception is raised.
2040 if Exceptions_OK and not CodePeer_Mode then
2041 Fin_Call :=
2042 Make_Block_Statement (Loc,
2043 Handled_Statement_Sequence =>
2044 Make_Handled_Sequence_Of_Statements (Loc,
2045 Statements => New_List (Fin_Call),
2047 Exception_Handlers => New_List (
2048 Build_Exception_Handler
2049 (Finalizer_Data, For_Package))));
2050 end if;
2052 Append_To (Finalizer_Stmts, Fin_Call);
2053 end if;
2055 -- Release the secondary stack
2057 if Present (Mark_Id) then
2058 declare
2059 Release : Node_Id := Build_SS_Release_Call (Loc, Mark_Id);
2061 begin
2062 -- If the context is a build-in-place function, the secondary
2063 -- stack must be released, unless the build-in-place function
2064 -- itself is returning on the secondary stack. Generate:
2066 -- if BIP_Alloc_Form /= Secondary_Stack then
2067 -- SS_Release (Mark_Id);
2068 -- end if;
2070 -- Note that if the function returns on the secondary stack,
2071 -- then the responsibility of reclaiming the space is always
2072 -- left to the caller (recursively if needed).
2074 if Nkind (N) = N_Subprogram_Body then
2075 declare
2076 Spec_Id : constant Entity_Id :=
2077 Unique_Defining_Entity (N);
2078 BIP_SS : constant Boolean :=
2079 Is_Build_In_Place_Function (Spec_Id)
2080 and then Needs_BIP_Alloc_Form (Spec_Id);
2081 begin
2082 if BIP_SS then
2083 Release :=
2084 Make_If_Statement (Loc,
2085 Condition =>
2086 Make_Op_Ne (Loc,
2087 Left_Opnd =>
2088 New_Occurrence_Of
2089 (Build_In_Place_Formal
2090 (Spec_Id, BIP_Alloc_Form), Loc),
2091 Right_Opnd =>
2092 Make_Integer_Literal (Loc,
2093 UI_From_Int
2094 (BIP_Allocation_Form'Pos
2095 (Secondary_Stack)))),
2097 Then_Statements => New_List (Release));
2098 end if;
2099 end;
2100 end if;
2102 Append_To (Finalizer_Stmts, Release);
2103 end;
2104 end if;
2106 -- Protect the statements with abort defer/undefer. This is only when
2107 -- aborts are allowed and the cleanup statements require deferral or
2108 -- there are controlled objects to be finalized. Note that the abort
2109 -- defer/undefer pair does not require an extra block because the
2110 -- finalization exception is caught in its corresponding finalization
2111 -- block. As a result, the call to Abort_Defer always takes place.
2113 if Abort_Allowed and then (Defer_Abort or Has_Ctrl_Objs) then
2114 Prepend_To (Finalizer_Stmts,
2115 Build_Runtime_Call (Loc, RE_Abort_Defer));
2117 Append_To (Finalizer_Stmts,
2118 Build_Runtime_Call (Loc, RE_Abort_Undefer));
2119 end if;
2121 -- The local exception does not need to be reraised for library-level
2122 -- finalizers. Note that this action must be carried out after object
2123 -- cleanup, secondary stack release, and abort undeferral. Generate:
2125 -- if Raised and then not Abort then
2126 -- Raise_From_Controlled_Operation (E);
2127 -- end if;
2129 if Has_Ctrl_Objs and Exceptions_OK and not For_Package then
2130 Append_To (Finalizer_Stmts,
2131 Build_Raise_Statement (Finalizer_Data));
2132 end if;
2134 -- Create the body of the finalizer
2136 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
2138 if Debug_Generated_Code then
2139 Set_Debug_Info_Needed (Body_Id);
2140 end if;
2142 if For_Package then
2143 Set_Has_Qualified_Name (Body_Id);
2144 Set_Has_Fully_Qualified_Name (Body_Id);
2145 end if;
2147 Fin_Body :=
2148 Make_Subprogram_Body (Loc,
2149 Specification =>
2150 Make_Procedure_Specification (Loc,
2151 Defining_Unit_Name => Body_Id),
2152 Declarations => Finalizer_Decls,
2153 Handled_Statement_Sequence =>
2154 Make_Handled_Sequence_Of_Statements (Loc,
2155 Statements => Finalizer_Stmts));
2157 -- Step 4: Spec and body insertion, analysis
2159 if For_Package then
2161 -- If a package spec has private declarations, both the finalizer
2162 -- spec and body are inserted at the end of this list.
2164 if For_Package_Spec and then Present (Priv_Decls) then
2165 Append_To (Priv_Decls, Fin_Spec);
2166 Append_To (Priv_Decls, Fin_Body);
2168 -- Otherwise, and for a package body, both the finalizer spec and
2169 -- body are inserted at the end of the package declarations.
2171 else
2172 Append_To (Decls, Fin_Spec);
2173 Append_To (Decls, Fin_Body);
2174 end if;
2176 -- Non-package case
2178 else
2179 pragma Assert (Present (Spec_Decls));
2181 Append_To (Spec_Decls, Fin_Spec);
2182 Append_To (Spec_Decls, Fin_Body);
2183 end if;
2185 Analyze (Fin_Spec, Suppress => All_Checks);
2186 Analyze (Fin_Body, Suppress => All_Checks);
2188 -- Never consider that the finalizer procedure is enabled Ghost, even
2189 -- when the corresponding unit is Ghost, as this would lead to an
2190 -- an external name with a ___ghost_ prefix that the binder cannot
2191 -- generate, as it has no knowledge of the Ghost status of units.
2193 Set_Is_Checked_Ghost_Entity (Fin_Id, False);
2194 end Create_Finalizer;
2196 ------------------------
2197 -- New_Finalizer_Name --
2198 ------------------------
2200 function New_Finalizer_Name
2201 (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id
2203 procedure New_Finalizer_Name (Id : Entity_Id);
2204 -- Place "__<name-of-Id>" in the name buffer. If the identifier
2205 -- has a non-standard scope, process the scope first.
2207 ------------------------
2208 -- New_Finalizer_Name --
2209 ------------------------
2211 procedure New_Finalizer_Name (Id : Entity_Id) is
2212 begin
2213 if Scope (Id) = Standard_Standard then
2214 Get_Name_String (Chars (Id));
2216 else
2217 New_Finalizer_Name (Scope (Id));
2218 Add_Str_To_Name_Buffer ("__");
2219 Get_Name_String_And_Append (Chars (Id));
2220 end if;
2221 end New_Finalizer_Name;
2223 -- Start of processing for New_Finalizer_Name
2225 begin
2226 -- Create the fully qualified name of the enclosing scope
2228 New_Finalizer_Name (Spec_Id);
2230 -- Generate:
2231 -- __finalize_[spec|body]
2233 Add_Str_To_Name_Buffer ("__finalize_");
2235 if For_Spec then
2236 Add_Str_To_Name_Buffer ("spec");
2237 else
2238 Add_Str_To_Name_Buffer ("body");
2239 end if;
2241 return Name_Find;
2242 end New_Finalizer_Name;
2244 --------------------------
2245 -- Process_Declarations --
2246 --------------------------
2248 procedure Process_Declarations
2249 (Decls : List_Id;
2250 Preprocess : Boolean := False)
2252 procedure Process_Package_Body (Decl : Node_Id);
2253 -- Process an N_Package_Body node
2255 procedure Processing_Actions
2256 (Decl : Node_Id;
2257 Is_Protected : Boolean := False);
2258 -- Depending on the mode of operation of Process_Declarations, either
2259 -- increment the controlled object counter, set the controlled object
2260 -- flag and store the last top level construct or process the current
2261 -- declaration. Flag Is_Protected is set when the current declaration
2262 -- denotes a simple protected object.
2264 --------------------------
2265 -- Process_Package_Body --
2266 --------------------------
2268 procedure Process_Package_Body (Decl : Node_Id) is
2269 begin
2270 -- Do not inspect an ignored Ghost package body because all
2271 -- code found within will not appear in the final tree.
2273 if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then
2274 null;
2276 elsif Ekind (Corresponding_Spec (Decl)) /= E_Generic_Package then
2277 Process_Declarations (Declarations (Decl), Preprocess);
2278 end if;
2279 end Process_Package_Body;
2281 ------------------------
2282 -- Processing_Actions --
2283 ------------------------
2285 procedure Processing_Actions
2286 (Decl : Node_Id;
2287 Is_Protected : Boolean := False)
2289 begin
2290 -- Library-level tagged type
2292 if Nkind (Decl) = N_Full_Type_Declaration then
2293 if Preprocess then
2294 Has_Tagged_Types := True;
2296 -- Unregister tagged type, unless No_Tagged_Type_Registration
2297 -- is active.
2299 elsif not Restriction_Active (No_Tagged_Type_Registration) then
2300 Process_Tagged_Type_Declaration (Decl);
2301 end if;
2303 -- Controlled object declaration
2305 else
2306 if Preprocess then
2307 Counter_Val := Counter_Val + 1;
2308 Has_Ctrl_Objs := True;
2310 else
2311 Process_Object_Declaration (Decl, Is_Protected);
2312 end if;
2313 end if;
2314 end Processing_Actions;
2316 -- Local variables
2318 Decl : Node_Id;
2319 Expr : Node_Id;
2320 Obj_Id : Entity_Id;
2321 Obj_Typ : Entity_Id;
2322 Pack_Id : Entity_Id;
2323 Spec : Node_Id;
2324 Typ : Entity_Id;
2326 -- Start of processing for Process_Declarations
2328 begin
2329 if Is_Empty_List (Decls) then
2330 return;
2331 end if;
2333 -- Process all declarations in reverse order
2335 Decl := Last_Non_Pragma (Decls);
2336 while Present (Decl) loop
2337 -- Library-level tagged types
2339 if Nkind (Decl) = N_Full_Type_Declaration then
2340 Typ := Defining_Identifier (Decl);
2342 -- Ignored Ghost types do not need any cleanup actions because
2343 -- they will not appear in the final tree.
2345 if Is_Ignored_Ghost_Entity (Typ) then
2346 null;
2348 elsif Is_Tagged_Type (Typ)
2349 and then Is_Library_Level_Entity (Typ)
2350 and then Convention (Typ) = Convention_Ada
2351 and then Present (Access_Disp_Table (Typ))
2352 and then not Is_Abstract_Type (Typ)
2353 and then not No_Run_Time_Mode
2354 and then not Restriction_Active (No_Tagged_Type_Registration)
2355 and then RTE_Available (RE_Register_Tag)
2356 then
2357 Processing_Actions (Decl);
2358 end if;
2360 -- Regular object declarations
2362 elsif Nkind (Decl) = N_Object_Declaration then
2363 Obj_Id := Defining_Identifier (Decl);
2364 Obj_Typ := Base_Type (Etype (Obj_Id));
2365 Expr := Expression (Decl);
2367 -- Bypass any form of processing for objects which have their
2368 -- finalization disabled. This applies only to objects at the
2369 -- library level.
2371 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
2372 null;
2374 -- Finalization of transient objects is treated separately in
2375 -- order to handle sensitive cases. These include:
2377 -- * Conditional expressions
2378 -- * Expressions with actions
2379 -- * Transient scopes
2381 elsif Is_Finalized_Transient (Obj_Id) then
2382 null;
2384 -- Finalization of specific objects is also treated separately
2386 elsif Is_Ignored_For_Finalization (Obj_Id) then
2387 null;
2389 -- Conversely, if one of the above cases created a Master_Node,
2390 -- finalization actions are required for the associated object.
2392 elsif Ekind (Obj_Id) = E_Variable
2393 and then Is_RTE (Obj_Typ, RE_Master_Node)
2394 then
2395 Processing_Actions (Decl);
2397 -- Ignored Ghost objects do not need any cleanup actions
2398 -- because they will not appear in the final tree.
2400 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2401 null;
2403 -- The object is of the form:
2404 -- Obj : [constant] Typ [:= Expr];
2406 -- Do not process the incomplete view of a deferred constant.
2407 -- Note that an object initialized by means of a BIP function
2408 -- call may appear as a deferred constant after expansion
2409 -- activities. These kinds of objects must be finalized.
2411 elsif not Is_Imported (Obj_Id)
2412 and then Needs_Finalization (Obj_Typ)
2413 and then not (Ekind (Obj_Id) = E_Constant
2414 and then not Has_Completion (Obj_Id)
2415 and then No (BIP_Initialization_Call (Obj_Id)))
2416 then
2417 Processing_Actions (Decl);
2419 -- The object is of the form:
2420 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
2422 -- Obj : Access_Typ :=
2423 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
2425 elsif Is_Access_Type (Obj_Typ)
2426 and then Needs_Finalization
2427 (Available_View (Designated_Type (Obj_Typ)))
2428 and then Present (Expr)
2429 and then
2430 (Is_Secondary_Stack_BIP_Func_Call (Expr)
2431 or else
2432 (Is_Non_BIP_Func_Call (Expr)
2433 and then not Is_Related_To_Func_Return (Obj_Id)))
2434 then
2435 Processing_Actions (Decl);
2437 -- Simple protected objects which use the type System.Tasking.
2438 -- Protected_Objects.Protection to manage their locks should
2439 -- be treated as controlled since they require manual cleanup.
2440 -- but not for restricted run-time libraries (Ravenscar), see
2441 -- also Cleanup_Protected_Object.
2443 -- The only exception is illustrated in the following example:
2445 -- package Pkg is
2446 -- type Ctrl is new Controlled ...
2447 -- procedure Finalize (Obj : in out Ctrl);
2448 -- Lib_Obj : Ctrl;
2449 -- end Pkg;
2451 -- package body Pkg is
2452 -- protected Prot is
2453 -- procedure Do_Something (Obj : in out Ctrl);
2454 -- end Prot;
2456 -- protected body Prot is
2457 -- procedure Do_Something (Obj : in out Ctrl) is ...
2458 -- end Prot;
2460 -- procedure Finalize (Obj : in out Ctrl) is
2461 -- begin
2462 -- Prot.Do_Something (Obj);
2463 -- end Finalize;
2464 -- end Pkg;
2466 -- Since for the most part entities in package bodies depend on
2467 -- those in package specs, Prot's lock should be cleaned up
2468 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
2469 -- This act however attempts to invoke Do_Something and fails
2470 -- because the lock has disappeared.
2472 elsif Ekind (Obj_Id) = E_Variable
2473 and then not In_Library_Level_Package_Body (Obj_Id)
2474 and then Has_Simple_Protected_Object (Obj_Typ)
2475 and then not Restricted_Profile
2476 then
2477 Processing_Actions (Decl, Is_Protected => True);
2478 end if;
2480 -- Specific cases of object renamings
2482 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
2483 Obj_Id := Defining_Identifier (Decl);
2484 Obj_Typ := Base_Type (Etype (Obj_Id));
2486 -- Bypass any form of processing for objects which have their
2487 -- finalization disabled. This applies only to objects at the
2488 -- library level.
2490 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
2491 null;
2493 -- Ignored Ghost object renamings do not need any cleanup
2494 -- actions because they will not appear in the final tree.
2496 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2497 null;
2498 end if;
2500 -- Inspect the freeze node of an access-to-controlled type and
2501 -- look for a delayed finalization collection. This case arises
2502 -- when the freeze actions are inserted at a later time than the
2503 -- expansion of the context. Since Build_Finalizer is never called
2504 -- on a single construct twice, the collection would be ultimately
2505 -- left out and never finalized. This is also needed for freeze
2506 -- actions of designated types themselves, since in some cases the
2507 -- finalization collection is associated with a designated type's
2508 -- freeze node rather than that of the access type (see handling
2509 -- for freeze actions in Build_Finalization_Collection).
2511 elsif Nkind (Decl) = N_Freeze_Entity
2512 and then Present (Actions (Decl))
2513 then
2514 Typ := Entity (Decl);
2516 -- Freeze nodes for ignored Ghost types do not need cleanup
2517 -- actions because they will never appear in the final tree.
2519 if Is_Ignored_Ghost_Entity (Typ) then
2520 null;
2522 elsif (Is_Access_Object_Type (Typ)
2523 and then Needs_Finalization
2524 (Available_View (Designated_Type (Typ))))
2525 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
2526 then
2527 -- Freeze nodes are considered to be identical to packages
2528 -- and blocks in terms of nesting. The difference is that
2529 -- a finalization collection created inside the freeze node
2530 -- is at the same nesting level as the node itself.
2532 Process_Declarations (Actions (Decl), Preprocess);
2533 end if;
2535 -- Nested package declarations, avoid generics
2537 elsif Nkind (Decl) = N_Package_Declaration then
2538 Pack_Id := Defining_Entity (Decl);
2539 Spec := Specification (Decl);
2541 -- Do not inspect an ignored Ghost package because all code
2542 -- found within will not appear in the final tree.
2544 if Is_Ignored_Ghost_Entity (Pack_Id) then
2545 null;
2547 elsif Ekind (Pack_Id) /= E_Generic_Package then
2548 Process_Declarations
2549 (Private_Declarations (Spec), Preprocess);
2550 Process_Declarations
2551 (Visible_Declarations (Spec), Preprocess);
2552 end if;
2554 -- Nested package bodies, avoid generics
2556 elsif Nkind (Decl) = N_Package_Body then
2557 Process_Package_Body (Decl);
2559 elsif Nkind (Decl) = N_Package_Body_Stub
2560 and then Present (Library_Unit (Decl))
2561 then
2562 Process_Package_Body (Proper_Body (Unit (Library_Unit (Decl))));
2563 end if;
2565 Prev_Non_Pragma (Decl);
2566 end loop;
2567 end Process_Declarations;
2569 --------------------------------
2570 -- Process_Object_Declaration --
2571 --------------------------------
2573 procedure Process_Object_Declaration
2574 (Decl : Node_Id;
2575 Is_Protected : Boolean := False)
2577 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2578 Loc : constant Source_Ptr := Sloc (Decl);
2580 Fin_Call : Node_Id;
2581 Fin_Id : Entity_Id;
2582 Master_Node_Attach : Node_Id;
2583 Master_Node_Decl : Node_Id;
2584 Master_Node_Id : Entity_Id;
2585 Master_Node_Ins : Node_Id;
2586 Master_Node_Loc : Source_Ptr;
2587 Obj_Ref : Node_Id;
2588 Obj_Typ : Entity_Id;
2590 -- Start of processing for Process_Object_Declaration
2592 begin
2593 -- Handle the object type and the reference to the object. Note
2594 -- that objects having simple protected components or of a CW type
2595 -- must retain their original type for the processing below to work.
2597 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
2598 Obj_Typ := Etype (Obj_Id);
2599 if not Is_Protected and then not Is_Class_Wide_Type (Obj_Typ) then
2600 Obj_Typ := Base_Type (Obj_Typ);
2601 end if;
2603 if Is_Access_Type (Obj_Typ) then
2604 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2605 Obj_Typ := Available_View (Designated_Type (Obj_Typ));
2606 end if;
2608 -- If the object is a Master_Node, then nothing to do, except if it
2609 -- is the only object, in which case we move its declaration, call
2610 -- marker (if any) and initialization call, as well as mark it to
2611 -- avoid double processing.
2613 if Is_RTE (Obj_Typ, RE_Master_Node) then
2614 Master_Node_Id := Obj_Id;
2616 if Counter_Val = 1 then
2617 if Nkind (Next (Decl)) = N_Call_Marker then
2618 Prepend_To (Decls, Remove_Next (Next (Decl)));
2619 end if;
2620 Prepend_To (Decls, Remove_Next (Decl));
2621 Remove (Decl);
2622 Prepend_To (Decls, Decl);
2623 Set_Is_Ignored_For_Finalization (Obj_Id);
2624 end if;
2626 -- Create the declaration of the Master_Node for the object and
2627 -- insert it before the declaration of the object itself, except
2628 -- for the case where it is the only object because it will play
2629 -- the role of a degenerated master and therefore needs to be
2630 -- inserted at the same place the master would have been.
2632 else pragma Assert (No (Finalization_Master_Node (Obj_Id)));
2633 -- For one object, use the Sloc the master would have had
2635 if Counter_Val = 1 then
2636 Master_Node_Loc := Sloc (N);
2637 else
2638 Master_Node_Loc := Loc;
2639 end if;
2641 Master_Node_Id :=
2642 Make_Defining_Identifier (Master_Node_Loc,
2643 Chars => New_External_Name (Chars (Obj_Id), Suffix => "MN"));
2644 Master_Node_Decl :=
2645 Make_Master_Node_Declaration (Master_Node_Loc,
2646 Master_Node_Id, Obj_Id);
2648 Push_Scope (Scope (Obj_Id));
2649 if Counter_Val = 1 then
2650 Prepend_To (Decls, Master_Node_Decl);
2651 else
2652 Insert_Before (Decl, Master_Node_Decl);
2653 end if;
2654 Analyze (Master_Node_Decl);
2655 Pop_Scope;
2657 -- Mark the Master_Node to avoid double processing
2659 Set_Is_Ignored_For_Finalization (Master_Node_Id);
2660 end if;
2662 -- Attach the Master_Node after all initialization has been done. The
2663 -- place of insertion depends on the context.
2665 if Ekind (Obj_Id) in E_Constant | E_Variable then
2667 -- The object is initialized by a build-in-place function call.
2668 -- The Master_Node insertion point is after the function call.
2670 if Present (BIP_Initialization_Call (Obj_Id)) then
2671 Master_Node_Ins := BIP_Initialization_Call (Obj_Id);
2673 -- The object is initialized by an aggregate. The Master_Node
2674 -- insertion point is after the last aggregate assignment.
2676 elsif Present (Last_Aggregate_Assignment (Obj_Id)) then
2677 Master_Node_Ins := Last_Aggregate_Assignment (Obj_Id);
2679 -- In other cases the Master_Node is inserted after the last call
2680 -- to either [Deep_]Initialize or the type-specific init proc.
2682 else
2683 Master_Node_Ins := Find_Last_Init (Decl);
2684 end if;
2686 -- In all other cases the Master_Node is inserted after the last call
2687 -- to either [Deep_]Initialize or the type-specific init proc.
2689 else
2690 Master_Node_Ins := Find_Last_Init (Decl);
2691 end if;
2693 -- If the Initialize function is null or trivial, the call will have
2694 -- been replaced with a null statement and we place the attachment
2695 -- of the Master_Node after the declaration of the object itself.
2697 if No (Master_Node_Ins) then
2698 Master_Node_Ins := Decl;
2699 end if;
2701 -- Processing for simple protected objects. Such objects require
2702 -- manual finalization of their lock managers. Generate:
2704 -- procedure obj_type_nnFD (v :system__address) is
2705 -- type Ptr_Typ is access all Obj_Typ;
2706 -- Rnn : Obj_Typ renames Ptr_Typ!(v).all;
2707 -- begin
2708 -- $system__tasking__protected_objects__finalize_protection
2709 -- (Obj_TypV!(Rnn)._object);
2710 -- exception
2711 -- when others =>
2712 -- null;
2713 -- end obj_type_nnFD;
2715 if Is_Protected
2716 or else (Has_Simple_Protected_Object (Obj_Typ)
2717 and then No (Finalize_Address (Obj_Typ)))
2718 then
2719 declare
2720 Param : constant Entity_Id :=
2721 Make_Defining_Identifier (Loc, Name_V);
2722 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
2723 Ren_Id : constant Entity_Id := Make_Temporary (Loc, 'R');
2724 Ren_Ref : constant Node_Id := New_Occurrence_Of (Ren_Id, Loc);
2726 Fin_Body : Node_Id;
2727 Fin_Call : Node_Id;
2728 Fin_Stmts : List_Id := No_List;
2729 HSS : Node_Id;
2731 begin
2732 Set_Etype (Ren_Ref, Obj_Typ);
2734 if Is_Simple_Protected_Type (Obj_Typ) then
2735 Fin_Call := Cleanup_Protected_Object (Decl, Ren_Ref);
2737 if Present (Fin_Call) then
2738 Fin_Stmts := New_List (Fin_Call);
2739 end if;
2741 elsif Is_Array_Type (Obj_Typ) then
2742 Fin_Stmts := Cleanup_Array (Decl, Ren_Ref, Obj_Typ);
2744 else
2745 Fin_Stmts := Cleanup_Record (Decl, Ren_Ref, Obj_Typ);
2746 end if;
2748 if No (Fin_Stmts) then
2749 return;
2750 end if;
2752 HSS :=
2753 Make_Handled_Sequence_Of_Statements (Loc,
2754 Statements => Fin_Stmts);
2756 if Exceptions_OK then
2757 Set_Exception_Handlers (HSS, New_List (
2758 Make_Exception_Handler (Loc,
2759 Exception_Choices => New_List (
2760 Make_Others_Choice (Loc)),
2761 Statements => New_List (
2762 Make_Null_Statement (Loc)))));
2763 end if;
2765 Fin_Id :=
2766 Make_Defining_Identifier (Loc,
2767 Make_TSS_Name_Local (Obj_Typ, TSS_Finalize_Address));
2769 Fin_Body :=
2770 Make_Subprogram_Body (Loc,
2771 Specification =>
2772 Make_Procedure_Specification (Loc,
2773 Defining_Unit_Name => Fin_Id,
2775 Parameter_Specifications => New_List (
2776 Make_Parameter_Specification (Loc,
2777 Defining_Identifier => Param,
2778 Parameter_Type =>
2779 New_Occurrence_Of (RTE (RE_Address), Loc)))),
2781 Declarations => New_List (
2782 Make_Full_Type_Declaration (Loc,
2783 Defining_Identifier => Ptr_Typ,
2784 Type_Definition =>
2785 Make_Access_To_Object_Definition (Loc,
2786 All_Present => True,
2787 Subtype_Indication =>
2788 New_Occurrence_Of (Obj_Typ, Loc))),
2790 Make_Object_Renaming_Declaration (Loc,
2791 Defining_Identifier => Ren_Id,
2792 Subtype_Mark =>
2793 New_Occurrence_Of (Obj_Typ, Loc),
2794 Name =>
2795 Make_Explicit_Dereference (Loc,
2796 Prefix =>
2797 Unchecked_Convert_To
2798 (Ptr_Typ, New_Occurrence_Of (Param, Loc))))),
2800 Handled_Statement_Sequence => HSS);
2802 Push_Scope (Scope (Obj_Id));
2803 Insert_After_And_Analyze
2804 (Master_Node_Ins, Fin_Body, Suppress => All_Checks);
2805 Pop_Scope;
2807 Master_Node_Ins := Fin_Body;
2808 end;
2810 else
2811 Fin_Id := Finalize_Address (Obj_Typ);
2813 if No (Fin_Id) and then Ekind (Obj_Typ) = E_Class_Wide_Subtype then
2814 Fin_Id := TSS (Obj_Typ, TSS_Finalize_Address);
2815 end if;
2816 end if;
2818 -- Now build the attachment call that will initialize the object's
2819 -- Master_Node using the object's address and type's finalization
2820 -- procedure and then attach the Master_Node to the master, unless
2821 -- there is a single controlled object.
2823 if Counter_Val = 1 then
2824 -- Finalize_Address is not generated in CodePeer mode because the
2825 -- body contains address arithmetic. So we don't want to generate
2826 -- the attach in this case. Ditto if the object is a Master_Node.
2828 if CodePeer_Mode or else Obj_Id = Master_Node_Id then
2829 Master_Node_Attach := Make_Null_Statement (Loc);
2831 else
2832 Master_Node_Attach :=
2833 Make_Procedure_Call_Statement (Loc,
2834 Name =>
2835 New_Occurrence_Of (RTE (RE_Attach_Object_To_Node), Loc),
2836 Parameter_Associations => New_List (
2837 Make_Address_For_Finalize (Loc, Obj_Ref, Obj_Typ),
2838 Make_Attribute_Reference (Loc,
2839 Prefix => New_Occurrence_Of (Fin_Id, Loc),
2840 Attribute_Name => Name_Unrestricted_Access),
2841 New_Occurrence_Of (Master_Node_Id, Loc)));
2842 end if;
2844 -- We also generate the direct finalization call here
2846 Fin_Call :=
2847 Make_Procedure_Call_Statement (Loc,
2848 Name =>
2849 New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
2850 Parameter_Associations => New_List (
2851 New_Occurrence_Of (Master_Node_Id, Loc)));
2853 -- For CodePeer, the exception handlers normally generated here
2854 -- generate complex flowgraphs which result in capacity problems.
2855 -- Omitting these handlers for CodePeer is justified as follows:
2857 -- If a handler is dead, then omitting it is surely ok
2859 -- If a handler is live, then CodePeer should flag the
2860 -- potentially-exception-raising construct that causes it
2861 -- to be live. That is what we are interested in, not what
2862 -- happens after the exception is raised.
2864 if Exceptions_OK and not CodePeer_Mode then
2865 Fin_Call :=
2866 Make_Block_Statement (Loc,
2867 Handled_Statement_Sequence =>
2868 Make_Handled_Sequence_Of_Statements (Loc,
2869 Statements => New_List (Fin_Call),
2871 Exception_Handlers => New_List (
2872 Build_Exception_Handler
2873 (Finalizer_Data, For_Package))));
2874 end if;
2876 Append_To (Finalizer_Stmts, Fin_Call);
2878 else
2879 -- If the object is a Master_Node, we just need to chain it
2881 if Obj_Id = Master_Node_Id then
2882 Master_Node_Attach :=
2883 Make_Procedure_Call_Statement (Loc,
2884 Name =>
2885 New_Occurrence_Of (RTE (RE_Chain_Node_To_Master), Loc),
2886 Parameter_Associations => New_List (
2887 Make_Attribute_Reference (Loc,
2888 Prefix => New_Occurrence_Of (Obj_Id, Loc),
2889 Attribute_Name => Name_Unrestricted_Access),
2890 New_Occurrence_Of (Finalization_Master, Loc)));
2892 -- Finalize_Address is not generated in CodePeer mode because the
2893 -- body contains address arithmetic. So we don't want to generate
2894 -- the attach in this case.
2896 elsif CodePeer_Mode then
2897 Master_Node_Attach := Make_Null_Statement (Loc);
2899 else
2900 Master_Node_Attach :=
2901 Make_Procedure_Call_Statement (Loc,
2902 Name =>
2903 New_Occurrence_Of (RTE (RE_Attach_Object_To_Master), Loc),
2904 Parameter_Associations => New_List (
2905 Make_Address_For_Finalize (Loc, Obj_Ref, Obj_Typ),
2906 Make_Attribute_Reference (Loc,
2907 Prefix => New_Occurrence_Of (Fin_Id, Loc),
2908 Attribute_Name => Name_Unrestricted_Access),
2909 Make_Attribute_Reference (Loc,
2910 Prefix =>
2911 New_Occurrence_Of (Master_Node_Id, Loc),
2912 Attribute_Name => Name_Unrestricted_Access),
2913 New_Occurrence_Of (Finalization_Master, Loc)));
2914 end if;
2915 end if;
2917 Insert_After_And_Analyze
2918 (Master_Node_Ins, Master_Node_Attach, Suppress => All_Checks);
2919 end Process_Object_Declaration;
2921 -------------------------------------
2922 -- Process_Tagged_Type_Declaration --
2923 -------------------------------------
2925 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2926 Typ : constant Entity_Id := Defining_Identifier (Decl);
2927 DT_Ptr : constant Entity_Id :=
2928 Node (First_Elmt (Access_Disp_Table (Typ)));
2929 begin
2930 -- Generate:
2931 -- Ada.Tags.Unregister_Tag (<Typ>P);
2933 Append_To (Tagged_Type_Stmts,
2934 Make_Procedure_Call_Statement (Loc,
2935 Name =>
2936 New_Occurrence_Of (RTE (RE_Unregister_Tag), Loc),
2937 Parameter_Associations => New_List (
2938 New_Occurrence_Of (DT_Ptr, Loc))));
2939 end Process_Tagged_Type_Declaration;
2941 -- Start of processing for Build_Finalizer
2943 begin
2944 Fin_Id := Empty;
2946 -- Do not perform this expansion in SPARK mode because it is not
2947 -- necessary.
2949 if GNATprove_Mode then
2950 return;
2951 end if;
2953 -- Step 1: Extract all lists which may contain controlled objects or
2954 -- library-level tagged types.
2956 if For_Package_Spec then
2957 Decls := Visible_Declarations (Specification (N));
2958 Priv_Decls := Private_Declarations (Specification (N));
2960 -- Retrieve the package spec id
2962 Spec_Id := Defining_Unit_Name (Specification (N));
2964 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2965 Spec_Id := Defining_Identifier (Spec_Id);
2966 end if;
2968 -- Accept statement, block, entry body, package body, protected body,
2969 -- subprogram body or task body.
2971 else
2972 Decls := Declarations (N);
2973 HSS := Handled_Statement_Sequence (N);
2975 if Present (HSS) then
2976 if Present (Statements (HSS)) then
2977 Stmts := Statements (HSS);
2978 end if;
2980 if Present (At_End_Proc (HSS)) then
2981 Prev_At_End := At_End_Proc (HSS);
2982 end if;
2983 end if;
2985 -- Retrieve the package spec id for package bodies
2987 if For_Package_Body then
2988 Spec_Id := Corresponding_Spec (N);
2989 end if;
2990 end if;
2992 -- We do not need to process nested packages since they are handled by
2993 -- the finalizer of the enclosing scope, including at library level.
2994 -- And we do not build two finalizers for an instance without body that
2995 -- is a library unit (see Analyze_Package_Instantiation).
2997 if For_Package
2998 and then (not Is_Compilation_Unit (Spec_Id)
2999 or else (Is_Generic_Instance (Spec_Id)
3000 and then Package_Instantiation (Spec_Id) = N))
3001 then
3002 return;
3003 end if;
3005 -- Step 2: Object [pre]processing
3007 if For_Package then
3008 -- For package specs and bodies, we are invoked from the Standard
3009 -- scope, so we need to push the specs onto the scope stack first.
3011 Push_Scope (Spec_Id);
3013 -- Preprocess the visible declarations now in order to obtain the
3014 -- correct number of controlled object by the time the private
3015 -- declarations are processed.
3017 Process_Declarations (Decls, Preprocess => True);
3019 -- From all the possible contexts, only package specifications may
3020 -- have private declarations.
3022 if For_Package_Spec then
3023 Process_Declarations (Priv_Decls, Preprocess => True);
3024 end if;
3026 -- The current context may lack controlled objects, but require some
3027 -- other form of completion (task termination for instance). In such
3028 -- cases, the finalizer must be created and carry the additional
3029 -- statements.
3031 if Acts_As_Clean or else Has_Ctrl_Objs or else Has_Tagged_Types then
3032 Build_Components;
3033 end if;
3035 -- The preprocessing has determined that the context has controlled
3036 -- objects or library-level tagged types.
3038 if Has_Ctrl_Objs or else Has_Tagged_Types then
3040 -- Private declarations are processed first in order to preserve
3041 -- possible dependencies between public and private objects.
3043 if For_Package_Spec then
3044 Process_Declarations (Priv_Decls);
3045 end if;
3047 Process_Declarations (Decls);
3048 end if;
3050 -- Non-package case
3052 else
3053 -- Preprocess both declarations and statements
3055 Process_Declarations (Decls, Preprocess => True);
3056 Process_Declarations (Stmts, Preprocess => True);
3058 -- At this point it is known that N has controlled objects. Ensure
3059 -- that N has a declarative list since the finalizer spec will be
3060 -- attached to it.
3062 if Has_Ctrl_Objs and then No (Decls) then
3063 Set_Declarations (N, New_List);
3064 Decls := Declarations (N);
3065 Spec_Decls := Decls;
3066 end if;
3068 -- The current context may lack controlled objects, but require some
3069 -- other form of completion (task termination for instance). In such
3070 -- cases, the finalizer must be created and carry the additional
3071 -- statements.
3073 if Acts_As_Clean or else Has_Ctrl_Objs or else Has_Tagged_Types then
3074 Build_Components;
3075 end if;
3077 if Has_Ctrl_Objs or else Has_Tagged_Types then
3078 Process_Declarations (Stmts);
3079 Process_Declarations (Decls);
3080 end if;
3081 end if;
3083 -- Step 3: Finalizer creation
3085 if Acts_As_Clean or else Has_Ctrl_Objs or else Has_Tagged_Types then
3086 Create_Finalizer;
3087 end if;
3089 -- Pop the scope that was pushed above for package specs and bodies
3091 if For_Package then
3092 Pop_Scope;
3093 end if;
3094 end Build_Finalizer;
3096 --------------------------
3097 -- Build_Finalizer_Call --
3098 --------------------------
3100 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
3101 begin
3102 -- Do not perform this expansion in SPARK mode because we do not create
3103 -- finalizers in the first place.
3105 if GNATprove_Mode then
3106 return;
3107 end if;
3109 -- If the construct to be cleaned up is a protected subprogram body, the
3110 -- finalizer call needs to be associated with the block that wraps the
3111 -- unprotected version of the subprogram. The following illustrates this
3112 -- scenario:
3114 -- procedure Prot_SubpP is
3115 -- procedure finalizer is
3116 -- begin
3117 -- Service_Entries (Prot_Obj);
3118 -- Abort_Undefer;
3119 -- end finalizer;
3121 -- begin
3122 -- . . .
3123 -- begin
3124 -- Prot_SubpN (Prot_Obj);
3125 -- at end
3126 -- finalizer;
3127 -- end;
3128 -- end Prot_SubpP;
3130 declare
3131 Loc : constant Source_Ptr := Sloc (N);
3133 Is_Protected_Subp_Body : constant Boolean :=
3134 Nkind (N) = N_Subprogram_Body
3135 and then Is_Protected_Subprogram_Body (N);
3136 -- True if N is the protected version of a subprogram that belongs to
3137 -- a protected type.
3139 HSS : constant Node_Id :=
3140 (if Is_Protected_Subp_Body
3141 then Handled_Statement_Sequence
3142 (Last (Statements (Handled_Statement_Sequence (N))))
3143 else Handled_Statement_Sequence (N));
3145 -- We attach the At_End_Proc to the HSS if this is an accept
3146 -- statement or extended return statement. Also in the case of
3147 -- a protected subprogram, because if Service_Entries raises an
3148 -- exception, we do not lock the PO, so we also do not want to
3149 -- unlock it.
3151 Use_HSS : constant Boolean :=
3152 Nkind (N) in N_Accept_Statement | N_Extended_Return_Statement
3153 or else Is_Protected_Subp_Body;
3155 At_End_Proc_Bearer : constant Node_Id := (if Use_HSS then HSS else N);
3156 begin
3157 pragma Assert (No (At_End_Proc (At_End_Proc_Bearer)));
3158 Set_At_End_Proc (At_End_Proc_Bearer, New_Occurrence_Of (Fin_Id, Loc));
3159 -- Attach reference to finalizer to tree, for LLVM use
3160 Set_Parent (At_End_Proc (At_End_Proc_Bearer), At_End_Proc_Bearer);
3161 Analyze (At_End_Proc (At_End_Proc_Bearer));
3162 Expand_At_End_Handler (At_End_Proc_Bearer, Empty);
3163 end;
3164 end Build_Finalizer_Call;
3166 ---------------------
3167 -- Build_Late_Proc --
3168 ---------------------
3170 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
3171 begin
3172 for Final_Prim in Name_Of'Range loop
3173 if Name_Of (Final_Prim) = Nam then
3174 Set_TSS (Typ,
3175 Make_Deep_Proc
3176 (Prim => Final_Prim,
3177 Typ => Typ,
3178 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
3179 end if;
3180 end loop;
3181 end Build_Late_Proc;
3183 -------------------------------
3184 -- Build_Object_Declarations --
3185 -------------------------------
3187 procedure Build_Object_Declarations
3188 (Data : out Finalization_Exception_Data;
3189 Decls : List_Id;
3190 Loc : Source_Ptr;
3191 For_Package : Boolean := False)
3193 Decl : Node_Id;
3195 Dummy : Entity_Id;
3196 -- This variable captures an unused dummy internal entity, see the
3197 -- comment associated with its use.
3199 begin
3200 pragma Assert (Decls /= No_List);
3202 -- Always set the proper location as it may be needed even when
3203 -- exception propagation is forbidden.
3205 Data.Loc := Loc;
3207 if Restriction_Active (No_Exception_Propagation) then
3208 Data.Abort_Id := Empty;
3209 Data.E_Id := Empty;
3210 Data.Raised_Id := Empty;
3211 return;
3212 end if;
3214 Data.Raised_Id := Make_Temporary (Loc, 'R');
3216 -- In certain scenarios, finalization can be triggered by an abort. If
3217 -- the finalization itself fails and raises an exception, the resulting
3218 -- Program_Error must be supressed and replaced by an abort signal. In
3219 -- order to detect this scenario, save the state of entry into the
3220 -- finalization code.
3222 -- This is not needed for library-level finalizers as they are called by
3223 -- the environment task and cannot be aborted.
3225 if not For_Package then
3226 if Abort_Allowed then
3227 Data.Abort_Id := Make_Temporary (Loc, 'A');
3229 -- Generate:
3230 -- Abort_Id : constant Boolean := <A_Expr>;
3232 Append_To (Decls,
3233 Make_Object_Declaration (Loc,
3234 Defining_Identifier => Data.Abort_Id,
3235 Constant_Present => True,
3236 Object_Definition =>
3237 New_Occurrence_Of (Standard_Boolean, Loc),
3238 Expression =>
3239 New_Occurrence_Of (RTE (RE_Triggered_By_Abort), Loc)));
3241 -- Abort is not required
3243 else
3244 -- Generate a dummy entity to ensure that the internal symbols are
3245 -- in sync when a unit is compiled with and without aborts.
3247 Dummy := Make_Temporary (Loc, 'A');
3248 Data.Abort_Id := Empty;
3249 end if;
3251 -- Library-level finalizers
3253 else
3254 Data.Abort_Id := Empty;
3255 end if;
3257 if Exception_Extra_Info then
3258 Data.E_Id := Make_Temporary (Loc, 'E');
3260 -- Generate:
3261 -- E_Id : Exception_Occurrence;
3263 Decl :=
3264 Make_Object_Declaration (Loc,
3265 Defining_Identifier => Data.E_Id,
3266 Object_Definition =>
3267 New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc));
3268 Set_No_Initialization (Decl);
3270 Append_To (Decls, Decl);
3272 else
3273 Data.E_Id := Empty;
3274 end if;
3276 -- Generate:
3277 -- Raised_Id : Boolean := False;
3279 Append_To (Decls,
3280 Make_Object_Declaration (Loc,
3281 Defining_Identifier => Data.Raised_Id,
3282 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
3283 Expression => New_Occurrence_Of (Standard_False, Loc)));
3285 if Debug_Generated_Code then
3286 Set_Debug_Info_Needed (Data.Raised_Id);
3287 end if;
3288 end Build_Object_Declarations;
3290 ---------------------------
3291 -- Build_Raise_Statement --
3292 ---------------------------
3294 function Build_Raise_Statement
3295 (Data : Finalization_Exception_Data) return Node_Id
3297 Stmt : Node_Id;
3298 Expr : Node_Id;
3300 begin
3301 -- Standard run-time use the specialized routine
3302 -- Raise_From_Controlled_Operation.
3304 if Exception_Extra_Info
3305 and then RTE_Available (RE_Raise_From_Controlled_Operation)
3306 then
3307 Stmt :=
3308 Make_Procedure_Call_Statement (Data.Loc,
3309 Name =>
3310 New_Occurrence_Of
3311 (RTE (RE_Raise_From_Controlled_Operation), Data.Loc),
3312 Parameter_Associations =>
3313 New_List (New_Occurrence_Of (Data.E_Id, Data.Loc)));
3315 -- Restricted run-time: exception messages are not supported and hence
3316 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3317 -- instead.
3319 else
3320 Stmt :=
3321 Make_Raise_Program_Error (Data.Loc,
3322 Reason => PE_Finalize_Raised_Exception);
3323 end if;
3325 -- Generate:
3327 -- Raised_Id and then not Abort_Id
3328 -- <or>
3329 -- Raised_Id
3331 Expr := New_Occurrence_Of (Data.Raised_Id, Data.Loc);
3333 if Present (Data.Abort_Id) then
3334 Expr := Make_And_Then (Data.Loc,
3335 Left_Opnd => Expr,
3336 Right_Opnd =>
3337 Make_Op_Not (Data.Loc,
3338 Right_Opnd => New_Occurrence_Of (Data.Abort_Id, Data.Loc)));
3339 end if;
3341 -- Generate:
3343 -- if Raised_Id and then not Abort_Id then
3344 -- Raise_From_Controlled_Operation (E_Id);
3345 -- <or>
3346 -- raise Program_Error; -- restricted runtime
3347 -- end if;
3349 return
3350 Make_If_Statement (Data.Loc,
3351 Condition => Expr,
3352 Then_Statements => New_List (Stmt));
3353 end Build_Raise_Statement;
3355 -----------------------------
3356 -- Build_Record_Deep_Procs --
3357 -----------------------------
3359 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3360 begin
3361 Set_TSS (Typ,
3362 Make_Deep_Proc
3363 (Prim => Initialize_Case,
3364 Typ => Typ,
3365 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3367 if not Is_Inherently_Limited_Type (Typ) then
3368 Set_TSS (Typ,
3369 Make_Deep_Proc
3370 (Prim => Adjust_Case,
3371 Typ => Typ,
3372 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3373 end if;
3375 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3376 -- suppressed since these routine will not be used.
3378 if not Restriction_Active (No_Finalization) then
3379 Set_TSS (Typ,
3380 Make_Deep_Proc
3381 (Prim => Finalize_Case,
3382 Typ => Typ,
3383 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3385 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
3387 if not CodePeer_Mode then
3388 Set_TSS (Typ,
3389 Make_Deep_Proc
3390 (Prim => Address_Case,
3391 Typ => Typ,
3392 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3393 end if;
3394 end if;
3395 end Build_Record_Deep_Procs;
3397 -------------------
3398 -- Cleanup_Array --
3399 -------------------
3401 function Cleanup_Array
3402 (N : Node_Id;
3403 Obj : Node_Id;
3404 Typ : Entity_Id) return List_Id
3406 Loc : constant Source_Ptr := Sloc (N);
3407 Index_List : constant List_Id := New_List;
3409 function Free_Component return List_Id;
3410 -- Generate the code to finalize the task or protected subcomponents
3411 -- of a single component of the array.
3413 function Free_One_Dimension (Dim : Int) return List_Id;
3414 -- Generate a loop over one dimension of the array
3416 --------------------
3417 -- Free_Component --
3418 --------------------
3420 function Free_Component return List_Id is
3421 Stmts : List_Id := New_List;
3422 Tsk : Node_Id;
3423 C_Typ : constant Entity_Id := Component_Type (Typ);
3425 begin
3426 -- Component type is known to contain tasks or protected objects
3428 Tsk :=
3429 Make_Indexed_Component (Loc,
3430 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3431 Expressions => Index_List);
3433 Set_Etype (Tsk, C_Typ);
3435 if Is_Task_Type (C_Typ) then
3436 Append_To (Stmts, Cleanup_Task (N, Tsk));
3438 elsif Is_Simple_Protected_Type (C_Typ) then
3439 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3441 elsif Is_Record_Type (C_Typ) then
3442 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3444 elsif Is_Array_Type (C_Typ) then
3445 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3446 end if;
3448 return Stmts;
3449 end Free_Component;
3451 ------------------------
3452 -- Free_One_Dimension --
3453 ------------------------
3455 function Free_One_Dimension (Dim : Int) return List_Id is
3456 Index : Entity_Id;
3458 begin
3459 if Dim > Number_Dimensions (Typ) then
3460 return Free_Component;
3462 -- Here we generate the required loop
3464 else
3465 Index := Make_Temporary (Loc, 'J');
3466 Append (New_Occurrence_Of (Index, Loc), Index_List);
3468 return New_List (
3469 Make_Implicit_Loop_Statement (N,
3470 Identifier => Empty,
3471 Iteration_Scheme =>
3472 Make_Iteration_Scheme (Loc,
3473 Loop_Parameter_Specification =>
3474 Make_Loop_Parameter_Specification (Loc,
3475 Defining_Identifier => Index,
3476 Discrete_Subtype_Definition =>
3477 Make_Attribute_Reference (Loc,
3478 Prefix => Duplicate_Subexpr (Obj),
3479 Attribute_Name => Name_Range,
3480 Expressions => New_List (
3481 Make_Integer_Literal (Loc, Dim))))),
3482 Statements => Free_One_Dimension (Dim + 1)));
3483 end if;
3484 end Free_One_Dimension;
3486 -- Start of processing for Cleanup_Array
3488 begin
3489 return Free_One_Dimension (1);
3490 end Cleanup_Array;
3492 --------------------
3493 -- Cleanup_Record --
3494 --------------------
3496 function Cleanup_Record
3497 (N : Node_Id;
3498 Obj : Node_Id;
3499 Typ : Entity_Id) return List_Id
3501 Loc : constant Source_Ptr := Sloc (N);
3502 Stmts : constant List_Id := New_List;
3503 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3505 Comp : Entity_Id;
3506 Tsk : Node_Id;
3508 begin
3509 if Has_Discriminants (U_Typ)
3510 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3511 and then Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3512 and then
3513 Present
3514 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3515 then
3516 -- For now, do not attempt to free a component that may appear in a
3517 -- variant, and instead issue a warning. Doing this "properly" would
3518 -- require building a case statement and would be quite a mess. Note
3519 -- that the RM only requires that free "work" for the case of a task
3520 -- access value, so already we go way beyond this in that we deal
3521 -- with the array case and non-discriminated record cases.
3523 Error_Msg_N
3524 ("task/protected object in variant record will not be freed??", N);
3525 return New_List (Make_Null_Statement (Loc));
3526 end if;
3528 Comp := First_Component (U_Typ);
3529 while Present (Comp) loop
3530 if Chars (Comp) /= Name_uParent
3531 and then (Has_Task (Etype (Comp))
3532 or else Has_Simple_Protected_Object (Etype (Comp)))
3533 then
3534 Tsk :=
3535 Make_Selected_Component (Loc,
3536 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3537 Selector_Name => New_Occurrence_Of (Comp, Loc));
3538 Set_Etype (Tsk, Etype (Comp));
3540 if Is_Task_Type (Etype (Comp)) then
3541 Append_To (Stmts, Cleanup_Task (N, Tsk));
3543 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3544 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3546 elsif Is_Record_Type (Etype (Comp)) then
3548 -- Recurse, by generating the prefix of the argument to the
3549 -- eventual cleanup call.
3551 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3553 elsif Is_Array_Type (Etype (Comp)) then
3554 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3555 end if;
3556 end if;
3558 Next_Component (Comp);
3559 end loop;
3561 return Stmts;
3562 end Cleanup_Record;
3564 ------------------------------
3565 -- Cleanup_Protected_Object --
3566 ------------------------------
3568 function Cleanup_Protected_Object
3569 (N : Node_Id;
3570 Ref : Node_Id) return Node_Id
3572 Loc : constant Source_Ptr := Sloc (N);
3574 begin
3575 -- For restricted run-time libraries (Ravenscar), tasks are
3576 -- non-terminating, and protected objects can only appear at library
3577 -- level, so we do not want finalization of protected objects.
3579 if Restricted_Profile then
3580 return Empty;
3582 else
3583 return
3584 Make_Procedure_Call_Statement (Loc,
3585 Name =>
3586 New_Occurrence_Of (RTE (RE_Finalize_Protection), Loc),
3587 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3588 end if;
3589 end Cleanup_Protected_Object;
3591 ------------------
3592 -- Cleanup_Task --
3593 ------------------
3595 function Cleanup_Task
3596 (N : Node_Id;
3597 Ref : Node_Id) return Node_Id
3599 Loc : constant Source_Ptr := Sloc (N);
3601 begin
3602 -- For restricted run-time libraries (Ravenscar), tasks are
3603 -- non-terminating and they can only appear at library level,
3604 -- so we do not want finalization of task objects.
3606 if Restricted_Profile then
3607 return Empty;
3609 else
3610 return
3611 Make_Procedure_Call_Statement (Loc,
3612 Name =>
3613 New_Occurrence_Of (RTE (RE_Free_Task), Loc),
3614 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3615 end if;
3616 end Cleanup_Task;
3618 --------------------------------------
3619 -- Check_Unnesting_Elaboration_Code --
3620 --------------------------------------
3622 procedure Check_Unnesting_Elaboration_Code (N : Node_Id) is
3623 Loc : constant Source_Ptr := Sloc (N);
3624 Block_Elab_Proc : Entity_Id := Empty;
3626 procedure Set_Block_Elab_Proc;
3627 -- Create a defining identifier for a procedure that will replace
3628 -- a block with nested subprograms (unless it has already been created,
3629 -- in which case this is a no-op).
3631 procedure Set_Block_Elab_Proc is
3632 begin
3633 if No (Block_Elab_Proc) then
3634 Block_Elab_Proc := Make_Temporary (Loc, 'I');
3635 end if;
3636 end Set_Block_Elab_Proc;
3638 procedure Reset_Scopes_To_Block_Elab_Proc (L : List_Id);
3639 -- Find entities in the elaboration code of a library package body that
3640 -- contain or represent a subprogram body. A body can appear within a
3641 -- block or a loop or can appear by itself if generated for an object
3642 -- declaration that involves controlled actions. The first such entity
3643 -- forces creation of a new procedure entity (via Set_Block_Elab_Proc)
3644 -- that will be used to reset the scopes of all entities that become
3645 -- local to the new elaboration procedure. This is needed for subsequent
3646 -- unnesting actions, which depend on proper setting of the Scope links
3647 -- to determine the nesting level of each subprogram.
3649 --------------------------------------
3650 -- Reset_Scopes_To_Block_Elab_Proc --
3651 --------------------------------------
3652 Maybe_Reset_Scopes_For_Decl : constant Elist_Id := New_Elmt_List;
3654 procedure Reset_Scopes_To_Block_Elab_Proc (L : List_Id) is
3655 Id : Entity_Id;
3656 Stat : Node_Id;
3657 Node : Node_Id;
3659 begin
3660 Stat := First (L);
3661 while Present (Stat) loop
3662 case Nkind (Stat) is
3663 when N_Block_Statement =>
3664 if Present (Identifier (Stat)) then
3665 Id := Entity (Identifier (Stat));
3667 -- The Scope of this block needs to be reset to the new
3668 -- procedure if the block contains nested subprograms.
3670 if Present (Id) and then Contains_Subprogram (Id) then
3671 Set_Block_Elab_Proc;
3672 Set_Scope (Id, Block_Elab_Proc);
3673 end if;
3674 end if;
3676 when N_Loop_Statement =>
3677 Id := Entity (Identifier (Stat));
3679 if Present (Id) and then Contains_Subprogram (Id) then
3680 if Scope (Id) = Current_Scope then
3681 Set_Block_Elab_Proc;
3682 Set_Scope (Id, Block_Elab_Proc);
3683 end if;
3684 end if;
3686 -- We traverse the loop's statements as well, which may
3687 -- include other block (etc.) statements that need to have
3688 -- their Scope set to Block_Elab_Proc. (Is this really the
3689 -- case, or do such nested blocks refer to the loop scope
3690 -- rather than the loop's enclosing scope???.)
3692 Reset_Scopes_To_Block_Elab_Proc (Statements (Stat));
3694 when N_If_Statement =>
3695 Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Stat));
3696 Reset_Scopes_To_Block_Elab_Proc (Else_Statements (Stat));
3698 Node := First (Elsif_Parts (Stat));
3699 while Present (Node) loop
3700 Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Node));
3701 Next (Node);
3702 end loop;
3704 when N_Case_Statement =>
3705 Node := First (Alternatives (Stat));
3706 while Present (Node) loop
3707 Reset_Scopes_To_Block_Elab_Proc (Statements (Node));
3708 Next (Node);
3709 end loop;
3711 -- Reset the Scope of a subprogram and object declaration
3712 -- occurring at the top level
3714 when N_Subprogram_Body =>
3715 Id := Defining_Entity (Stat);
3717 Set_Block_Elab_Proc;
3718 Set_Scope (Id, Block_Elab_Proc);
3720 when N_Object_Declaration
3721 | N_Object_Renaming_Declaration =>
3722 Id := Defining_Entity (Stat);
3723 if No (Block_Elab_Proc) then
3724 Append_Elmt (Id, Maybe_Reset_Scopes_For_Decl);
3725 else
3726 Set_Scope (Id, Block_Elab_Proc);
3727 end if;
3729 when others =>
3730 null;
3731 end case;
3733 Next (Stat);
3734 end loop;
3736 -- If we are creating an Elab procedure, move all the gathered
3737 -- declarations in its scope.
3739 if Present (Block_Elab_Proc) then
3740 while not Is_Empty_Elmt_List (Maybe_Reset_Scopes_For_Decl) loop
3741 Set_Scope
3742 (Elists.Node
3743 (Last_Elmt (Maybe_Reset_Scopes_For_Decl)), Block_Elab_Proc);
3744 Remove_Last_Elmt (Maybe_Reset_Scopes_For_Decl);
3745 end loop;
3746 end if;
3747 end Reset_Scopes_To_Block_Elab_Proc;
3749 -- Local variables
3751 H_Seq : constant Node_Id := Handled_Statement_Sequence (N);
3752 Elab_Body : Node_Id;
3753 Elab_Call : Node_Id;
3755 -- Start of processing for Check_Unnesting_Elaboration_Code
3757 begin
3758 if Present (H_Seq) then
3759 Reset_Scopes_To_Block_Elab_Proc (Statements (H_Seq));
3761 -- There may be subprograms declared in the exception handlers
3762 -- of the current body.
3764 if Present (Exception_Handlers (H_Seq)) then
3765 declare
3766 Handler : Node_Id := First (Exception_Handlers (H_Seq));
3767 begin
3768 while Present (Handler) loop
3769 Reset_Scopes_To_Block_Elab_Proc (Statements (Handler));
3771 Next (Handler);
3772 end loop;
3773 end;
3774 end if;
3776 if Present (Block_Elab_Proc) then
3777 Elab_Body :=
3778 Make_Subprogram_Body (Loc,
3779 Specification =>
3780 Make_Procedure_Specification (Loc,
3781 Defining_Unit_Name => Block_Elab_Proc),
3782 Declarations => New_List,
3783 Handled_Statement_Sequence =>
3784 Relocate_Node (Handled_Statement_Sequence (N)));
3786 Elab_Call :=
3787 Make_Procedure_Call_Statement (Loc,
3788 Name => New_Occurrence_Of (Block_Elab_Proc, Loc));
3790 Append_To (Declarations (N), Elab_Body);
3791 Analyze (Elab_Body);
3792 Set_Has_Nested_Subprogram (Block_Elab_Proc);
3794 Set_Handled_Statement_Sequence (N,
3795 Make_Handled_Sequence_Of_Statements (Loc,
3796 Statements => New_List (Elab_Call)));
3798 Analyze (Elab_Call);
3800 -- Could we reset the scopes of entities associated with the new
3801 -- procedure here via a loop over entities rather than doing it in
3802 -- the recursive Reset_Scopes_To_Elab_Proc procedure???
3803 end if;
3804 end if;
3805 end Check_Unnesting_Elaboration_Code;
3807 ---------------------------------------
3808 -- Check_Unnesting_In_Decls_Or_Stmts --
3809 ---------------------------------------
3811 procedure Check_Unnesting_In_Decls_Or_Stmts (Decls_Or_Stmts : List_Id) is
3812 Decl_Or_Stmt : Node_Id;
3814 begin
3815 if Unnest_Subprogram_Mode
3816 and then Present (Decls_Or_Stmts)
3817 then
3818 Decl_Or_Stmt := First (Decls_Or_Stmts);
3819 while Present (Decl_Or_Stmt) loop
3820 if Nkind (Decl_Or_Stmt) = N_Block_Statement
3821 and then Contains_Subprogram (Entity (Identifier (Decl_Or_Stmt)))
3822 then
3823 Unnest_Block (Decl_Or_Stmt);
3825 -- If-statements may contain subprogram bodies at the outer level
3826 -- of their statement lists, and the subprograms may make up-level
3827 -- references (such as to objects declared in the same statement
3828 -- list). Unlike block and loop cases, however, we don't have an
3829 -- entity on which to test the Contains_Subprogram flag, so
3830 -- Unnest_If_Statement must traverse the statement lists to
3831 -- determine whether there are nested subprograms present.
3833 elsif Nkind (Decl_Or_Stmt) = N_If_Statement then
3834 Unnest_If_Statement (Decl_Or_Stmt);
3836 elsif Nkind (Decl_Or_Stmt) = N_Loop_Statement then
3837 declare
3838 Id : constant Entity_Id :=
3839 Entity (Identifier (Decl_Or_Stmt));
3841 begin
3842 -- When a top-level loop within declarations of a library
3843 -- package spec or body contains nested subprograms, we wrap
3844 -- it in a procedure to handle possible up-level references
3845 -- to entities associated with the loop (such as loop
3846 -- parameters).
3848 if Present (Id) and then Contains_Subprogram (Id) then
3849 Unnest_Loop (Decl_Or_Stmt);
3850 end if;
3851 end;
3853 elsif Nkind (Decl_Or_Stmt) = N_Package_Declaration
3854 and then not Modify_Tree_For_C
3855 then
3856 Check_Unnesting_In_Decls_Or_Stmts
3857 (Visible_Declarations (Specification (Decl_Or_Stmt)));
3858 Check_Unnesting_In_Decls_Or_Stmts
3859 (Private_Declarations (Specification (Decl_Or_Stmt)));
3861 elsif Nkind (Decl_Or_Stmt) = N_Package_Body
3862 and then not Modify_Tree_For_C
3863 then
3864 Check_Unnesting_In_Decls_Or_Stmts (Declarations (Decl_Or_Stmt));
3865 if Present (Statements
3866 (Handled_Statement_Sequence (Decl_Or_Stmt)))
3867 then
3868 Check_Unnesting_In_Decls_Or_Stmts (Statements
3869 (Handled_Statement_Sequence (Decl_Or_Stmt)));
3870 Check_Unnesting_In_Handlers (Decl_Or_Stmt);
3871 end if;
3872 end if;
3874 Next (Decl_Or_Stmt);
3875 end loop;
3876 end if;
3877 end Check_Unnesting_In_Decls_Or_Stmts;
3879 ---------------------------------
3880 -- Check_Unnesting_In_Handlers --
3881 ---------------------------------
3883 procedure Check_Unnesting_In_Handlers (N : Node_Id) is
3884 Stmt_Seq : constant Node_Id := Handled_Statement_Sequence (N);
3886 begin
3887 if Present (Stmt_Seq)
3888 and then Present (Exception_Handlers (Stmt_Seq))
3889 then
3890 declare
3891 Handler : Node_Id := First (Exception_Handlers (Stmt_Seq));
3892 begin
3893 while Present (Handler) loop
3894 if Present (Statements (Handler)) then
3895 Check_Unnesting_In_Decls_Or_Stmts (Statements (Handler));
3896 end if;
3898 Next (Handler);
3899 end loop;
3900 end;
3901 end if;
3902 end Check_Unnesting_In_Handlers;
3904 ------------------------------
3905 -- Check_Visibly_Controlled --
3906 ------------------------------
3908 procedure Check_Visibly_Controlled
3909 (Prim : Final_Primitives;
3910 Typ : Entity_Id;
3911 E : in out Entity_Id;
3912 Cref : in out Node_Id)
3914 Parent_Type : Entity_Id;
3915 Op : Entity_Id;
3917 begin
3918 if Is_Derived_Type (Typ)
3919 and then Comes_From_Source (E)
3920 and then No (Overridden_Operation (E))
3921 then
3922 -- We know that the explicit operation on the type does not override
3923 -- the inherited operation of the parent, and that the derivation
3924 -- is from a private type that is not visibly controlled.
3926 Parent_Type := Etype (Typ);
3927 Op := Find_Optional_Prim_Op (Parent_Type, Name_Of (Prim));
3929 if Present (Op) then
3930 E := Op;
3932 -- Wrap the object to be initialized into the proper
3933 -- unchecked conversion, to be compatible with the operation
3934 -- to be called.
3936 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3937 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3938 else
3939 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3940 end if;
3941 end if;
3942 end if;
3943 end Check_Visibly_Controlled;
3945 --------------------------
3946 -- Contains_Subprogram --
3947 --------------------------
3949 function Contains_Subprogram (Blk : Entity_Id) return Boolean is
3950 E : Entity_Id;
3952 begin
3953 E := First_Entity (Blk);
3955 -- The compiler may generate loops with a declare block containing
3956 -- nested procedures used for finalization. Recursively search for
3957 -- subprograms in such constructs.
3959 if Ekind (Blk) = E_Loop
3960 and then Parent_Kind (Blk) = N_Loop_Statement
3961 then
3962 declare
3963 Stmt : Node_Id := First (Statements (Parent (Blk)));
3964 begin
3965 while Present (Stmt) loop
3966 if Nkind (Stmt) = N_Block_Statement then
3967 declare
3968 Id : constant Entity_Id :=
3969 Entity (Identifier (Stmt));
3970 begin
3971 if Contains_Subprogram (Id) then
3972 return True;
3973 end if;
3974 end;
3975 end if;
3976 Next (Stmt);
3977 end loop;
3978 end;
3979 end if;
3981 while Present (E) loop
3982 if Is_Subprogram (E) then
3983 return True;
3985 elsif Ekind (E) in E_Block | E_Loop
3986 and then Contains_Subprogram (E)
3987 then
3988 return True;
3989 end if;
3991 Next_Entity (E);
3992 end loop;
3994 return False;
3995 end Contains_Subprogram;
3997 ------------------
3998 -- Convert_View --
3999 ------------------
4001 function Convert_View (Proc : Entity_Id; Arg : Node_Id) return Node_Id is
4002 Ftyp : constant Entity_Id := Etype (First_Formal (Proc));
4004 Atyp : Entity_Id;
4006 begin
4007 if Nkind (Arg) in N_Type_Conversion | N_Unchecked_Type_Conversion then
4008 Atyp := Entity (Subtype_Mark (Arg));
4009 else
4010 Atyp := Etype (Arg);
4011 end if;
4013 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
4014 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
4016 elsif Present (Atyp)
4017 and then Atyp /= Ftyp
4018 and then (Is_Private_Type (Ftyp)
4019 or else Is_Private_Type (Atyp)
4020 or else Is_Private_Type (Base_Type (Atyp)))
4021 and then Implementation_Base_Type (Atyp) =
4022 Implementation_Base_Type (Ftyp)
4023 then
4024 return Unchecked_Convert_To (Ftyp, Arg);
4026 -- If the argument is already a conversion, as generated by
4027 -- Make_Init_Call, set the target type to the type of the formal
4028 -- directly, to avoid spurious typing problems.
4030 elsif Nkind (Arg) in N_Unchecked_Type_Conversion | N_Type_Conversion
4031 and then not Is_Class_Wide_Type (Atyp)
4032 then
4033 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
4034 Set_Etype (Arg, Ftyp);
4035 return Arg;
4037 -- Otherwise, introduce a conversion when the designated object
4038 -- has a type derived from the formal of the controlled routine.
4040 elsif Is_Private_Type (Ftyp)
4041 and then Present (Atyp)
4042 and then Is_Derived_Type (Underlying_Type (Base_Type (Atyp)))
4043 then
4044 return Unchecked_Convert_To (Ftyp, Arg);
4046 else
4047 return Arg;
4048 end if;
4049 end Convert_View;
4051 -------------------------------
4052 -- Establish_Transient_Scope --
4053 -------------------------------
4055 -- This procedure is called each time a transient block has to be inserted
4056 -- that is to say for each call to a function with unconstrained or tagged
4057 -- result. It creates a new scope on the scope stack in order to enclose
4058 -- all transient variables generated.
4060 procedure Establish_Transient_Scope
4061 (N : Node_Id;
4062 Manage_Sec_Stack : Boolean)
4064 function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean;
4065 -- Determine whether arbitrary Id denotes a package or subprogram [body]
4067 function Find_Enclosing_Transient_Scope return Int;
4068 -- Examine the scope stack looking for the nearest enclosing transient
4069 -- scope within the innermost enclosing package or subprogram. Return
4070 -- its index in the table or else -1 if no such scope exists.
4072 function Find_Transient_Context (N : Node_Id) return Node_Id;
4073 -- Locate a suitable context for arbitrary node N which may need to be
4074 -- serviced by a transient scope. Return Empty if no suitable context
4075 -- is available.
4077 procedure Delegate_Sec_Stack_Management;
4078 -- Move the management of the secondary stack to the nearest enclosing
4079 -- suitable scope.
4081 procedure Create_Transient_Scope (Context : Node_Id);
4082 -- Place a new scope on the scope stack in order to service construct
4083 -- Context. Context is the node found by Find_Transient_Context. The
4084 -- new scope may also manage the secondary stack.
4086 ----------------------------
4087 -- Create_Transient_Scope --
4088 ----------------------------
4090 procedure Create_Transient_Scope (Context : Node_Id) is
4091 Loc : constant Source_Ptr := Sloc (N);
4093 Iter_Loop : Entity_Id;
4094 Trans_Scop : constant Entity_Id :=
4095 New_Internal_Entity (E_Block, Current_Scope, Loc, 'B');
4097 begin
4098 Set_Etype (Trans_Scop, Standard_Void_Type);
4100 -- Push a new scope, and set its Node_To_Be_Wrapped and Is_Transient
4101 -- fields.
4103 Push_Scope (Trans_Scop);
4104 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := Context;
4105 Scope_Stack.Table (Scope_Stack.Last).Is_Transient := True;
4107 -- The transient scope must also manage the secondary stack
4109 if Manage_Sec_Stack then
4110 Set_Uses_Sec_Stack (Trans_Scop);
4111 Check_Restriction (No_Secondary_Stack, N);
4113 -- The expansion of iterator loops generates references to objects
4114 -- in order to extract elements from a container:
4116 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
4117 -- Obj : <object type> renames Ref.all.Element.all;
4119 -- These references are controlled and returned on the secondary
4120 -- stack. A new reference is created at each iteration of the loop
4121 -- and as a result it must be finalized and the space occupied by
4122 -- it on the secondary stack reclaimed at the end of the current
4123 -- iteration.
4125 -- When the context that requires a transient scope is a call to
4126 -- routine Reference, the node to be wrapped is the source object:
4128 -- for Obj of Container loop
4130 -- Routine Wrap_Transient_Declaration however does not generate
4131 -- a physical block as wrapping a declaration will kill it too
4132 -- early. To handle this peculiar case, mark the related iterator
4133 -- loop as requiring the secondary stack. This signals the
4134 -- finalization machinery to manage the secondary stack (see
4135 -- routine Process_Statements_For_Controlled_Objects).
4137 Iter_Loop := Find_Enclosing_Iterator_Loop (Trans_Scop);
4139 if Present (Iter_Loop) then
4140 Set_Uses_Sec_Stack (Iter_Loop);
4141 end if;
4142 end if;
4144 if Debug_Flag_W then
4145 Write_Str (" <Transient>");
4146 Write_Eol;
4147 end if;
4148 end Create_Transient_Scope;
4150 -----------------------------------
4151 -- Delegate_Sec_Stack_Management --
4152 -----------------------------------
4154 procedure Delegate_Sec_Stack_Management is
4155 begin
4156 for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop
4157 declare
4158 Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index);
4159 begin
4160 -- Prevent the search from going too far or within the scope
4161 -- space of another unit.
4163 if Scope.Entity = Standard_Standard then
4164 return;
4166 -- No transient scope should be encountered during the
4167 -- traversal because Establish_Transient_Scope should have
4168 -- already handled this case.
4170 elsif Scope.Is_Transient then
4171 raise Program_Error;
4173 -- The construct that requires secondary stack management is
4174 -- always enclosed by a package or subprogram scope.
4176 elsif Is_Package_Or_Subprogram (Scope.Entity) then
4177 Set_Uses_Sec_Stack (Scope.Entity);
4178 Check_Restriction (No_Secondary_Stack, N);
4180 return;
4181 end if;
4182 end;
4183 end loop;
4185 -- At this point no suitable scope was found. This should never occur
4186 -- because a construct is always enclosed by a compilation unit which
4187 -- has a scope.
4189 pragma Assert (False);
4190 end Delegate_Sec_Stack_Management;
4192 ------------------------------------
4193 -- Find_Enclosing_Transient_Scope --
4194 ------------------------------------
4196 function Find_Enclosing_Transient_Scope return Int is
4197 begin
4198 for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop
4199 declare
4200 Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index);
4201 begin
4202 -- Prevent the search from going too far or within the scope
4203 -- space of another unit.
4205 if Scope.Entity = Standard_Standard
4206 or else Is_Package_Or_Subprogram (Scope.Entity)
4207 then
4208 exit;
4210 elsif Scope.Is_Transient then
4211 return Index;
4212 end if;
4213 end;
4214 end loop;
4216 return -1;
4217 end Find_Enclosing_Transient_Scope;
4219 ----------------------------
4220 -- Find_Transient_Context --
4221 ----------------------------
4223 function Find_Transient_Context (N : Node_Id) return Node_Id is
4224 Curr : Node_Id := N;
4225 Prev : Node_Id := Empty;
4227 begin
4228 while Present (Curr) loop
4229 case Nkind (Curr) is
4231 -- Declarations
4233 -- Declarations act as a boundary for a transient scope even if
4234 -- they are not wrapped, see Wrap_Transient_Declaration.
4236 when N_Object_Declaration
4237 | N_Object_Renaming_Declaration
4238 | N_Subtype_Declaration
4240 return Curr;
4242 -- Statements
4244 -- Statements and statement-like constructs act as a boundary
4245 -- for a transient scope.
4247 when N_Accept_Alternative
4248 | N_Attribute_Definition_Clause
4249 | N_Case_Statement
4250 | N_Case_Statement_Alternative
4251 | N_Code_Statement
4252 | N_Delay_Alternative
4253 | N_Delay_Until_Statement
4254 | N_Delay_Relative_Statement
4255 | N_Discriminant_Association
4256 | N_Elsif_Part
4257 | N_Entry_Body_Formal_Part
4258 | N_Exit_Statement
4259 | N_If_Statement
4260 | N_Iteration_Scheme
4261 | N_Terminate_Alternative
4263 pragma Assert (Present (Prev));
4264 return Prev;
4266 when N_Assignment_Statement =>
4267 return Curr;
4269 when N_Entry_Call_Statement
4270 | N_Procedure_Call_Statement
4272 -- When an entry or procedure call acts as the alternative
4273 -- of a conditional or timed entry call, the proper context
4274 -- is that of the alternative.
4276 if Nkind (Parent (Curr)) = N_Entry_Call_Alternative
4277 and then Nkind (Parent (Parent (Curr))) in
4278 N_Conditional_Entry_Call | N_Timed_Entry_Call
4279 then
4280 return Parent (Parent (Curr));
4282 -- General case for entry or procedure calls
4284 else
4285 return Curr;
4286 end if;
4288 when N_Pragma =>
4290 -- Pragma Check is not a valid transient context in
4291 -- GNATprove mode because the pragma must remain unchanged.
4293 if GNATprove_Mode
4294 and then Get_Pragma_Id (Curr) = Pragma_Check
4295 then
4296 return Empty;
4298 -- General case for pragmas
4300 else
4301 return Curr;
4302 end if;
4304 when N_Raise_Statement =>
4305 return Curr;
4307 when N_Simple_Return_Statement =>
4308 declare
4309 Fun_Id : constant Entity_Id :=
4310 Return_Applies_To (Return_Statement_Entity (Curr));
4312 begin
4313 -- A transient context that must manage the secondary
4314 -- stack cannot be a return statement of a function that
4315 -- itself requires secondary stack management, because
4316 -- the function's result would be reclaimed too early.
4317 -- And returns of thunks never require transient scopes.
4319 if (Manage_Sec_Stack
4320 and then Needs_Secondary_Stack (Etype (Fun_Id)))
4321 or else Is_Thunk (Fun_Id)
4322 then
4323 return Empty;
4325 -- General case for return statements
4327 else
4328 return Curr;
4329 end if;
4330 end;
4332 -- Special
4334 when N_Attribute_Reference =>
4335 if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then
4336 return Curr;
4337 end if;
4339 -- An Ada 2012 iterator specification is not a valid context
4340 -- because Analyze_Iterator_Specification already employs
4341 -- special processing for it.
4343 when N_Iterator_Specification =>
4344 return Empty;
4346 when N_Loop_Parameter_Specification =>
4348 -- An iteration scheme is not a valid context because
4349 -- routine Analyze_Iteration_Scheme already employs
4350 -- special processing.
4352 if Nkind (Parent (Curr)) = N_Iteration_Scheme then
4353 return Empty;
4354 else
4355 return Parent (Curr);
4356 end if;
4358 -- Termination
4360 -- The following nodes represent "dummy contexts" which do not
4361 -- need to be wrapped.
4363 when N_Component_Declaration
4364 | N_Discriminant_Specification
4365 | N_Parameter_Specification
4367 return Empty;
4369 -- If the traversal leaves a scope without having been able to
4370 -- find a construct to wrap, something is going wrong, but this
4371 -- can happen in error situations that are not detected yet
4372 -- (such as a dynamic string in a pragma Export).
4374 when N_Block_Statement
4375 | N_Entry_Body
4376 | N_Package_Body
4377 | N_Package_Declaration
4378 | N_Protected_Body
4379 | N_Subprogram_Body
4380 | N_Task_Body
4382 return Empty;
4384 -- Default
4386 when others =>
4387 null;
4388 end case;
4390 Prev := Curr;
4391 Curr := Parent (Curr);
4392 end loop;
4394 return Empty;
4395 end Find_Transient_Context;
4397 ------------------------------
4398 -- Is_Package_Or_Subprogram --
4399 ------------------------------
4401 function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean is
4402 begin
4403 return Ekind (Id) in E_Entry
4404 | E_Entry_Family
4405 | E_Function
4406 | E_Package
4407 | E_Procedure
4408 | E_Subprogram_Body;
4409 end Is_Package_Or_Subprogram;
4411 -- Local variables
4413 Trans_Idx : constant Int := Find_Enclosing_Transient_Scope;
4414 Context : Node_Id;
4416 -- Start of processing for Establish_Transient_Scope
4418 begin
4419 -- Do not create a new transient scope if there is already an enclosing
4420 -- transient scope within the innermost enclosing package or subprogram.
4422 if Trans_Idx >= 0 then
4424 -- If the transient scope was requested for purposes of managing the
4425 -- secondary stack, then the existing scope must perform this task,
4426 -- unless the node to be wrapped is a return statement of a function
4427 -- that requires secondary stack management, because the function's
4428 -- result would be reclaimed too early (see Find_Transient_Context).
4430 if Manage_Sec_Stack then
4431 declare
4432 SE : Scope_Stack_Entry renames Scope_Stack.Table (Trans_Idx);
4434 begin
4435 if Nkind (SE.Node_To_Be_Wrapped) /= N_Simple_Return_Statement
4436 or else not
4437 Needs_Secondary_Stack
4438 (Etype
4439 (Return_Applies_To
4440 (Return_Statement_Entity (SE.Node_To_Be_Wrapped))))
4441 then
4442 Set_Uses_Sec_Stack (SE.Entity);
4443 end if;
4444 end;
4445 end if;
4447 return;
4448 end if;
4450 -- Find the construct that must be serviced by a new transient scope, if
4451 -- it exists.
4453 Context := Find_Transient_Context (N);
4455 if Present (Context) then
4456 if Nkind (Context) = N_Assignment_Statement then
4458 -- An assignment statement with suppressed controlled semantics
4459 -- does not need a transient scope because finalization is not
4460 -- desirable at this point. Note that No_Ctrl_Actions is also
4461 -- set for non-controlled assignments to suppress dispatching
4462 -- _assign.
4464 if No_Ctrl_Actions (Context)
4465 and then Needs_Finalization (Etype (Name (Context)))
4466 then
4467 -- When a controlled component is initialized by a function
4468 -- call, the result on the secondary stack is always assigned
4469 -- to the component. Signal the nearest suitable scope that it
4470 -- is safe to manage the secondary stack.
4472 if Manage_Sec_Stack and then Within_Init_Proc then
4473 Delegate_Sec_Stack_Management;
4474 end if;
4476 -- Otherwise the assignment is a normal transient context and thus
4477 -- requires a transient scope.
4479 else
4480 Create_Transient_Scope (Context);
4481 end if;
4483 -- General case
4485 else
4486 Create_Transient_Scope (Context);
4487 end if;
4488 end if;
4489 end Establish_Transient_Scope;
4491 ----------------------------
4492 -- Expand_Cleanup_Actions --
4493 ----------------------------
4495 procedure Expand_Cleanup_Actions (N : Node_Id) is
4496 pragma Assert
4497 (Nkind (N) in N_Block_Statement
4498 | N_Subprogram_Body
4499 | N_Task_Body
4500 | N_Entry_Body
4501 | N_Extended_Return_Statement);
4503 Scop : constant Entity_Id := Current_Scope;
4505 Is_Asynchronous_Call : constant Boolean :=
4506 Nkind (N) = N_Block_Statement
4507 and then Is_Asynchronous_Call_Block (N);
4508 Is_Master : constant Boolean :=
4509 Nkind (N) /= N_Extended_Return_Statement
4510 and then Nkind (N) /= N_Entry_Body
4511 and then Is_Task_Master (N);
4512 Is_Protected_Subp_Body : constant Boolean :=
4513 Nkind (N) = N_Subprogram_Body
4514 and then Is_Protected_Subprogram_Body (N);
4515 Is_Task_Allocation : constant Boolean :=
4516 Nkind (N) = N_Block_Statement
4517 and then Is_Task_Allocation_Block (N);
4518 Is_Task_Body : constant Boolean :=
4519 Nkind (Original_Node (N)) = N_Task_Body;
4521 -- We mark the secondary stack if it is used in this construct, and
4522 -- we're not returning a function result on the secondary stack, except
4523 -- that a build-in-place function that might or might not return on the
4524 -- secondary stack always needs a mark. A run-time test is required in
4525 -- the case where the build-in-place function has a BIP_Alloc extra
4526 -- parameter (see Create_Finalizer).
4528 Needs_Sec_Stack_Mark : constant Boolean :=
4529 (Uses_Sec_Stack (Scop)
4530 and then
4531 not Sec_Stack_Needed_For_Return (Scop))
4532 or else
4533 (Is_Build_In_Place_Function (Scop)
4534 and then Needs_BIP_Alloc_Form (Scop));
4536 Needs_Custom_Cleanup : constant Boolean :=
4537 Nkind (N) = N_Block_Statement
4538 and then Present (Cleanup_Actions (N));
4540 Actions_Required : constant Boolean :=
4541 Requires_Cleanup_Actions (N, True)
4542 or else Is_Asynchronous_Call
4543 or else Is_Master
4544 or else Is_Protected_Subp_Body
4545 or else Is_Task_Allocation
4546 or else Is_Task_Body
4547 or else Needs_Sec_Stack_Mark
4548 or else Needs_Custom_Cleanup;
4550 Loc : Source_Ptr;
4551 Cln : List_Id;
4553 -- Start of processing for Expand_Cleanup_Actions
4555 begin
4556 -- The current construct does not need any form of servicing
4558 if not Actions_Required then
4559 return;
4560 end if;
4562 -- If an extended return statement contains something like
4564 -- X := F (...);
4566 -- where F is a build-in-place function call returning a controlled
4567 -- type, then a temporary object will be implicitly declared as part
4568 -- of the statement list, and this will need cleanup. In such cases,
4569 -- we transform:
4571 -- return Result : T := ... do
4572 -- <statements> -- possibly with handlers
4573 -- end return;
4575 -- into:
4577 -- return Result : T := ... do
4578 -- declare -- no declarations
4579 -- begin
4580 -- <statements> -- possibly with handlers
4581 -- end; -- no handlers
4582 -- end return;
4584 -- So Expand_Cleanup_Actions will end up being called recursively on the
4585 -- block statement.
4587 if Nkind (N) = N_Extended_Return_Statement then
4588 declare
4589 Block : constant Node_Id :=
4590 Make_Block_Statement (Sloc (N),
4591 Declarations => Empty_List,
4592 Handled_Statement_Sequence =>
4593 Handled_Statement_Sequence (N));
4594 begin
4595 Set_Handled_Statement_Sequence (N,
4596 Make_Handled_Sequence_Of_Statements (Sloc (N),
4597 Statements => New_List (Block)));
4599 Analyze (Block);
4600 end;
4602 -- Analysis of the block did all the work
4604 return;
4605 end if;
4607 if Needs_Custom_Cleanup then
4608 Cln := Cleanup_Actions (N);
4609 else
4610 Cln := No_List;
4611 end if;
4613 if No (Declarations (N)) then
4614 Set_Declarations (N, New_List);
4615 end if;
4617 declare
4618 Decls : constant List_Id := Declarations (N);
4619 Fin_Id : Entity_Id;
4620 Mark : Entity_Id := Empty;
4621 begin
4622 -- If we are generating expanded code for debugging purposes, use the
4623 -- Sloc of the point of insertion for the cleanup code. The Sloc will
4624 -- be updated subsequently to reference the proper line in .dg files.
4625 -- If we are not debugging generated code, use No_Location instead,
4626 -- so that no debug information is generated for the cleanup code.
4627 -- This makes the behavior of the NEXT command in GDB monotonic, and
4628 -- makes the placement of breakpoints more accurate.
4630 if Debug_Generated_Code then
4631 Loc := Sloc (Scop);
4632 else
4633 Loc := No_Location;
4634 end if;
4636 -- A task activation call has already been built for a task
4637 -- allocation block.
4639 if not Is_Task_Allocation then
4640 Build_Task_Activation_Call (N);
4641 end if;
4643 if Is_Master then
4644 Establish_Task_Master (N);
4645 end if;
4647 -- If secondary stack is in use, generate:
4649 -- Mnn : constant Mark_Id := SS_Mark;
4651 if Needs_Sec_Stack_Mark then
4652 Set_Uses_Sec_Stack (Scop, False); -- avoid duplicate SS marks
4653 Mark := Make_Temporary (Loc, 'M');
4655 declare
4656 Mark_Call : constant Node_Id := Build_SS_Mark_Call (Loc, Mark);
4657 begin
4658 Prepend_To (Decls, Mark_Call);
4659 Analyze (Mark_Call);
4660 end;
4661 end if;
4663 -- Generate finalization calls for all controlled objects appearing
4664 -- in the statements of N. Add context specific cleanup for various
4665 -- constructs.
4667 Build_Finalizer
4668 (N => N,
4669 Clean_Stmts => Build_Cleanup_Statements (N, Cln),
4670 Mark_Id => Mark,
4671 Top_Decls => Decls,
4672 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
4673 or else Is_Master,
4674 Fin_Id => Fin_Id);
4676 if Present (Fin_Id) then
4677 Build_Finalizer_Call (N, Fin_Id);
4678 end if;
4679 end;
4680 end Expand_Cleanup_Actions;
4682 ---------------------------
4683 -- Expand_N_Package_Body --
4684 ---------------------------
4686 -- Add call to Activate_Tasks if body is an activator (actual processing
4687 -- is in chapter 9).
4689 -- Generate subprogram descriptor for elaboration routine
4691 -- Encode entity names in package body
4693 procedure Expand_N_Package_Body (N : Node_Id) is
4694 Id : constant Entity_Id := Defining_Entity (N);
4695 Spec_Id : constant Entity_Id := Corresponding_Spec (N);
4697 Fin_Id : Entity_Id;
4699 begin
4700 -- This is done only for non-generic packages
4702 if Ekind (Spec_Id) = E_Package then
4703 -- Build dispatch tables of library-level tagged types for bodies
4704 -- that are not compilation units (see Analyze_Compilation_Unit),
4705 -- except for instances because they have no N_Compilation_Unit.
4707 if Tagged_Type_Expansion
4708 and then Is_Library_Level_Entity (Spec_Id)
4709 and then (not Is_Compilation_Unit (Spec_Id)
4710 or else Is_Generic_Instance (Spec_Id))
4711 then
4712 Build_Static_Dispatch_Tables (N);
4713 end if;
4715 Push_Scope (Spec_Id);
4717 Expand_CUDA_Package (N);
4719 Build_Task_Activation_Call (N);
4721 -- Verify the run-time semantics of pragma Initial_Condition at the
4722 -- end of the body statements.
4724 Expand_Pragma_Initial_Condition (Spec_Id, N);
4726 -- If this is a library-level package and unnesting is enabled,
4727 -- check for the presence of blocks with nested subprograms occurring
4728 -- in elaboration code, and generate procedures to encapsulate the
4729 -- blocks in case the nested subprograms make up-level references.
4731 if Unnest_Subprogram_Mode
4732 and then
4733 Is_Library_Level_Entity (Current_Scope)
4734 then
4735 Check_Unnesting_Elaboration_Code (N);
4736 Check_Unnesting_In_Decls_Or_Stmts (Declarations (N));
4737 Check_Unnesting_In_Handlers (N);
4738 end if;
4740 Pop_Scope;
4741 end if;
4743 Set_Elaboration_Flag (N, Spec_Id);
4744 Set_In_Package_Body (Spec_Id, False);
4746 -- Set to encode entity names in package body before gigi is called
4748 Qualify_Entity_Names (N);
4750 if Ekind (Spec_Id) /= E_Generic_Package
4751 and then not Delay_Cleanups (Id)
4752 then
4753 Build_Finalizer
4754 (N => N,
4755 Clean_Stmts => No_List,
4756 Mark_Id => Empty,
4757 Top_Decls => No_List,
4758 Defer_Abort => False,
4759 Fin_Id => Fin_Id);
4761 if Present (Fin_Id) then
4762 Set_Finalizer (Defining_Entity (N), Fin_Id);
4763 end if;
4764 end if;
4765 end Expand_N_Package_Body;
4767 ----------------------------------
4768 -- Expand_N_Package_Declaration --
4769 ----------------------------------
4771 -- Add call to Activate_Tasks if there are tasks declared and the package
4772 -- has no body. Note that in Ada 83 this may result in premature activation
4773 -- of some tasks, given that we cannot tell whether a body will eventually
4774 -- appear.
4776 procedure Expand_N_Package_Declaration (N : Node_Id) is
4777 Id : constant Entity_Id := Defining_Entity (N);
4778 Spec : constant Node_Id := Specification (N);
4779 Decls : List_Id;
4780 Fin_Id : Entity_Id;
4782 No_Body : Boolean := False;
4783 -- True in the case of a package declaration that is a compilation
4784 -- unit and for which no associated body will be compiled in this
4785 -- compilation.
4787 begin
4788 -- Case of a package declaration other than a compilation unit
4790 if Nkind (Parent (N)) /= N_Compilation_Unit then
4791 null;
4793 -- Case of a compilation unit that does not require a body
4795 elsif not Body_Required (Parent (N))
4796 and then not Unit_Requires_Body (Id)
4797 then
4798 No_Body := True;
4800 -- Special case of generating calling stubs for a remote call interface
4801 -- package: even though the package declaration requires one, the body
4802 -- won't be processed in this compilation (so any stubs for RACWs
4803 -- declared in the package must be generated here, along with the spec).
4805 elsif Parent (N) = Cunit (Main_Unit)
4806 and then Is_Remote_Call_Interface (Id)
4807 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
4808 then
4809 No_Body := True;
4810 end if;
4812 -- For a nested instance, delay processing until freeze point
4814 if Has_Delayed_Freeze (Id)
4815 and then Nkind (Parent (N)) /= N_Compilation_Unit
4816 then
4817 return;
4818 end if;
4820 -- For a package declaration that implies no associated body, generate
4821 -- task activation call and RACW supporting bodies now (since we won't
4822 -- have a specific separate compilation unit for that).
4824 if No_Body then
4825 Push_Scope (Id);
4827 -- Generate RACW subprogram bodies
4829 if Has_RACW (Id) then
4830 Decls := Private_Declarations (Spec);
4832 if No (Decls) then
4833 Decls := Visible_Declarations (Spec);
4834 end if;
4836 if No (Decls) then
4837 Decls := New_List;
4838 Set_Visible_Declarations (Spec, Decls);
4839 end if;
4841 Append_RACW_Bodies (Decls, Id);
4842 Analyze_List (Decls);
4843 end if;
4845 -- Generate task activation call as last step of elaboration
4847 if Present (Activation_Chain_Entity (N)) then
4848 Build_Task_Activation_Call (N);
4849 end if;
4851 -- Verify the run-time semantics of pragma Initial_Condition at the
4852 -- end of the private declarations when the package lacks a body.
4854 Expand_Pragma_Initial_Condition (Id, N);
4856 Pop_Scope;
4857 end if;
4859 -- Build dispatch tables of library-level tagged types for instances
4860 -- that are not compilation units (see Analyze_Compilation_Unit).
4862 if Tagged_Type_Expansion
4863 and then Is_Library_Level_Entity (Id)
4864 and then Is_Generic_Instance (Id)
4865 and then not Is_Compilation_Unit (Id)
4866 then
4867 Build_Static_Dispatch_Tables (N);
4868 end if;
4870 -- Note: it is not necessary to worry about generating a subprogram
4871 -- descriptor, since the only way to get exception handlers into a
4872 -- package spec is to include instantiations, and that would cause
4873 -- generation of subprogram descriptors to be delayed in any case.
4875 -- Set to encode entity names in package spec before gigi is called
4877 Qualify_Entity_Names (N);
4879 if Ekind (Id) /= E_Generic_Package
4880 and then not Delay_Cleanups (Id)
4881 then
4882 Build_Finalizer
4883 (N => N,
4884 Clean_Stmts => No_List,
4885 Mark_Id => Empty,
4886 Top_Decls => No_List,
4887 Defer_Abort => False,
4888 Fin_Id => Fin_Id);
4890 if Present (Fin_Id) then
4891 Set_Finalizer (Id, Fin_Id);
4892 end if;
4893 end if;
4895 -- If this is a library-level package and unnesting is enabled,
4896 -- check for the presence of blocks with nested subprograms occurring
4897 -- in elaboration code, and generate procedures to encapsulate the
4898 -- blocks in case the nested subprograms make up-level references.
4900 if Unnest_Subprogram_Mode
4901 and then Is_Library_Level_Entity (Current_Scope)
4902 then
4903 Check_Unnesting_In_Decls_Or_Stmts (Visible_Declarations (Spec));
4904 Check_Unnesting_In_Decls_Or_Stmts (Private_Declarations (Spec));
4905 end if;
4906 end Expand_N_Package_Declaration;
4908 ---------------------------------
4909 -- Has_Simple_Protected_Object --
4910 ---------------------------------
4912 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4913 begin
4914 if Has_Task (T) then
4915 return False;
4917 elsif Is_Simple_Protected_Type (T) then
4918 return True;
4920 elsif Is_Array_Type (T) then
4921 return Has_Simple_Protected_Object (Component_Type (T));
4923 elsif Is_Record_Type (T) then
4924 declare
4925 Comp : Entity_Id;
4927 begin
4928 Comp := First_Component (T);
4929 while Present (Comp) loop
4930 if Has_Simple_Protected_Object (Etype (Comp)) then
4931 return True;
4932 end if;
4934 Next_Component (Comp);
4935 end loop;
4937 return False;
4938 end;
4940 else
4941 return False;
4942 end if;
4943 end Has_Simple_Protected_Object;
4945 ------------------------------------
4946 -- Insert_Actions_In_Scope_Around --
4947 ------------------------------------
4949 procedure Insert_Actions_In_Scope_Around
4950 (N : Node_Id;
4951 Clean : Boolean;
4952 Manage_SS : Boolean)
4954 Act_Before : constant List_Id :=
4955 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Before);
4956 Act_After : constant List_Id :=
4957 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (After);
4958 Act_Cleanup : constant List_Id :=
4959 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup);
4960 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
4961 -- Last), but this was incorrect as Process_Transients_In_Scope may
4962 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
4964 procedure Process_Transients_In_Scope
4965 (First_Object : Node_Id;
4966 Last_Object : Node_Id;
4967 Related_Node : Node_Id);
4968 -- Find all transient objects in the list First_Object .. Last_Object
4969 -- and generate finalization actions for them. Related_Node denotes the
4970 -- node which created all transient objects.
4972 ---------------------------------
4973 -- Process_Transients_In_Scope --
4974 ---------------------------------
4976 procedure Process_Transients_In_Scope
4977 (First_Object : Node_Id;
4978 Last_Object : Node_Id;
4979 Related_Node : Node_Id)
4981 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result;
4982 -- Return Abandon if arbitrary node denotes a subprogram call
4984 function Has_Subprogram_Call is
4985 new Traverse_Func (Is_Subprogram_Call);
4987 procedure Process_Transient_In_Scope
4988 (Obj_Decl : Node_Id;
4989 Insert_Nod : Node_Id;
4990 Must_Export : Boolean);
4991 -- Generate finalization actions for a single transient object
4992 -- denoted by object declaration Obj_Decl.
4994 ------------------------
4995 -- Is_Subprogram_Call --
4996 ------------------------
4998 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result is
4999 begin
5000 -- A regular procedure or function call
5002 if Nkind (N) in N_Subprogram_Call then
5003 return Abandon;
5005 -- Special cases
5007 -- Heavy expansion may relocate function calls outside the related
5008 -- node. Inspect the original node to detect the initial placement
5009 -- of the call.
5011 elsif Is_Rewrite_Substitution (N) then
5012 return Has_Subprogram_Call (Original_Node (N));
5014 -- Generalized indexing always involves a function call
5016 elsif Nkind (N) = N_Indexed_Component
5017 and then Present (Generalized_Indexing (N))
5018 then
5019 return Abandon;
5021 -- Keep searching
5023 else
5024 return OK;
5025 end if;
5026 end Is_Subprogram_Call;
5028 --------------------------------
5029 -- Process_Transient_In_Scope --
5030 --------------------------------
5032 procedure Process_Transient_In_Scope
5033 (Obj_Decl : Node_Id;
5034 Insert_Nod : Node_Id;
5035 Must_Export : Boolean)
5037 Loc : constant Source_Ptr := Sloc (Obj_Decl);
5038 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
5040 Master_Node_Id : Entity_Id;
5041 Master_Node_Decl : Node_Id;
5042 Obj_Ref : Node_Id;
5043 Obj_Typ : Entity_Id;
5045 begin
5046 -- If the object needs to be exported to the outer finalizer,
5047 -- create the declaration of the Master_Node for the object,
5048 -- which will later be picked up by Build_Finalizer.
5050 if Must_Export then
5051 Master_Node_Id := Make_Temporary (Loc, 'N');
5052 Master_Node_Decl :=
5053 Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj_Id);
5054 Insert_Before_And_Analyze (Obj_Decl, Master_Node_Decl);
5056 -- Generate the attachment of the object to the Master_Node
5058 Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id);
5060 -- Then add the finalization call for the object
5062 Insert_After_And_Analyze (Insert_Nod,
5063 Make_Procedure_Call_Statement (Loc,
5064 Name =>
5065 New_Occurrence_Of (RTE (RE_Finalize_Object), Loc),
5066 Parameter_Associations => New_List (
5067 New_Occurrence_Of (Master_Node_Id, Loc))));
5069 -- Otherwise generate a direct finalization call for the object
5071 else
5072 -- Handle the object type and the reference to the object
5074 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
5075 Obj_Typ := Base_Type (Etype (Obj_Id));
5077 if Is_Access_Type (Obj_Typ) then
5078 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
5079 Obj_Typ := Available_View (Designated_Type (Obj_Typ));
5080 end if;
5082 Insert_After_And_Analyze (Insert_Nod,
5083 Make_Final_Call (Obj_Ref => Obj_Ref, Typ => Obj_Typ));
5084 end if;
5086 -- Mark the transient object to avoid double finalization
5088 Set_Is_Finalized_Transient (Obj_Id);
5089 end Process_Transient_In_Scope;
5091 -- Local variables
5093 Insert_Nod : Node_Id;
5094 -- Insertion node for the finalization actions
5096 Must_Export : Boolean;
5097 -- Flag denoting whether the context requires transient object
5098 -- export to the outer finalizer.
5100 Obj_Decl : Node_Id;
5102 -- Start of processing for Process_Transients_In_Scope
5104 begin
5105 -- The expansion performed by this routine is as follows:
5107 -- Ctrl_Trans_Obj_1MN : Master_Node;
5108 -- Ctrl_Trans_Obj_1 : ...;
5109 -- . . .
5110 -- Ctrl_Trans_Obj_NMN : Master_Node;
5111 -- Ctrl_Trans_Obj_N : ...;
5113 -- Finalize_Object (Ctrl_Trans_Obj_NMN);
5114 -- . . .
5115 -- Finalize_Object (Ctrl_Trans_Obj_1MN);
5117 -- Recognize a scenario where the transient context is an object
5118 -- declaration initialized by a build-in-place function call:
5120 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
5122 -- The rough expansion of the above is:
5124 -- Temp : ... := Ctrl_Func_Call;
5125 -- Obj : ...;
5126 -- Res : ... := BIP_Func_Call (..., Obj, ...);
5128 -- The finalization of any transient object must happen after the
5129 -- build-in-place function call is executed.
5131 if Nkind (N) = N_Object_Declaration
5132 and then Present (BIP_Initialization_Call (Defining_Identifier (N)))
5133 then
5134 Must_Export := True;
5135 Insert_Nod := BIP_Initialization_Call (Defining_Identifier (N));
5137 -- Search the context for at least one subprogram call. If found, the
5138 -- machinery exports all transient objects to the enclosing finalizer
5139 -- due to the possibility of abnormal call termination.
5141 else
5142 Must_Export := Has_Subprogram_Call (N) = Abandon;
5143 Insert_Nod := Last_Object;
5144 end if;
5146 Insert_List_After_And_Analyze (Insert_Nod, Act_Cleanup);
5148 -- Examine all the objects in the list First_Object .. Last_Object
5149 -- but skip the node to be wrapped because it is not transient as
5150 -- far as this scope is concerned.
5152 Obj_Decl := First_Object;
5153 while Present (Obj_Decl) loop
5154 if Obj_Decl /= Related_Node
5155 and then Nkind (Obj_Decl) = N_Object_Declaration
5156 and then Analyzed (Obj_Decl)
5157 and then Is_Finalizable_Transient (Obj_Decl, N)
5158 then
5159 Process_Transient_In_Scope (Obj_Decl, Insert_Nod, Must_Export);
5160 end if;
5162 exit when Obj_Decl = Last_Object;
5164 Next (Obj_Decl);
5165 end loop;
5166 end Process_Transients_In_Scope;
5168 -- Local variables
5170 Loc : constant Source_Ptr := Sloc (N);
5171 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
5172 First_Obj : Node_Id;
5173 Last_Obj : Node_Id;
5174 Mark_Id : Entity_Id;
5175 Target : Node_Id;
5177 -- Start of processing for Insert_Actions_In_Scope_Around
5179 begin
5180 -- Nothing to do if the scope does not manage the secondary stack or
5181 -- does not contain meaningful actions for insertion.
5183 if not Manage_SS
5184 and then No (Act_Before)
5185 and then No (Act_After)
5186 and then No (Act_Cleanup)
5187 then
5188 return;
5189 end if;
5191 -- If the node to be wrapped is the trigger of an asynchronous select,
5192 -- it is not part of a statement list. The actions must be inserted
5193 -- before the select itself, which is part of some list of statements.
5194 -- Note that the triggering alternative includes the triggering
5195 -- statement and an optional statement list. If the node to be
5196 -- wrapped is part of that list, the normal insertion applies.
5198 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
5199 and then not Is_List_Member (Node_To_Wrap)
5200 then
5201 Target := Parent (Parent (Node_To_Wrap));
5202 else
5203 Target := N;
5204 end if;
5206 First_Obj := Target;
5207 Last_Obj := Target;
5209 -- Add all actions associated with a transient scope into the main tree.
5210 -- There are several scenarios here:
5212 -- +--- Before ----+ +----- After ---+
5213 -- 1) First_Obj ....... Target ........ Last_Obj
5215 -- 2) First_Obj ....... Target
5217 -- 3) Target ........ Last_Obj
5219 -- Flag declarations are inserted before the first object
5221 if Present (Act_Before) then
5222 First_Obj := First (Act_Before);
5223 Insert_List_Before (Target, Act_Before);
5224 end if;
5226 -- Finalization calls are inserted after the last object
5228 if Present (Act_After) then
5229 Last_Obj := Last (Act_After);
5230 Insert_List_After (Target, Act_After);
5231 end if;
5233 -- Mark and release the secondary stack when the context warrants it
5235 if Manage_SS then
5236 Mark_Id := Make_Temporary (Loc, 'M');
5238 -- Generate:
5239 -- Mnn : constant Mark_Id := SS_Mark;
5241 Insert_Before_And_Analyze
5242 (First_Obj, Build_SS_Mark_Call (Loc, Mark_Id));
5244 -- Generate:
5245 -- SS_Release (Mnn);
5247 Insert_After_And_Analyze
5248 (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
5249 end if;
5251 -- If we are handling cleanups, check for transient objects associated
5252 -- with Target and generate the required finalization actions for them.
5254 if Clean then
5255 Process_Transients_In_Scope
5256 (First_Object => First_Obj,
5257 Last_Object => Last_Obj,
5258 Related_Node => Target);
5259 end if;
5261 -- Reset the action lists
5263 Scope_Stack.Table
5264 (Scope_Stack.Last).Actions_To_Be_Wrapped (Before) := No_List;
5265 Scope_Stack.Table
5266 (Scope_Stack.Last).Actions_To_Be_Wrapped (After) := No_List;
5268 if Clean then
5269 Scope_Stack.Table
5270 (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup) := No_List;
5271 end if;
5272 end Insert_Actions_In_Scope_Around;
5274 ------------------------------
5275 -- Is_Simple_Protected_Type --
5276 ------------------------------
5278 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
5279 begin
5280 return
5281 Is_Protected_Type (T)
5282 and then not Uses_Lock_Free (T)
5283 and then not Has_Entries (T)
5284 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
5285 end Is_Simple_Protected_Type;
5287 -------------------------------
5288 -- Make_Address_For_Finalize --
5289 -------------------------------
5291 function Make_Address_For_Finalize
5292 (Loc : Source_Ptr;
5293 Obj_Ref : Node_Id;
5294 Obj_Typ : Entity_Id) return Node_Id
5296 Obj_Addr : Node_Id;
5298 begin
5299 Obj_Addr :=
5300 Make_Attribute_Reference (Loc,
5301 Prefix => Obj_Ref,
5302 Attribute_Name => Name_Address);
5304 -- If the type of a constrained array has an unconstrained first
5305 -- subtype, its Finalize_Address primitive expects the address of
5306 -- an object with a dope vector (see Make_Finalize_Address_Stmts).
5307 -- This is achieved by setting Is_Constr_Array_Subt_With_Bounds,
5308 -- but the address of the object is still that of its elements,
5309 -- so we need to shift it.
5311 if Is_Array_Type (Obj_Typ)
5312 and then not Is_Constrained (First_Subtype (Obj_Typ))
5313 then
5314 -- Shift the address from the start of the elements to the
5315 -- start of the dope vector:
5317 -- V - (Obj_Typ'Descriptor_Size / Storage_Unit)
5319 -- Note that this is done through a wrapper routine as RTSfind
5320 -- cannot retrieve operations with string name of the form "+".
5322 Obj_Addr :=
5323 Make_Function_Call (Loc,
5324 Name =>
5325 New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
5326 Parameter_Associations => New_List (
5327 Obj_Addr,
5328 Make_Op_Minus (Loc,
5329 Make_Op_Divide (Loc,
5330 Left_Opnd =>
5331 Make_Attribute_Reference (Loc,
5332 Prefix => New_Occurrence_Of (Obj_Typ, Loc),
5333 Attribute_Name => Name_Descriptor_Size),
5334 Right_Opnd =>
5335 Make_Integer_Literal (Loc, System_Storage_Unit)))));
5336 end if;
5338 return Obj_Addr;
5339 end Make_Address_For_Finalize;
5341 -----------------------
5342 -- Make_Adjust_Call --
5343 -----------------------
5345 function Make_Adjust_Call
5346 (Obj_Ref : Node_Id;
5347 Typ : Entity_Id;
5348 Skip_Self : Boolean := False) return Node_Id
5350 Loc : constant Source_Ptr := Sloc (Obj_Ref);
5351 Adj_Id : Entity_Id := Empty;
5352 Ref : Node_Id;
5353 Utyp : Entity_Id;
5355 begin
5356 Ref := Obj_Ref;
5358 -- Recover the proper type which contains Deep_Adjust
5360 if Is_Class_Wide_Type (Typ) then
5361 Utyp := Root_Type (Typ);
5362 else
5363 Utyp := Typ;
5364 end if;
5366 Utyp := Underlying_Type (Base_Type (Utyp));
5367 Set_Assignment_OK (Ref);
5369 -- Deal with untagged derivation of private views
5371 if Present (Utyp) and then Is_Untagged_Derivation (Typ) then
5372 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
5373 Ref := Unchecked_Convert_To (Utyp, Ref);
5374 Set_Assignment_OK (Ref);
5375 end if;
5377 -- When dealing with the completion of a private type, use the base
5378 -- type instead.
5380 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
5381 pragma Assert (Is_Private_Type (Typ));
5383 Utyp := Base_Type (Utyp);
5384 Ref := Unchecked_Convert_To (Utyp, Ref);
5385 end if;
5387 -- The underlying type may not be present due to a missing full view. In
5388 -- this case freezing did not take place and there is no [Deep_]Adjust
5389 -- primitive to call.
5391 if No (Utyp) then
5392 return Empty;
5394 elsif Skip_Self then
5395 if Has_Controlled_Component (Utyp) then
5396 if Is_Tagged_Type (Utyp) then
5397 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
5398 else
5399 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
5400 end if;
5401 end if;
5403 -- Class-wide types, interfaces and types with controlled components
5405 elsif Is_Class_Wide_Type (Typ)
5406 or else Is_Interface (Typ)
5407 or else Has_Controlled_Component (Utyp)
5408 then
5409 if Is_Tagged_Type (Utyp) then
5410 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
5411 else
5412 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
5413 end if;
5415 -- Derivations from [Limited_]Controlled
5417 elsif Is_Controlled (Utyp) then
5418 Adj_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Adjust_Case));
5420 -- Tagged types
5422 elsif Is_Tagged_Type (Utyp) then
5423 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
5425 else
5426 raise Program_Error;
5427 end if;
5429 if Present (Adj_Id) then
5431 -- If the object is unanalyzed, set its expected type for use in
5432 -- Convert_View in case an additional conversion is needed.
5434 if No (Etype (Ref))
5435 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
5436 then
5437 Set_Etype (Ref, Typ);
5438 end if;
5440 -- The object reference may need another conversion depending on the
5441 -- type of the formal and that of the actual.
5443 if not Is_Class_Wide_Type (Typ) then
5444 Ref := Convert_View (Adj_Id, Ref);
5445 end if;
5447 return
5448 Make_Call (Loc,
5449 Proc_Id => Adj_Id,
5450 Param => Ref,
5451 Skip_Self => Skip_Self);
5452 else
5453 return Empty;
5454 end if;
5455 end Make_Adjust_Call;
5457 ---------------
5458 -- Make_Call --
5459 ---------------
5461 function Make_Call
5462 (Loc : Source_Ptr;
5463 Proc_Id : Entity_Id;
5464 Param : Node_Id;
5465 Skip_Self : Boolean := False) return Node_Id
5467 Params : constant List_Id := New_List (Param);
5469 begin
5470 -- Do not apply the controlled action to the object itself by signaling
5471 -- the related routine to avoid self.
5473 if Skip_Self then
5474 Append_To (Params, New_Occurrence_Of (Standard_False, Loc));
5475 end if;
5477 return
5478 Make_Procedure_Call_Statement (Loc,
5479 Name => New_Occurrence_Of (Proc_Id, Loc),
5480 Parameter_Associations => Params);
5481 end Make_Call;
5483 --------------------------
5484 -- Make_Deep_Array_Body --
5485 --------------------------
5487 function Make_Deep_Array_Body
5488 (Prim : Final_Primitives;
5489 Typ : Entity_Id) return List_Id
5491 function Build_Adjust_Or_Finalize_Statements
5492 (Typ : Entity_Id) return List_Id;
5493 -- Create the statements necessary to adjust or finalize an array of
5494 -- controlled elements. Generate:
5496 -- declare
5497 -- Abort : constant Boolean := Triggered_By_Abort;
5498 -- <or>
5499 -- Abort : constant Boolean := False; -- no abort
5501 -- E : Exception_Occurrence;
5502 -- Raised : Boolean := False;
5504 -- begin
5505 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
5506 -- ^-- in the finalization case
5507 -- ...
5508 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
5509 -- begin
5510 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
5512 -- exception
5513 -- when others =>
5514 -- if not Raised then
5515 -- Raised := True;
5516 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5517 -- end if;
5518 -- end;
5519 -- end loop;
5520 -- ...
5521 -- end loop;
5523 -- if Raised and then not Abort then
5524 -- Raise_From_Controlled_Operation (E);
5525 -- end if;
5526 -- end;
5528 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
5529 -- Create the statements necessary to initialize an array of controlled
5530 -- elements. Include a mechanism to carry out partial finalization if an
5531 -- exception occurs. Generate:
5533 -- declare
5534 -- Counter : Integer := 0;
5536 -- begin
5537 -- for J1 in V'Range (1) loop
5538 -- ...
5539 -- for JN in V'Range (N) loop
5540 -- begin
5541 -- [Deep_]Initialize (V (J1, ..., JN));
5543 -- Counter := Counter + 1;
5545 -- exception
5546 -- when others =>
5547 -- declare
5548 -- Abort : constant Boolean := Triggered_By_Abort;
5549 -- <or>
5550 -- Abort : constant Boolean := False; -- no abort
5551 -- E : Exception_Occurrence;
5552 -- Raised : Boolean := False;
5554 -- begin
5555 -- Counter :=
5556 -- V'Length (1) *
5557 -- V'Length (2) *
5558 -- ...
5559 -- V'Length (N) - Counter;
5561 -- for F1 in reverse V'Range (1) loop
5562 -- ...
5563 -- for FN in reverse V'Range (N) loop
5564 -- if Counter > 0 then
5565 -- Counter := Counter - 1;
5566 -- else
5567 -- begin
5568 -- [Deep_]Finalize (V (F1, ..., FN));
5570 -- exception
5571 -- when others =>
5572 -- if not Raised then
5573 -- Raised := True;
5574 -- Save_Occurrence (E,
5575 -- Get_Current_Excep.all.all);
5576 -- end if;
5577 -- end;
5578 -- end if;
5579 -- end loop;
5580 -- ...
5581 -- end loop;
5582 -- end;
5584 -- if Raised and then not Abort then
5585 -- Raise_From_Controlled_Operation (E);
5586 -- end if;
5588 -- raise;
5589 -- end;
5590 -- end loop;
5591 -- end loop;
5592 -- end;
5594 function New_References_To
5595 (L : List_Id;
5596 Loc : Source_Ptr) return List_Id;
5597 -- Given a list of defining identifiers, return a list of references to
5598 -- the original identifiers, in the same order as they appear.
5600 -----------------------------------------
5601 -- Build_Adjust_Or_Finalize_Statements --
5602 -----------------------------------------
5604 function Build_Adjust_Or_Finalize_Statements
5605 (Typ : Entity_Id) return List_Id
5607 Comp_Typ : constant Entity_Id := Component_Type (Typ);
5608 Index_List : constant List_Id := New_List;
5609 Loc : constant Source_Ptr := Sloc (Typ);
5610 Num_Dims : constant Int := Number_Dimensions (Typ);
5612 procedure Build_Indexes;
5613 -- Generate the indexes used in the dimension loops
5615 -------------------
5616 -- Build_Indexes --
5617 -------------------
5619 procedure Build_Indexes is
5620 begin
5621 -- Generate the following identifiers:
5622 -- Jnn - for initialization
5624 for Dim in 1 .. Num_Dims loop
5625 Append_To (Index_List,
5626 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5627 end loop;
5628 end Build_Indexes;
5630 -- Local variables
5632 Final_Decls : List_Id := No_List;
5633 Final_Data : Finalization_Exception_Data;
5634 Block : Node_Id;
5635 Call : Node_Id;
5636 Comp_Ref : Node_Id;
5637 Core_Loop : Node_Id;
5638 Dim : Int;
5639 J : Entity_Id;
5640 Loop_Id : Entity_Id;
5641 Stmts : List_Id;
5643 -- Start of processing for Build_Adjust_Or_Finalize_Statements
5645 begin
5646 Final_Decls := New_List;
5648 Build_Indexes;
5649 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
5651 Comp_Ref :=
5652 Make_Indexed_Component (Loc,
5653 Prefix => Make_Identifier (Loc, Name_V),
5654 Expressions => New_References_To (Index_List, Loc));
5655 Set_Etype (Comp_Ref, Comp_Typ);
5657 -- Generate:
5658 -- [Deep_]Adjust (V (J1, ..., JN))
5660 if Prim = Adjust_Case then
5661 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5663 -- Generate:
5664 -- [Deep_]Finalize (V (J1, ..., JN))
5666 else pragma Assert (Prim = Finalize_Case);
5667 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5668 end if;
5670 if Present (Call) then
5672 -- Generate the block which houses the adjust or finalize call:
5674 -- begin
5675 -- <adjust or finalize call>
5677 -- exception
5678 -- when others =>
5679 -- if not Raised then
5680 -- Raised := True;
5681 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5682 -- end if;
5683 -- end;
5685 if Exceptions_OK then
5686 Core_Loop :=
5687 Make_Block_Statement (Loc,
5688 Handled_Statement_Sequence =>
5689 Make_Handled_Sequence_Of_Statements (Loc,
5690 Statements => New_List (Call),
5691 Exception_Handlers => New_List (
5692 Build_Exception_Handler (Final_Data))));
5693 else
5694 Core_Loop := Call;
5695 end if;
5697 -- Generate the dimension loops starting from the innermost one
5699 -- for Jnn in [reverse] V'Range (Dim) loop
5700 -- <core loop>
5701 -- end loop;
5703 J := Last (Index_List);
5704 Dim := Num_Dims;
5705 while Present (J) and then Dim > 0 loop
5706 Loop_Id := J;
5707 Prev (J);
5708 Remove (Loop_Id);
5710 Core_Loop :=
5711 Make_Loop_Statement (Loc,
5712 Iteration_Scheme =>
5713 Make_Iteration_Scheme (Loc,
5714 Loop_Parameter_Specification =>
5715 Make_Loop_Parameter_Specification (Loc,
5716 Defining_Identifier => Loop_Id,
5717 Discrete_Subtype_Definition =>
5718 Make_Attribute_Reference (Loc,
5719 Prefix => Make_Identifier (Loc, Name_V),
5720 Attribute_Name => Name_Range,
5721 Expressions => New_List (
5722 Make_Integer_Literal (Loc, Dim))),
5724 Reverse_Present =>
5725 Prim = Finalize_Case)),
5727 Statements => New_List (Core_Loop),
5728 End_Label => Empty);
5730 Dim := Dim - 1;
5731 end loop;
5733 -- Generate the block which contains the core loop, declarations
5734 -- of the abort flag, the exception occurrence, the raised flag
5735 -- and the conditional raise:
5737 -- declare
5738 -- Abort : constant Boolean := Triggered_By_Abort;
5739 -- <or>
5740 -- Abort : constant Boolean := False; -- no abort
5742 -- E : Exception_Occurrence;
5743 -- Raised : Boolean := False;
5745 -- begin
5746 -- <core loop>
5748 -- if Raised and then not Abort then
5749 -- Raise_From_Controlled_Operation (E);
5750 -- end if;
5751 -- end;
5753 Stmts := New_List (Core_Loop);
5755 if Exceptions_OK then
5756 Append_To (Stmts, Build_Raise_Statement (Final_Data));
5757 end if;
5759 Block :=
5760 Make_Block_Statement (Loc,
5761 Declarations => Final_Decls,
5762 Handled_Statement_Sequence =>
5763 Make_Handled_Sequence_Of_Statements (Loc,
5764 Statements => Stmts));
5766 -- Otherwise previous errors or a missing full view may prevent the
5767 -- proper freezing of the component type. If this is the case, there
5768 -- is no [Deep_]Adjust or [Deep_]Finalize primitive to call.
5770 else
5771 Block := Make_Null_Statement (Loc);
5772 end if;
5774 return New_List (Block);
5775 end Build_Adjust_Or_Finalize_Statements;
5777 ---------------------------------
5778 -- Build_Initialize_Statements --
5779 ---------------------------------
5781 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
5782 Comp_Typ : constant Entity_Id := Component_Type (Typ);
5783 Final_List : constant List_Id := New_List;
5784 Index_List : constant List_Id := New_List;
5785 Loc : constant Source_Ptr := Sloc (Typ);
5786 Num_Dims : constant Int := Number_Dimensions (Typ);
5788 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id;
5789 -- Generate the following assignment:
5790 -- Counter := V'Length (1) *
5791 -- ...
5792 -- V'Length (N) - Counter;
5794 -- Counter_Id denotes the entity of the counter.
5796 function Build_Finalization_Call return Node_Id;
5797 -- Generate a deep finalization call for an array element
5799 procedure Build_Indexes;
5800 -- Generate the initialization and finalization indexes used in the
5801 -- dimension loops.
5803 function Build_Initialization_Call return Node_Id;
5804 -- Generate a deep initialization call for an array element
5806 ----------------------
5807 -- Build_Assignment --
5808 ----------------------
5810 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id is
5811 Dim : Int;
5812 Expr : Node_Id;
5814 begin
5815 -- Start from the first dimension and generate:
5816 -- V'Length (1)
5818 Dim := 1;
5819 Expr :=
5820 Make_Attribute_Reference (Loc,
5821 Prefix => Make_Identifier (Loc, Name_V),
5822 Attribute_Name => Name_Length,
5823 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
5825 -- Process the rest of the dimensions, generate:
5826 -- Expr * V'Length (N)
5828 Dim := Dim + 1;
5829 while Dim <= Num_Dims loop
5830 Expr :=
5831 Make_Op_Multiply (Loc,
5832 Left_Opnd => Expr,
5833 Right_Opnd =>
5834 Make_Attribute_Reference (Loc,
5835 Prefix => Make_Identifier (Loc, Name_V),
5836 Attribute_Name => Name_Length,
5837 Expressions => New_List (
5838 Make_Integer_Literal (Loc, Dim))));
5840 Dim := Dim + 1;
5841 end loop;
5843 -- Generate:
5844 -- Counter := Expr - Counter;
5846 return
5847 Make_Assignment_Statement (Loc,
5848 Name => New_Occurrence_Of (Counter_Id, Loc),
5849 Expression =>
5850 Make_Op_Subtract (Loc,
5851 Left_Opnd => Expr,
5852 Right_Opnd => New_Occurrence_Of (Counter_Id, Loc)));
5853 end Build_Assignment;
5855 -----------------------------
5856 -- Build_Finalization_Call --
5857 -----------------------------
5859 function Build_Finalization_Call return Node_Id is
5860 Comp_Ref : constant Node_Id :=
5861 Make_Indexed_Component (Loc,
5862 Prefix => Make_Identifier (Loc, Name_V),
5863 Expressions => New_References_To (Final_List, Loc));
5865 begin
5866 Set_Etype (Comp_Ref, Comp_Typ);
5868 -- Generate:
5869 -- [Deep_]Finalize (V);
5871 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5872 end Build_Finalization_Call;
5874 -------------------
5875 -- Build_Indexes --
5876 -------------------
5878 procedure Build_Indexes is
5879 begin
5880 -- Generate the following identifiers:
5881 -- Jnn - for initialization
5882 -- Fnn - for finalization
5884 for Dim in 1 .. Num_Dims loop
5885 Append_To (Index_List,
5886 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5888 Append_To (Final_List,
5889 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5890 end loop;
5891 end Build_Indexes;
5893 -------------------------------
5894 -- Build_Initialization_Call --
5895 -------------------------------
5897 function Build_Initialization_Call return Node_Id is
5898 Comp_Ref : constant Node_Id :=
5899 Make_Indexed_Component (Loc,
5900 Prefix => Make_Identifier (Loc, Name_V),
5901 Expressions => New_References_To (Index_List, Loc));
5903 begin
5904 Set_Etype (Comp_Ref, Comp_Typ);
5906 -- Generate:
5907 -- [Deep_]Initialize (V (J1, ..., JN));
5909 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5910 end Build_Initialization_Call;
5912 -- Local variables
5914 Counter_Id : Entity_Id;
5915 Dim : Int;
5916 F : Node_Id;
5917 Fin_Stmt : Node_Id;
5918 Final_Block : Node_Id;
5919 Final_Data : Finalization_Exception_Data;
5920 Final_Decls : List_Id := No_List;
5921 Final_Loop : Node_Id;
5922 Init_Block : Node_Id;
5923 Init_Call : Node_Id;
5924 Init_Loop : Node_Id;
5925 J : Node_Id;
5926 Loop_Id : Node_Id;
5927 Stmts : List_Id;
5929 -- Start of processing for Build_Initialize_Statements
5931 begin
5932 Counter_Id := Make_Temporary (Loc, 'C');
5933 Final_Decls := New_List;
5935 Build_Indexes;
5936 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
5938 -- Generate the block which houses the finalization call, the index
5939 -- guard and the handler which triggers Program_Error later on.
5941 -- if Counter > 0 then
5942 -- Counter := Counter - 1;
5943 -- else
5944 -- begin
5945 -- [Deep_]Finalize (V (F1, ..., FN));
5946 -- exception
5947 -- when others =>
5948 -- if not Raised then
5949 -- Raised := True;
5950 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5951 -- end if;
5952 -- end;
5953 -- end if;
5955 Fin_Stmt := Build_Finalization_Call;
5957 if Present (Fin_Stmt) then
5958 if Exceptions_OK then
5959 Fin_Stmt :=
5960 Make_Block_Statement (Loc,
5961 Handled_Statement_Sequence =>
5962 Make_Handled_Sequence_Of_Statements (Loc,
5963 Statements => New_List (Fin_Stmt),
5964 Exception_Handlers => New_List (
5965 Build_Exception_Handler (Final_Data))));
5966 end if;
5968 -- This is the core of the loop, the dimension iterators are added
5969 -- one by one in reverse.
5971 Final_Loop :=
5972 Make_If_Statement (Loc,
5973 Condition =>
5974 Make_Op_Gt (Loc,
5975 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
5976 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5978 Then_Statements => New_List (
5979 Make_Assignment_Statement (Loc,
5980 Name => New_Occurrence_Of (Counter_Id, Loc),
5981 Expression =>
5982 Make_Op_Subtract (Loc,
5983 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
5984 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5986 Else_Statements => New_List (Fin_Stmt));
5988 -- Generate all finalization loops starting from the innermost
5989 -- dimension.
5991 -- for Fnn in reverse V'Range (Dim) loop
5992 -- <final loop>
5993 -- end loop;
5995 F := Last (Final_List);
5996 Dim := Num_Dims;
5997 while Present (F) and then Dim > 0 loop
5998 Loop_Id := F;
5999 Prev (F);
6000 Remove (Loop_Id);
6002 Final_Loop :=
6003 Make_Loop_Statement (Loc,
6004 Iteration_Scheme =>
6005 Make_Iteration_Scheme (Loc,
6006 Loop_Parameter_Specification =>
6007 Make_Loop_Parameter_Specification (Loc,
6008 Defining_Identifier => Loop_Id,
6009 Discrete_Subtype_Definition =>
6010 Make_Attribute_Reference (Loc,
6011 Prefix => Make_Identifier (Loc, Name_V),
6012 Attribute_Name => Name_Range,
6013 Expressions => New_List (
6014 Make_Integer_Literal (Loc, Dim))),
6016 Reverse_Present => True)),
6018 Statements => New_List (Final_Loop),
6019 End_Label => Empty);
6021 Dim := Dim - 1;
6022 end loop;
6024 -- Generate the block which contains the finalization loops, the
6025 -- declarations of the abort flag, the exception occurrence, the
6026 -- raised flag and the conditional raise.
6028 -- declare
6029 -- Abort : constant Boolean := Triggered_By_Abort;
6030 -- <or>
6031 -- Abort : constant Boolean := False; -- no abort
6033 -- E : Exception_Occurrence;
6034 -- Raised : Boolean := False;
6036 -- begin
6037 -- Counter :=
6038 -- V'Length (1) *
6039 -- ...
6040 -- V'Length (N) - Counter;
6042 -- <final loop>
6044 -- if Raised and then not Abort then
6045 -- Raise_From_Controlled_Operation (E);
6046 -- end if;
6048 -- raise;
6049 -- end;
6051 Stmts := New_List (Build_Assignment (Counter_Id), Final_Loop);
6053 if Exceptions_OK then
6054 Append_To (Stmts, Build_Raise_Statement (Final_Data));
6055 Append_To (Stmts, Make_Raise_Statement (Loc));
6056 end if;
6058 Final_Block :=
6059 Make_Block_Statement (Loc,
6060 Declarations => Final_Decls,
6061 Handled_Statement_Sequence =>
6062 Make_Handled_Sequence_Of_Statements (Loc,
6063 Statements => Stmts));
6065 -- Otherwise previous errors or a missing full view may prevent the
6066 -- proper freezing of the component type. If this is the case, there
6067 -- is no [Deep_]Finalize primitive to call.
6069 else
6070 Final_Block := Make_Null_Statement (Loc);
6071 end if;
6073 -- Generate the block which contains the initialization call and
6074 -- the partial finalization code.
6076 -- begin
6077 -- [Deep_]Initialize (V (J1, ..., JN));
6079 -- Counter := Counter + 1;
6081 -- exception
6082 -- when others =>
6083 -- <finalization code>
6084 -- end;
6086 Init_Call := Build_Initialization_Call;
6088 -- Only create finalization block if there is a nontrivial call
6089 -- to initialization or a Default_Initial_Condition check to be
6090 -- performed.
6092 if (Present (Init_Call)
6093 and then Nkind (Init_Call) /= N_Null_Statement)
6094 or else
6095 (Has_DIC (Comp_Typ)
6096 and then not GNATprove_Mode
6097 and then Present (DIC_Procedure (Comp_Typ))
6098 and then not Has_Null_Body (DIC_Procedure (Comp_Typ)))
6099 then
6100 declare
6101 Init_Stmts : constant List_Id := New_List;
6103 begin
6104 if Present (Init_Call) then
6105 Append_To (Init_Stmts, Init_Call);
6106 end if;
6108 if Has_DIC (Comp_Typ)
6109 and then Present (DIC_Procedure (Comp_Typ))
6110 then
6111 Append_To
6112 (Init_Stmts,
6113 Build_DIC_Call (Loc,
6114 Make_Indexed_Component (Loc,
6115 Prefix => Make_Identifier (Loc, Name_V),
6116 Expressions => New_References_To (Index_List, Loc)),
6117 Comp_Typ));
6118 end if;
6120 Init_Loop :=
6121 Make_Block_Statement (Loc,
6122 Handled_Statement_Sequence =>
6123 Make_Handled_Sequence_Of_Statements (Loc,
6124 Statements => Init_Stmts,
6125 Exception_Handlers => New_List (
6126 Make_Exception_Handler (Loc,
6127 Exception_Choices => New_List (
6128 Make_Others_Choice (Loc)),
6129 Statements => New_List (Final_Block)))));
6130 end;
6132 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
6133 Make_Assignment_Statement (Loc,
6134 Name => New_Occurrence_Of (Counter_Id, Loc),
6135 Expression =>
6136 Make_Op_Add (Loc,
6137 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
6138 Right_Opnd => Make_Integer_Literal (Loc, 1))));
6140 -- Generate all initialization loops starting from the innermost
6141 -- dimension.
6143 -- for Jnn in V'Range (Dim) loop
6144 -- <init loop>
6145 -- end loop;
6147 J := Last (Index_List);
6148 Dim := Num_Dims;
6149 while Present (J) and then Dim > 0 loop
6150 Loop_Id := J;
6151 Prev (J);
6152 Remove (Loop_Id);
6154 Init_Loop :=
6155 Make_Loop_Statement (Loc,
6156 Iteration_Scheme =>
6157 Make_Iteration_Scheme (Loc,
6158 Loop_Parameter_Specification =>
6159 Make_Loop_Parameter_Specification (Loc,
6160 Defining_Identifier => Loop_Id,
6161 Discrete_Subtype_Definition =>
6162 Make_Attribute_Reference (Loc,
6163 Prefix => Make_Identifier (Loc, Name_V),
6164 Attribute_Name => Name_Range,
6165 Expressions => New_List (
6166 Make_Integer_Literal (Loc, Dim))))),
6168 Statements => New_List (Init_Loop),
6169 End_Label => Empty);
6171 Dim := Dim - 1;
6172 end loop;
6174 -- Generate the block which contains the counter variable and the
6175 -- initialization loops.
6177 -- declare
6178 -- Counter : Integer := 0;
6179 -- begin
6180 -- <init loop>
6181 -- end;
6183 Init_Block :=
6184 Make_Block_Statement (Loc,
6185 Declarations => New_List (
6186 Make_Object_Declaration (Loc,
6187 Defining_Identifier => Counter_Id,
6188 Object_Definition =>
6189 New_Occurrence_Of (Standard_Integer, Loc),
6190 Expression => Make_Integer_Literal (Loc, 0))),
6192 Handled_Statement_Sequence =>
6193 Make_Handled_Sequence_Of_Statements (Loc,
6194 Statements => New_List (Init_Loop)));
6196 if Debug_Generated_Code then
6197 Set_Debug_Info_Needed (Counter_Id);
6198 end if;
6200 -- Otherwise previous errors or a missing full view may prevent the
6201 -- proper freezing of the component type. If this is the case, there
6202 -- is no [Deep_]Initialize primitive to call.
6204 else
6205 Init_Block := Make_Null_Statement (Loc);
6206 end if;
6208 return New_List (Init_Block);
6209 end Build_Initialize_Statements;
6211 -----------------------
6212 -- New_References_To --
6213 -----------------------
6215 function New_References_To
6216 (L : List_Id;
6217 Loc : Source_Ptr) return List_Id
6219 Refs : constant List_Id := New_List;
6220 Id : Node_Id;
6222 begin
6223 Id := First (L);
6224 while Present (Id) loop
6225 Append_To (Refs, New_Occurrence_Of (Id, Loc));
6226 Next (Id);
6227 end loop;
6229 return Refs;
6230 end New_References_To;
6232 -- Start of processing for Make_Deep_Array_Body
6234 begin
6235 case Prim is
6236 when Address_Case =>
6237 return Make_Finalize_Address_Stmts (Typ);
6239 when Adjust_Case
6240 | Finalize_Case
6242 return Build_Adjust_Or_Finalize_Statements (Typ);
6244 when Initialize_Case =>
6245 return Build_Initialize_Statements (Typ);
6246 end case;
6247 end Make_Deep_Array_Body;
6249 --------------------
6250 -- Make_Deep_Proc --
6251 --------------------
6253 function Make_Deep_Proc
6254 (Prim : Final_Primitives;
6255 Typ : Entity_Id;
6256 Stmts : List_Id) return Entity_Id
6258 Loc : constant Source_Ptr := Sloc (Typ);
6259 Formals : List_Id;
6260 Proc_Id : Entity_Id;
6262 begin
6263 -- Create the object formal, generate:
6264 -- V : System.Address
6266 if Prim = Address_Case then
6267 Formals := New_List (
6268 Make_Parameter_Specification (Loc,
6269 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
6270 Parameter_Type =>
6271 New_Occurrence_Of (RTE (RE_Address), Loc)));
6273 -- Default case
6275 else
6276 -- V : in out Typ
6278 Formals := New_List (
6279 Make_Parameter_Specification (Loc,
6280 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
6281 In_Present => True,
6282 Out_Present => True,
6283 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
6285 -- F : Boolean := True
6287 if Prim = Adjust_Case
6288 or else Prim = Finalize_Case
6289 then
6290 Append_To (Formals,
6291 Make_Parameter_Specification (Loc,
6292 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
6293 Parameter_Type =>
6294 New_Occurrence_Of (Standard_Boolean, Loc),
6295 Expression =>
6296 New_Occurrence_Of (Standard_True, Loc)));
6297 end if;
6298 end if;
6300 Proc_Id :=
6301 Make_Defining_Identifier (Loc,
6302 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
6304 -- Generate:
6305 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
6306 -- begin
6307 -- <stmts>
6308 -- exception -- Finalize and Adjust cases only
6309 -- raise Program_Error;
6310 -- end Deep_Initialize / Adjust / Finalize;
6312 -- or
6314 -- procedure Finalize_Address (V : System.Address) is
6315 -- begin
6316 -- <stmts>
6317 -- end Finalize_Address;
6319 Discard_Node (
6320 Make_Subprogram_Body (Loc,
6321 Specification =>
6322 Make_Procedure_Specification (Loc,
6323 Defining_Unit_Name => Proc_Id,
6324 Parameter_Specifications => Formals),
6326 Declarations => Empty_List,
6328 Handled_Statement_Sequence =>
6329 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
6331 -- If there are no calls to component initialization, indicate that
6332 -- the procedure is trivial, so prevent calls to it.
6334 if Is_Empty_List (Stmts)
6335 or else Nkind (First (Stmts)) = N_Null_Statement
6336 then
6337 Set_Is_Trivial_Subprogram (Proc_Id);
6338 end if;
6340 return Proc_Id;
6341 end Make_Deep_Proc;
6343 ---------------------------
6344 -- Make_Deep_Record_Body --
6345 ---------------------------
6347 function Make_Deep_Record_Body
6348 (Prim : Final_Primitives;
6349 Typ : Entity_Id;
6350 Is_Local : Boolean := False) return List_Id
6352 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
6353 -- Build the statements necessary to adjust a record type. The type may
6354 -- have discriminants and contain variant parts. Generate:
6356 -- begin
6357 -- begin
6358 -- [Deep_]Adjust (V.Comp_1);
6359 -- exception
6360 -- when Id : others =>
6361 -- if not Raised then
6362 -- Raised := True;
6363 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6364 -- end if;
6365 -- end;
6366 -- . . .
6367 -- begin
6368 -- [Deep_]Adjust (V.Comp_N);
6369 -- exception
6370 -- when Id : others =>
6371 -- if not Raised then
6372 -- Raised := True;
6373 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6374 -- end if;
6375 -- end;
6377 -- begin
6378 -- Deep_Adjust (V._parent, False); -- If applicable
6379 -- exception
6380 -- when Id : others =>
6381 -- if not Raised then
6382 -- Raised := True;
6383 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6384 -- end if;
6385 -- end;
6387 -- if F then
6388 -- begin
6389 -- Adjust (V); -- If applicable
6390 -- exception
6391 -- when others =>
6392 -- if not Raised then
6393 -- Raised := True;
6394 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6395 -- end if;
6396 -- end;
6397 -- end if;
6399 -- if Raised and then not Abort then
6400 -- Raise_From_Controlled_Operation (E);
6401 -- end if;
6402 -- end;
6404 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
6405 -- Build the statements necessary to finalize a record type. The type
6406 -- may have discriminants and contain variant parts. Generate:
6408 -- declare
6409 -- Abort : constant Boolean := Triggered_By_Abort;
6410 -- <or>
6411 -- Abort : constant Boolean := False; -- no abort
6412 -- E : Exception_Occurrence;
6413 -- Raised : Boolean := False;
6415 -- begin
6416 -- if F then
6417 -- begin
6418 -- Finalize (V); -- If applicable
6419 -- exception
6420 -- when others =>
6421 -- if not Raised then
6422 -- Raised := True;
6423 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6424 -- end if;
6425 -- end;
6426 -- end if;
6428 -- case Variant_1 is
6429 -- when Value_1 =>
6430 -- case State_Counter_N => -- If Is_Local is enabled
6431 -- when N => .
6432 -- goto LN; .
6433 -- ... .
6434 -- when 1 => .
6435 -- goto L1; .
6436 -- when others => .
6437 -- goto L0; .
6438 -- end case; .
6440 -- <<LN>> -- If Is_Local is enabled
6441 -- begin
6442 -- [Deep_]Finalize (V.Comp_N);
6443 -- exception
6444 -- when others =>
6445 -- if not Raised then
6446 -- Raised := True;
6447 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6448 -- end if;
6449 -- end;
6450 -- . . .
6451 -- <<L1>>
6452 -- begin
6453 -- [Deep_]Finalize (V.Comp_1);
6454 -- exception
6455 -- when others =>
6456 -- if not Raised then
6457 -- Raised := True;
6458 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6459 -- end if;
6460 -- end;
6461 -- <<L0>>
6462 -- end case;
6464 -- case State_Counter_1 => -- If Is_Local is enabled
6465 -- when M => .
6466 -- goto LM; .
6467 -- ...
6469 -- begin
6470 -- Deep_Finalize (V._parent, False); -- If applicable
6471 -- exception
6472 -- when Id : others =>
6473 -- if not Raised then
6474 -- Raised := True;
6475 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6476 -- end if;
6477 -- end;
6479 -- if Raised and then not Abort then
6480 -- Raise_From_Controlled_Operation (E);
6481 -- end if;
6482 -- end;
6484 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
6485 -- Given a derived tagged type Typ, traverse all components, find field
6486 -- _parent and return its type.
6488 procedure Preprocess_Components
6489 (Comps : Node_Id;
6490 Num_Comps : out Nat;
6491 Has_POC : out Boolean);
6492 -- Examine all components in component list Comps, count all controlled
6493 -- components and determine whether at least one of them is per-object
6494 -- constrained. Component _parent is always skipped.
6496 -----------------------------
6497 -- Build_Adjust_Statements --
6498 -----------------------------
6500 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
6501 Loc : constant Source_Ptr := Sloc (Typ);
6502 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6504 Finalizer_Data : Finalization_Exception_Data;
6506 function Process_Component_List_For_Adjust
6507 (Comps : Node_Id) return List_Id;
6508 -- Build all necessary adjust statements for a single component list
6510 ---------------------------------------
6511 -- Process_Component_List_For_Adjust --
6512 ---------------------------------------
6514 function Process_Component_List_For_Adjust
6515 (Comps : Node_Id) return List_Id
6517 Stmts : constant List_Id := New_List;
6519 procedure Process_Component_For_Adjust (Decl : Node_Id);
6520 -- Process the declaration of a single controlled component
6522 ----------------------------------
6523 -- Process_Component_For_Adjust --
6524 ----------------------------------
6526 procedure Process_Component_For_Adjust (Decl : Node_Id) is
6527 Id : constant Entity_Id := Defining_Identifier (Decl);
6528 Typ : constant Entity_Id := Etype (Id);
6530 Adj_Call : Node_Id;
6532 begin
6533 -- begin
6534 -- [Deep_]Adjust (V.Id);
6536 -- exception
6537 -- when others =>
6538 -- if not Raised then
6539 -- Raised := True;
6540 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6541 -- end if;
6542 -- end;
6544 Adj_Call :=
6545 Make_Adjust_Call (
6546 Obj_Ref =>
6547 Make_Selected_Component (Loc,
6548 Prefix => Make_Identifier (Loc, Name_V),
6549 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6550 Typ => Typ);
6552 -- Guard against a missing [Deep_]Adjust when the component
6553 -- type was not properly frozen.
6555 if Present (Adj_Call) then
6556 if Exceptions_OK then
6557 Adj_Call :=
6558 Make_Block_Statement (Loc,
6559 Handled_Statement_Sequence =>
6560 Make_Handled_Sequence_Of_Statements (Loc,
6561 Statements => New_List (Adj_Call),
6562 Exception_Handlers => New_List (
6563 Build_Exception_Handler (Finalizer_Data))));
6564 end if;
6566 Append_To (Stmts, Adj_Call);
6567 end if;
6568 end Process_Component_For_Adjust;
6570 -- Local variables
6572 Decl : Node_Id;
6573 Decl_Id : Entity_Id;
6574 Decl_Typ : Entity_Id;
6575 Has_POC : Boolean;
6576 Num_Comps : Nat;
6577 Var_Case : Node_Id;
6579 -- Start of processing for Process_Component_List_For_Adjust
6581 begin
6582 -- Perform an initial check, determine the number of controlled
6583 -- components in the current list and whether at least one of them
6584 -- is per-object constrained.
6586 Preprocess_Components (Comps, Num_Comps, Has_POC);
6588 -- The processing in this routine is done in the following order:
6589 -- 1) Regular components
6590 -- 2) Per-object constrained components
6591 -- 3) Variant parts
6593 if Num_Comps > 0 then
6595 -- Process all regular components in order of declarations
6597 Decl := First_Non_Pragma (Component_Items (Comps));
6598 while Present (Decl) loop
6599 Decl_Id := Defining_Identifier (Decl);
6600 Decl_Typ := Etype (Decl_Id);
6602 -- Skip _parent as well as per-object constrained components
6604 if Chars (Decl_Id) /= Name_uParent
6605 and then Needs_Finalization (Decl_Typ)
6606 then
6607 if Has_Access_Constraint (Decl_Id)
6608 and then No (Expression (Decl))
6609 then
6610 null;
6611 else
6612 Process_Component_For_Adjust (Decl);
6613 end if;
6614 end if;
6616 Next_Non_Pragma (Decl);
6617 end loop;
6619 -- Process all per-object constrained components in order of
6620 -- declarations.
6622 if Has_POC then
6623 Decl := First_Non_Pragma (Component_Items (Comps));
6624 while Present (Decl) loop
6625 Decl_Id := Defining_Identifier (Decl);
6626 Decl_Typ := Etype (Decl_Id);
6628 -- Skip _parent
6630 if Chars (Decl_Id) /= Name_uParent
6631 and then Needs_Finalization (Decl_Typ)
6632 and then Has_Access_Constraint (Decl_Id)
6633 and then No (Expression (Decl))
6634 then
6635 Process_Component_For_Adjust (Decl);
6636 end if;
6638 Next_Non_Pragma (Decl);
6639 end loop;
6640 end if;
6641 end if;
6643 -- Process all variants, if any
6645 Var_Case := Empty;
6646 if Present (Variant_Part (Comps)) then
6647 declare
6648 Var_Alts : constant List_Id := New_List;
6649 Var : Node_Id;
6651 begin
6652 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6653 while Present (Var) loop
6655 -- Generate:
6656 -- when <discrete choices> =>
6657 -- <adjust statements>
6659 Append_To (Var_Alts,
6660 Make_Case_Statement_Alternative (Loc,
6661 Discrete_Choices =>
6662 New_Copy_List (Discrete_Choices (Var)),
6663 Statements =>
6664 Process_Component_List_For_Adjust (
6665 Component_List (Var))));
6667 Next_Non_Pragma (Var);
6668 end loop;
6670 -- Generate:
6671 -- case V.<discriminant> is
6672 -- when <discrete choices 1> =>
6673 -- <adjust statements 1>
6674 -- ...
6675 -- when <discrete choices N> =>
6676 -- <adjust statements N>
6677 -- end case;
6679 Var_Case :=
6680 Make_Case_Statement (Loc,
6681 Expression =>
6682 Make_Selected_Component (Loc,
6683 Prefix => Make_Identifier (Loc, Name_V),
6684 Selector_Name =>
6685 Make_Identifier (Loc,
6686 Chars => Chars (Name (Variant_Part (Comps))))),
6687 Alternatives => Var_Alts);
6688 end;
6689 end if;
6691 -- Add the variant case statement to the list of statements
6693 if Present (Var_Case) then
6694 Append_To (Stmts, Var_Case);
6695 end if;
6697 -- If the component list did not have any controlled components
6698 -- nor variants, return null.
6700 if Is_Empty_List (Stmts) then
6701 Append_To (Stmts, Make_Null_Statement (Loc));
6702 end if;
6704 return Stmts;
6705 end Process_Component_List_For_Adjust;
6707 -- Local variables
6709 Bod_Stmts : List_Id := No_List;
6710 Finalizer_Decls : List_Id := No_List;
6711 Rec_Def : Node_Id;
6713 -- Start of processing for Build_Adjust_Statements
6715 begin
6716 Finalizer_Decls := New_List;
6717 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
6719 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6720 Rec_Def := Record_Extension_Part (Typ_Def);
6721 else
6722 Rec_Def := Typ_Def;
6723 end if;
6725 -- Create an adjust sequence for all record components
6727 if Present (Component_List (Rec_Def)) then
6728 Bod_Stmts :=
6729 Process_Component_List_For_Adjust (Component_List (Rec_Def));
6730 end if;
6732 -- A derived record type must adjust all inherited components. This
6733 -- action poses the following problem:
6735 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
6736 -- begin
6737 -- Adjust (Obj);
6738 -- ...
6740 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
6741 -- begin
6742 -- Deep_Adjust (Obj._parent);
6743 -- ...
6744 -- Adjust (Obj);
6745 -- ...
6747 -- Adjusting the derived type will invoke Adjust of the parent and
6748 -- then that of the derived type. This is undesirable because both
6749 -- routines may modify shared components. Only the Adjust of the
6750 -- derived type should be invoked.
6752 -- To prevent this double adjustment of shared components,
6753 -- Deep_Adjust uses a flag to control the invocation of Adjust:
6755 -- procedure Deep_Adjust
6756 -- (Obj : in out Some_Type;
6757 -- Flag : Boolean := True)
6758 -- is
6759 -- begin
6760 -- if Flag then
6761 -- Adjust (Obj);
6762 -- end if;
6763 -- ...
6765 -- When Deep_Adjust is invoked for field _parent, a value of False is
6766 -- provided for the flag:
6768 -- Deep_Adjust (Obj._parent, False);
6770 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
6771 declare
6772 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6773 Adj_Stmt : Node_Id;
6774 Call : Node_Id;
6776 begin
6777 if Needs_Finalization (Par_Typ) then
6778 Call :=
6779 Make_Adjust_Call
6780 (Obj_Ref =>
6781 Make_Selected_Component (Loc,
6782 Prefix => Make_Identifier (Loc, Name_V),
6783 Selector_Name =>
6784 Make_Identifier (Loc, Name_uParent)),
6785 Typ => Par_Typ,
6786 Skip_Self => True);
6788 -- Generate:
6789 -- begin
6790 -- Deep_Adjust (V._parent, False);
6792 -- exception
6793 -- when Id : others =>
6794 -- if not Raised then
6795 -- Raised := True;
6796 -- Save_Occurrence (E,
6797 -- Get_Current_Excep.all.all);
6798 -- end if;
6799 -- end;
6801 if Present (Call) then
6802 Adj_Stmt := Call;
6804 if Exceptions_OK then
6805 Adj_Stmt :=
6806 Make_Block_Statement (Loc,
6807 Handled_Statement_Sequence =>
6808 Make_Handled_Sequence_Of_Statements (Loc,
6809 Statements => New_List (Adj_Stmt),
6810 Exception_Handlers => New_List (
6811 Build_Exception_Handler (Finalizer_Data))));
6812 end if;
6814 Prepend_To (Bod_Stmts, Adj_Stmt);
6815 end if;
6816 end if;
6817 end;
6818 end if;
6820 -- Adjust the object. This action must be performed last after all
6821 -- components have been adjusted.
6823 if Is_Controlled (Typ) then
6824 declare
6825 Adj_Stmt : Node_Id;
6826 Proc : Entity_Id;
6828 begin
6829 Proc := Find_Optional_Prim_Op (Typ, Name_Adjust);
6831 -- Generate:
6832 -- if F then
6833 -- begin
6834 -- Adjust (V);
6836 -- exception
6837 -- when others =>
6838 -- if not Raised then
6839 -- Raised := True;
6840 -- Save_Occurrence (E,
6841 -- Get_Current_Excep.all.all);
6842 -- end if;
6843 -- end;
6844 -- end if;
6846 if Present (Proc) then
6847 Adj_Stmt :=
6848 Make_Procedure_Call_Statement (Loc,
6849 Name => New_Occurrence_Of (Proc, Loc),
6850 Parameter_Associations => New_List (
6851 Make_Identifier (Loc, Name_V)));
6853 if Exceptions_OK then
6854 Adj_Stmt :=
6855 Make_Block_Statement (Loc,
6856 Handled_Statement_Sequence =>
6857 Make_Handled_Sequence_Of_Statements (Loc,
6858 Statements => New_List (Adj_Stmt),
6859 Exception_Handlers => New_List (
6860 Build_Exception_Handler
6861 (Finalizer_Data))));
6862 end if;
6864 Append_To (Bod_Stmts,
6865 Make_If_Statement (Loc,
6866 Condition => Make_Identifier (Loc, Name_F),
6867 Then_Statements => New_List (Adj_Stmt)));
6868 end if;
6869 end;
6870 end if;
6872 -- At this point either all adjustment statements have been generated
6873 -- or the type is not controlled.
6875 if Is_Empty_List (Bod_Stmts) then
6876 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6878 return Bod_Stmts;
6880 -- Generate:
6881 -- declare
6882 -- Abort : constant Boolean := Triggered_By_Abort;
6883 -- <or>
6884 -- Abort : constant Boolean := False; -- no abort
6886 -- E : Exception_Occurrence;
6887 -- Raised : Boolean := False;
6889 -- begin
6890 -- <adjust statements>
6892 -- if Raised and then not Abort then
6893 -- Raise_From_Controlled_Operation (E);
6894 -- end if;
6895 -- end;
6897 else
6898 if Exceptions_OK then
6899 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
6900 end if;
6902 return
6903 New_List (
6904 Make_Block_Statement (Loc,
6905 Declarations =>
6906 Finalizer_Decls,
6907 Handled_Statement_Sequence =>
6908 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6909 end if;
6910 end Build_Adjust_Statements;
6912 -------------------------------
6913 -- Build_Finalize_Statements --
6914 -------------------------------
6916 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6917 Loc : constant Source_Ptr := Sloc (Typ);
6918 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6920 Counter : Nat := 0;
6921 Finalizer_Data : Finalization_Exception_Data;
6922 Last_POC_Call : Node_Id := Empty;
6924 function Process_Component_List_For_Finalize
6925 (Comps : Node_Id;
6926 In_Variant_Part : Boolean := False) return List_Id;
6927 -- Build all necessary finalization statements for a single component
6928 -- list. The statements may include a jump circuitry if flag Is_Local
6929 -- is enabled. In_Variant_Part indicates whether this is a recursive
6930 -- call.
6932 -----------------------------------------
6933 -- Process_Component_List_For_Finalize --
6934 -----------------------------------------
6936 function Process_Component_List_For_Finalize
6937 (Comps : Node_Id;
6938 In_Variant_Part : Boolean := False) return List_Id
6940 procedure Process_Component_For_Finalize
6941 (Decl : Node_Id;
6942 Alts : List_Id;
6943 Decls : List_Id;
6944 Stmts : List_Id;
6945 Num_Comps : in out Nat);
6946 -- Process the declaration of a single controlled component. If
6947 -- flag Is_Local is enabled, create the corresponding label and
6948 -- jump circuitry. Alts is the list of case alternatives, Decls
6949 -- is the top level declaration list where labels are declared
6950 -- and Stmts is the list of finalization actions. Num_Comps
6951 -- denotes the current number of components needing finalization.
6953 ------------------------------------
6954 -- Process_Component_For_Finalize --
6955 ------------------------------------
6957 procedure Process_Component_For_Finalize
6958 (Decl : Node_Id;
6959 Alts : List_Id;
6960 Decls : List_Id;
6961 Stmts : List_Id;
6962 Num_Comps : in out Nat)
6964 Id : constant Entity_Id := Defining_Identifier (Decl);
6965 Typ : constant Entity_Id := Etype (Id);
6966 Fin_Call : Node_Id;
6968 begin
6969 if Is_Local then
6970 declare
6971 Label : Node_Id;
6972 Label_Id : Entity_Id;
6974 begin
6975 -- Generate:
6976 -- LN : label;
6978 Label_Id :=
6979 Make_Identifier (Loc,
6980 Chars => New_External_Name ('L', Num_Comps));
6981 Set_Entity (Label_Id,
6982 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6983 Label := Make_Label (Loc, Label_Id);
6985 Append_To (Decls,
6986 Make_Implicit_Label_Declaration (Loc,
6987 Defining_Identifier => Entity (Label_Id),
6988 Label_Construct => Label));
6990 -- Generate:
6991 -- when N =>
6992 -- goto LN;
6994 Append_To (Alts,
6995 Make_Case_Statement_Alternative (Loc,
6996 Discrete_Choices => New_List (
6997 Make_Integer_Literal (Loc, Num_Comps)),
6999 Statements => New_List (
7000 Make_Goto_Statement (Loc,
7001 Name =>
7002 New_Occurrence_Of (Entity (Label_Id), Loc)))));
7004 -- Generate:
7005 -- <<LN>>
7007 Append_To (Stmts, Label);
7009 -- Decrease the number of components to be processed.
7010 -- This action yields a new Label_Id in future calls.
7012 Num_Comps := Num_Comps - 1;
7013 end;
7014 end if;
7016 -- Generate:
7017 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
7019 -- begin -- Exception handlers allowed
7020 -- [Deep_]Finalize (V.Id);
7021 -- exception
7022 -- when others =>
7023 -- if not Raised then
7024 -- Raised := True;
7025 -- Save_Occurrence (E,
7026 -- Get_Current_Excep.all.all);
7027 -- end if;
7028 -- end;
7030 Fin_Call :=
7031 Make_Final_Call
7032 (Obj_Ref =>
7033 Make_Selected_Component (Loc,
7034 Prefix => Make_Identifier (Loc, Name_V),
7035 Selector_Name => Make_Identifier (Loc, Chars (Id))),
7036 Typ => Typ);
7038 -- Guard against a missing [Deep_]Finalize when the component
7039 -- type was not properly frozen.
7041 if Present (Fin_Call) then
7042 if Exceptions_OK then
7043 Fin_Call :=
7044 Make_Block_Statement (Loc,
7045 Handled_Statement_Sequence =>
7046 Make_Handled_Sequence_Of_Statements (Loc,
7047 Statements => New_List (Fin_Call),
7048 Exception_Handlers => New_List (
7049 Build_Exception_Handler (Finalizer_Data))));
7050 end if;
7052 Append_To (Stmts, Fin_Call);
7053 end if;
7054 end Process_Component_For_Finalize;
7056 -- Local variables
7058 Alts : List_Id;
7059 Counter_Id : Entity_Id := Empty;
7060 Decl : Node_Id;
7061 Decl_Id : Entity_Id;
7062 Decl_Typ : Entity_Id;
7063 Decls : List_Id;
7064 Has_POC : Boolean;
7065 Jump_Block : Node_Id;
7066 Label : Node_Id;
7067 Label_Id : Entity_Id;
7068 Num_Comps : Nat;
7069 Stmts : List_Id;
7070 Var_Case : Node_Id;
7072 -- Start of processing for Process_Component_List_For_Finalize
7074 begin
7075 -- Perform an initial check, look for controlled and per-object
7076 -- constrained components.
7078 Preprocess_Components (Comps, Num_Comps, Has_POC);
7080 -- Create a state counter to service the current component list.
7081 -- This step is performed before the variants are inspected in
7082 -- order to generate the same state counter names as those from
7083 -- Build_Initialize_Statements.
7085 if Num_Comps > 0 and then Is_Local then
7086 Counter := Counter + 1;
7088 Counter_Id :=
7089 Make_Defining_Identifier (Loc,
7090 Chars => New_External_Name ('C', Counter));
7091 end if;
7093 -- Process the component in the following order:
7094 -- 1) Variants
7095 -- 2) Per-object constrained components
7096 -- 3) Regular components
7098 -- Start with the variant parts
7100 Var_Case := Empty;
7101 if Present (Variant_Part (Comps)) then
7102 declare
7103 Var_Alts : constant List_Id := New_List;
7104 Var : Node_Id;
7106 begin
7107 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
7108 while Present (Var) loop
7110 -- Generate:
7111 -- when <discrete choices> =>
7112 -- <finalize statements>
7114 Append_To (Var_Alts,
7115 Make_Case_Statement_Alternative (Loc,
7116 Discrete_Choices =>
7117 New_Copy_List (Discrete_Choices (Var)),
7118 Statements =>
7119 Process_Component_List_For_Finalize (
7120 Component_List (Var),
7121 In_Variant_Part => True)));
7123 Next_Non_Pragma (Var);
7124 end loop;
7126 -- Generate:
7127 -- case V.<discriminant> is
7128 -- when <discrete choices 1> =>
7129 -- <finalize statements 1>
7130 -- ...
7131 -- when <discrete choices N> =>
7132 -- <finalize statements N>
7133 -- end case;
7135 Var_Case :=
7136 Make_Case_Statement (Loc,
7137 Expression =>
7138 Make_Selected_Component (Loc,
7139 Prefix => Make_Identifier (Loc, Name_V),
7140 Selector_Name =>
7141 Make_Identifier (Loc,
7142 Chars => Chars (Name (Variant_Part (Comps))))),
7143 Alternatives => Var_Alts);
7144 end;
7145 end if;
7147 -- The current component list does not have a single controlled
7148 -- component, however it may contain variants. Return the case
7149 -- statement for the variants or nothing.
7151 if Num_Comps = 0 then
7152 if Present (Var_Case) then
7153 return New_List (Var_Case);
7154 else
7155 return New_List (Make_Null_Statement (Loc));
7156 end if;
7157 end if;
7159 -- Prepare all lists
7161 Alts := New_List;
7162 Decls := New_List;
7163 Stmts := New_List;
7165 -- Process all per-object constrained components in reverse order
7167 if Has_POC then
7168 Decl := Last_Non_Pragma (Component_Items (Comps));
7169 while Present (Decl) loop
7170 Decl_Id := Defining_Identifier (Decl);
7171 Decl_Typ := Etype (Decl_Id);
7173 -- Skip _parent
7175 if Chars (Decl_Id) /= Name_uParent
7176 and then Needs_Finalization (Decl_Typ)
7177 and then Has_Access_Constraint (Decl_Id)
7178 and then No (Expression (Decl))
7179 then
7180 Process_Component_For_Finalize
7181 (Decl, Alts, Decls, Stmts, Num_Comps);
7182 end if;
7184 Prev_Non_Pragma (Decl);
7185 end loop;
7186 end if;
7188 if not In_Variant_Part then
7189 Last_POC_Call := Last (Stmts);
7190 -- In the case of a type extension, the deep-finalize call
7191 -- for the _Parent component will be inserted here.
7192 end if;
7194 -- Process the rest of the components in reverse order
7196 Decl := Last_Non_Pragma (Component_Items (Comps));
7197 while Present (Decl) loop
7198 Decl_Id := Defining_Identifier (Decl);
7199 Decl_Typ := Etype (Decl_Id);
7201 -- Skip _parent
7203 if Chars (Decl_Id) /= Name_uParent
7204 and then Needs_Finalization (Decl_Typ)
7205 then
7206 -- Skip per-object constrained components since they were
7207 -- handled in the above step.
7209 if Has_Access_Constraint (Decl_Id)
7210 and then No (Expression (Decl))
7211 then
7212 null;
7213 else
7214 Process_Component_For_Finalize
7215 (Decl, Alts, Decls, Stmts, Num_Comps);
7216 end if;
7217 end if;
7219 Prev_Non_Pragma (Decl);
7220 end loop;
7222 -- Generate:
7223 -- declare
7224 -- LN : label; -- If Is_Local is enabled
7225 -- ... .
7226 -- L0 : label; .
7228 -- begin .
7229 -- case CounterX is .
7230 -- when N => .
7231 -- goto LN; .
7232 -- ... .
7233 -- when 1 => .
7234 -- goto L1; .
7235 -- when others => .
7236 -- goto L0; .
7237 -- end case; .
7239 -- <<LN>> -- If Is_Local is enabled
7240 -- begin
7241 -- [Deep_]Finalize (V.CompY);
7242 -- exception
7243 -- when Id : others =>
7244 -- if not Raised then
7245 -- Raised := True;
7246 -- Save_Occurrence (E,
7247 -- Get_Current_Excep.all.all);
7248 -- end if;
7249 -- end;
7250 -- ...
7251 -- <<L0>> -- If Is_Local is enabled
7252 -- end;
7254 if Is_Local then
7256 -- Add the declaration of default jump location L0, its
7257 -- corresponding alternative and its place in the statements.
7259 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
7260 Set_Entity (Label_Id,
7261 Make_Defining_Identifier (Loc, Chars (Label_Id)));
7262 Label := Make_Label (Loc, Label_Id);
7264 Append_To (Decls, -- declaration
7265 Make_Implicit_Label_Declaration (Loc,
7266 Defining_Identifier => Entity (Label_Id),
7267 Label_Construct => Label));
7269 Append_To (Alts, -- alternative
7270 Make_Case_Statement_Alternative (Loc,
7271 Discrete_Choices => New_List (
7272 Make_Others_Choice (Loc)),
7274 Statements => New_List (
7275 Make_Goto_Statement (Loc,
7276 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
7278 Append_To (Stmts, Label); -- statement
7280 -- Create the jump block
7282 Prepend_To (Stmts,
7283 Make_Case_Statement (Loc,
7284 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
7285 Alternatives => Alts));
7286 end if;
7288 Jump_Block :=
7289 Make_Block_Statement (Loc,
7290 Declarations => Decls,
7291 Handled_Statement_Sequence =>
7292 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
7294 if Present (Var_Case) then
7295 return New_List (Var_Case, Jump_Block);
7296 else
7297 return New_List (Jump_Block);
7298 end if;
7299 end Process_Component_List_For_Finalize;
7301 -- Local variables
7303 Bod_Stmts : List_Id := No_List;
7304 Finalizer_Decls : List_Id := No_List;
7305 Rec_Def : Node_Id;
7307 -- Start of processing for Build_Finalize_Statements
7309 begin
7310 Finalizer_Decls := New_List;
7311 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
7313 if Nkind (Typ_Def) = N_Derived_Type_Definition then
7314 Rec_Def := Record_Extension_Part (Typ_Def);
7315 else
7316 Rec_Def := Typ_Def;
7317 end if;
7319 -- Create a finalization sequence for all record components
7321 if Present (Component_List (Rec_Def)) then
7322 Bod_Stmts :=
7323 Process_Component_List_For_Finalize (Component_List (Rec_Def));
7324 end if;
7326 -- A derived record type must finalize all inherited components. This
7327 -- action poses the following problem:
7329 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
7330 -- begin
7331 -- Finalize (Obj);
7332 -- ...
7334 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
7335 -- begin
7336 -- Deep_Finalize (Obj._parent);
7337 -- ...
7338 -- Finalize (Obj);
7339 -- ...
7341 -- Finalizing the derived type will invoke Finalize of the parent and
7342 -- then that of the derived type. This is undesirable because both
7343 -- routines may modify shared components. Only the Finalize of the
7344 -- derived type should be invoked.
7346 -- To prevent this double adjustment of shared components,
7347 -- Deep_Finalize uses a flag to control the invocation of Finalize:
7349 -- procedure Deep_Finalize
7350 -- (Obj : in out Some_Type;
7351 -- Flag : Boolean := True)
7352 -- is
7353 -- begin
7354 -- if Flag then
7355 -- Finalize (Obj);
7356 -- end if;
7357 -- ...
7359 -- When Deep_Finalize is invoked for field _parent, a value of False
7360 -- is provided for the flag:
7362 -- Deep_Finalize (Obj._parent, False);
7364 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
7365 declare
7366 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
7367 Call : Node_Id;
7368 Fin_Stmt : Node_Id;
7370 begin
7371 if Needs_Finalization (Par_Typ) then
7372 Call :=
7373 Make_Final_Call
7374 (Obj_Ref =>
7375 Make_Selected_Component (Loc,
7376 Prefix => Make_Identifier (Loc, Name_V),
7377 Selector_Name =>
7378 Make_Identifier (Loc, Name_uParent)),
7379 Typ => Par_Typ,
7380 Skip_Self => True);
7382 -- Generate:
7383 -- begin
7384 -- Deep_Finalize (V._parent, False);
7386 -- exception
7387 -- when Id : others =>
7388 -- if not Raised then
7389 -- Raised := True;
7390 -- Save_Occurrence (E,
7391 -- Get_Current_Excep.all.all);
7392 -- end if;
7393 -- end;
7395 if Present (Call) then
7396 Fin_Stmt := Call;
7398 if Exceptions_OK then
7399 Fin_Stmt :=
7400 Make_Block_Statement (Loc,
7401 Handled_Statement_Sequence =>
7402 Make_Handled_Sequence_Of_Statements (Loc,
7403 Statements => New_List (Fin_Stmt),
7404 Exception_Handlers => New_List (
7405 Build_Exception_Handler
7406 (Finalizer_Data))));
7407 end if;
7409 -- The intended component finalization order is
7410 -- 1) POC components of extension
7411 -- 2) _Parent component
7412 -- 3) non-POC components of extension.
7414 -- With this "finalize the parent part in the middle"
7415 -- ordering, we can avoid the need for making two
7416 -- calls to the parent's subprogram in the way that
7417 -- is necessary for Init_Procs. This does have the
7418 -- peculiar (but legal) consequence that the parent's
7419 -- non-POC components are finalized before the
7420 -- non-POC extension components. This violates the
7421 -- usual "finalize in reverse declaration order"
7422 -- principle, but that's ok (see RM 7.6.1(9)).
7424 -- Last_POC_Call should be non-empty if the extension
7425 -- has at least one POC. Interactions with variant
7426 -- parts are incorrectly ignored.
7428 if Present (Last_POC_Call) then
7429 Insert_After (Last_POC_Call, Fin_Stmt);
7430 else
7431 -- At this point, we could look for the common case
7432 -- where there are no POC components anywhere in
7433 -- sight (inherited or not) and, in that common case,
7434 -- call Append_To instead of Prepend_To. That would
7435 -- result in finalizing the parent part after, rather
7436 -- than before, the extension components. That might
7437 -- be more intuitive (as discussed in preceding
7438 -- comment), but it is not required.
7439 Prepend_To (Bod_Stmts, Fin_Stmt);
7440 end if;
7441 end if;
7442 end if;
7443 end;
7444 end if;
7446 -- Finalize the object. This action must be performed first before
7447 -- all components have been finalized.
7449 if Is_Controlled (Typ) and then not Is_Local then
7450 declare
7451 Fin_Stmt : Node_Id;
7452 Proc : Entity_Id;
7454 begin
7455 Proc := Find_Optional_Prim_Op (Typ, Name_Finalize);
7457 -- Generate:
7458 -- if F then
7459 -- begin
7460 -- Finalize (V);
7462 -- exception
7463 -- when others =>
7464 -- if not Raised then
7465 -- Raised := True;
7466 -- Save_Occurrence (E,
7467 -- Get_Current_Excep.all.all);
7468 -- end if;
7469 -- end;
7470 -- end if;
7472 if Present (Proc) then
7473 Fin_Stmt :=
7474 Make_Procedure_Call_Statement (Loc,
7475 Name => New_Occurrence_Of (Proc, Loc),
7476 Parameter_Associations => New_List (
7477 Make_Identifier (Loc, Name_V)));
7479 if Exceptions_OK then
7480 Fin_Stmt :=
7481 Make_Block_Statement (Loc,
7482 Handled_Statement_Sequence =>
7483 Make_Handled_Sequence_Of_Statements (Loc,
7484 Statements => New_List (Fin_Stmt),
7485 Exception_Handlers => New_List (
7486 Build_Exception_Handler
7487 (Finalizer_Data))));
7488 end if;
7490 Prepend_To (Bod_Stmts,
7491 Make_If_Statement (Loc,
7492 Condition => Make_Identifier (Loc, Name_F),
7493 Then_Statements => New_List (Fin_Stmt)));
7494 end if;
7495 end;
7496 end if;
7498 -- At this point either all finalization statements have been
7499 -- generated or the type is not controlled.
7501 if No (Bod_Stmts) then
7502 return New_List (Make_Null_Statement (Loc));
7504 -- Generate:
7505 -- declare
7506 -- Abort : constant Boolean := Triggered_By_Abort;
7507 -- <or>
7508 -- Abort : constant Boolean := False; -- no abort
7510 -- E : Exception_Occurrence;
7511 -- Raised : Boolean := False;
7513 -- begin
7514 -- <finalize statements>
7516 -- if Raised and then not Abort then
7517 -- Raise_From_Controlled_Operation (E);
7518 -- end if;
7519 -- end;
7521 else
7522 if Exceptions_OK then
7523 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
7524 end if;
7526 return
7527 New_List (
7528 Make_Block_Statement (Loc,
7529 Declarations =>
7530 Finalizer_Decls,
7531 Handled_Statement_Sequence =>
7532 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
7533 end if;
7534 end Build_Finalize_Statements;
7536 -----------------------
7537 -- Parent_Field_Type --
7538 -----------------------
7540 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
7541 Field : Entity_Id;
7543 begin
7544 Field := First_Entity (Typ);
7545 while Present (Field) loop
7546 if Chars (Field) = Name_uParent then
7547 return Etype (Field);
7548 end if;
7550 Next_Entity (Field);
7551 end loop;
7553 -- A derived tagged type should always have a parent field
7555 raise Program_Error;
7556 end Parent_Field_Type;
7558 ---------------------------
7559 -- Preprocess_Components --
7560 ---------------------------
7562 procedure Preprocess_Components
7563 (Comps : Node_Id;
7564 Num_Comps : out Nat;
7565 Has_POC : out Boolean)
7567 Decl : Node_Id;
7568 Id : Entity_Id;
7569 Typ : Entity_Id;
7571 begin
7572 Num_Comps := 0;
7573 Has_POC := False;
7575 Decl := First_Non_Pragma (Component_Items (Comps));
7576 while Present (Decl) loop
7577 Id := Defining_Identifier (Decl);
7578 Typ := Etype (Id);
7580 -- Skip field _parent
7582 if Chars (Id) /= Name_uParent
7583 and then Needs_Finalization (Typ)
7584 then
7585 Num_Comps := Num_Comps + 1;
7587 if Has_Access_Constraint (Id)
7588 and then No (Expression (Decl))
7589 then
7590 Has_POC := True;
7591 end if;
7592 end if;
7594 Next_Non_Pragma (Decl);
7595 end loop;
7596 end Preprocess_Components;
7598 -- Start of processing for Make_Deep_Record_Body
7600 begin
7601 case Prim is
7602 when Address_Case =>
7603 return Make_Finalize_Address_Stmts (Typ);
7605 when Adjust_Case =>
7606 return Build_Adjust_Statements (Typ);
7608 when Finalize_Case =>
7609 return Build_Finalize_Statements (Typ);
7611 when Initialize_Case =>
7612 declare
7613 Loc : constant Source_Ptr := Sloc (Typ);
7615 begin
7616 if Is_Controlled (Typ) then
7617 return New_List (
7618 Make_Procedure_Call_Statement (Loc,
7619 Name =>
7620 New_Occurrence_Of
7621 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
7622 Parameter_Associations => New_List (
7623 Make_Identifier (Loc, Name_V))));
7624 else
7625 return Empty_List;
7626 end if;
7627 end;
7628 end case;
7629 end Make_Deep_Record_Body;
7631 ----------------------
7632 -- Make_Final_Call --
7633 ----------------------
7635 function Make_Final_Call
7636 (Obj_Ref : Node_Id;
7637 Typ : Entity_Id;
7638 Skip_Self : Boolean := False) return Node_Id
7640 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7641 Atyp : Entity_Id;
7642 Prot_Typ : Entity_Id := Empty;
7643 Fin_Id : Entity_Id := Empty;
7644 Ref : Node_Id;
7645 Utyp : Entity_Id;
7647 begin
7648 Ref := Obj_Ref;
7650 -- Recover the proper type which contains [Deep_]Finalize
7652 if Is_Class_Wide_Type (Typ) then
7653 Utyp := Root_Type (Typ);
7654 Atyp := Utyp;
7656 elsif Is_Concurrent_Type (Typ) then
7657 Utyp := Corresponding_Record_Type (Typ);
7658 Atyp := Empty;
7659 Ref := Convert_Concurrent (Ref, Typ);
7661 elsif Is_Private_Type (Typ)
7662 and then Present (Underlying_Type (Typ))
7663 and then Is_Concurrent_Type (Underlying_Type (Typ))
7664 then
7665 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7666 Atyp := Typ;
7667 Ref := Convert_Concurrent (Ref, Underlying_Type (Typ));
7669 else
7670 Utyp := Typ;
7671 Atyp := Typ;
7672 end if;
7674 Utyp := Underlying_Type (Base_Type (Utyp));
7675 Set_Assignment_OK (Ref);
7677 -- Deal with untagged derivation of private views. If the parent type
7678 -- is a protected type, Deep_Finalize is found on the corresponding
7679 -- record of the ancestor.
7681 if Is_Untagged_Derivation (Typ) then
7682 if Is_Protected_Type (Typ) then
7683 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7684 else
7685 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7687 if Is_Protected_Type (Utyp) then
7688 Utyp := Corresponding_Record_Type (Utyp);
7689 end if;
7690 end if;
7692 Ref := Unchecked_Convert_To (Utyp, Ref);
7693 Set_Assignment_OK (Ref);
7694 end if;
7696 -- Deal with derived private types which do not inherit primitives from
7697 -- their parents. In this case, [Deep_]Finalize can be found in the full
7698 -- view of the parent type.
7700 if Present (Utyp)
7701 and then Is_Tagged_Type (Utyp)
7702 and then Is_Derived_Type (Utyp)
7703 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
7704 and then Is_Private_Type (Etype (Utyp))
7705 and then Present (Full_View (Etype (Utyp)))
7706 then
7707 Utyp := Full_View (Etype (Utyp));
7708 Ref := Unchecked_Convert_To (Utyp, Ref);
7709 Set_Assignment_OK (Ref);
7710 end if;
7712 -- When dealing with the completion of a private type, use the base type
7713 -- instead.
7715 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
7716 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
7718 Utyp := Base_Type (Utyp);
7719 Ref := Unchecked_Convert_To (Utyp, Ref);
7720 Set_Assignment_OK (Ref);
7721 end if;
7723 -- Detect if Typ is a protected type or an expanded protected type and
7724 -- store the relevant type within Prot_Typ for later processing.
7726 if Is_Protected_Type (Typ) then
7727 Prot_Typ := Typ;
7729 elsif Ekind (Typ) = E_Record_Type
7730 and then Present (Corresponding_Concurrent_Type (Typ))
7731 and then Is_Protected_Type (Corresponding_Concurrent_Type (Typ))
7732 then
7733 Prot_Typ := Corresponding_Concurrent_Type (Typ);
7734 end if;
7736 -- The underlying type may not be present due to a missing full view. In
7737 -- this case freezing did not take place and there is no [Deep_]Finalize
7738 -- primitive to call.
7740 if No (Utyp) then
7741 return Empty;
7743 elsif Skip_Self then
7744 if Has_Controlled_Component (Utyp) then
7745 if Is_Tagged_Type (Utyp) then
7746 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
7747 else
7748 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
7749 end if;
7750 end if;
7752 -- Class-wide types, interfaces and types with controlled components
7754 elsif Is_Class_Wide_Type (Typ)
7755 or else Is_Interface (Typ)
7756 or else Has_Controlled_Component (Utyp)
7757 then
7758 if Is_Tagged_Type (Utyp) then
7759 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
7760 else
7761 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
7762 end if;
7764 -- Derivations from [Limited_]Controlled
7766 elsif Is_Controlled (Utyp) then
7767 Fin_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Finalize_Case));
7769 -- Tagged types
7771 elsif Is_Tagged_Type (Utyp) then
7772 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
7774 -- Protected types: these also require finalization even though they
7775 -- are not marked controlled explicitly.
7777 elsif Present (Prot_Typ) then
7778 -- Protected objects do not need to be finalized on restricted
7779 -- runtimes.
7781 if Restricted_Profile then
7782 return Empty;
7784 -- ??? Only handle the simple case for now. Will not support a record
7785 -- or array containing protected objects.
7787 elsif Is_Simple_Protected_Type (Prot_Typ) then
7788 Fin_Id := RTE (RE_Finalize_Protection);
7789 else
7790 raise Program_Error;
7791 end if;
7793 else
7794 raise Program_Error;
7795 end if;
7797 if Present (Fin_Id) then
7799 -- When finalizing a class-wide object, do not convert to the root
7800 -- type in order to produce a dispatching call.
7802 if Is_Class_Wide_Type (Typ) then
7803 null;
7805 -- Ensure that a finalization routine is at least decorated in order
7806 -- to inspect the object parameter.
7808 elsif Analyzed (Fin_Id)
7809 or else Ekind (Fin_Id) = E_Procedure
7810 then
7811 -- In certain cases, such as the creation of Stream_Read, the
7812 -- visible entity of the type is its full view. Since Stream_Read
7813 -- will have to create an object of type Typ, the local object
7814 -- will be finalzed by the scope finalizer generated later on. The
7815 -- object parameter of Deep_Finalize will always use the private
7816 -- view of the type. To avoid such a clash between a private and a
7817 -- full view, perform an unchecked conversion of the object
7818 -- reference to the private view.
7820 declare
7821 Formal_Typ : constant Entity_Id :=
7822 Etype (First_Formal (Fin_Id));
7823 begin
7824 if Is_Private_Type (Formal_Typ)
7825 and then Present (Full_View (Formal_Typ))
7826 and then Full_View (Formal_Typ) = Utyp
7827 then
7828 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
7829 end if;
7830 end;
7832 -- If the object is unanalyzed, set its expected type for use in
7833 -- Convert_View in case an additional conversion is needed.
7835 if No (Etype (Ref))
7836 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
7837 then
7838 Set_Etype (Ref, Typ);
7839 end if;
7841 Ref := Convert_View (Fin_Id, Ref);
7842 end if;
7844 return
7845 Make_Call (Loc,
7846 Proc_Id => Fin_Id,
7847 Param => Ref,
7848 Skip_Self => Skip_Self);
7849 else
7850 pragma Assert (Serious_Errors_Detected > 0
7851 or else not Has_Controlled_Component (Utyp));
7852 return Empty;
7853 end if;
7854 end Make_Final_Call;
7856 --------------------------------
7857 -- Make_Finalize_Address_Body --
7858 --------------------------------
7860 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
7861 Is_Task : constant Boolean :=
7862 Ekind (Typ) = E_Record_Type
7863 and then Is_Concurrent_Record_Type (Typ)
7864 and then Ekind (Corresponding_Concurrent_Type (Typ)) =
7865 E_Task_Type;
7866 Loc : constant Source_Ptr := Sloc (Typ);
7867 Proc_Id : Entity_Id;
7868 Stmts : List_Id;
7870 begin
7871 -- The corresponding records of task types are not controlled by design.
7872 -- For the sake of completeness, create an empty Finalize_Address to be
7873 -- used in task class-wide allocations.
7875 if Is_Task then
7876 null;
7878 -- Nothing to do if the type is not controlled or it already has a
7879 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
7880 -- come from source. These are usually generated for completeness and
7881 -- do not need the Finalize_Address primitive.
7883 elsif not Needs_Finalization (Typ)
7884 or else Present (TSS (Typ, TSS_Finalize_Address))
7885 or else
7886 (Is_Class_Wide_Type (Typ)
7887 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
7888 and then not Comes_From_Source (Root_Type (Typ)))
7889 then
7890 return;
7891 end if;
7893 -- Do not generate Finalize_Address routine for CodePeer
7895 if CodePeer_Mode then
7896 return;
7897 end if;
7899 Proc_Id :=
7900 Make_Defining_Identifier (Loc,
7901 Make_TSS_Name (Typ, TSS_Finalize_Address));
7903 -- Generate:
7905 -- procedure <Typ>FD (V : System.Address) is
7906 -- begin
7907 -- null; -- for tasks
7909 -- declare -- for all other types
7910 -- type Pnn is access all Typ;
7911 -- for Pnn'Storage_Size use 0;
7912 -- begin
7913 -- [Deep_]Finalize (Pnn (V).all);
7914 -- end;
7915 -- end TypFD;
7917 if Is_Task then
7918 Stmts := New_List (Make_Null_Statement (Loc));
7919 else
7920 Stmts := Make_Finalize_Address_Stmts (Typ);
7921 end if;
7923 Discard_Node (
7924 Make_Subprogram_Body (Loc,
7925 Specification =>
7926 Make_Procedure_Specification (Loc,
7927 Defining_Unit_Name => Proc_Id,
7929 Parameter_Specifications => New_List (
7930 Make_Parameter_Specification (Loc,
7931 Defining_Identifier =>
7932 Make_Defining_Identifier (Loc, Name_V),
7933 Parameter_Type =>
7934 New_Occurrence_Of (RTE (RE_Address), Loc)))),
7936 Declarations => No_List,
7938 Handled_Statement_Sequence =>
7939 Make_Handled_Sequence_Of_Statements (Loc,
7940 Statements => Stmts)));
7942 Set_TSS (Typ, Proc_Id);
7943 end Make_Finalize_Address_Body;
7945 ---------------------------------
7946 -- Make_Finalize_Address_Stmts --
7947 ---------------------------------
7949 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
7950 Loc : constant Source_Ptr := Sloc (Typ);
7952 Decls : List_Id;
7953 Desig_Typ : Entity_Id;
7954 Fin_Block : Node_Id;
7955 Fin_Call : Node_Id;
7956 Obj_Expr : Node_Id;
7957 Ptr_Typ : Entity_Id;
7959 begin
7960 if Is_Array_Type (Typ) then
7961 if Is_Constrained (First_Subtype (Typ)) then
7962 Desig_Typ := First_Subtype (Typ);
7963 else
7964 Desig_Typ := Base_Type (Typ);
7965 end if;
7967 -- Class-wide types of constrained root types
7969 elsif Is_Class_Wide_Type (Typ)
7970 and then Has_Discriminants (Root_Type (Typ))
7971 and then not
7972 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7973 then
7974 declare
7975 Parent_Typ : Entity_Id;
7976 Parent_Utyp : Entity_Id;
7978 begin
7979 -- Climb the parent type chain looking for a non-constrained type
7981 Parent_Typ := Root_Type (Typ);
7982 while Parent_Typ /= Etype (Parent_Typ)
7983 and then Has_Discriminants (Parent_Typ)
7984 and then not
7985 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7986 loop
7987 Parent_Typ := Etype (Parent_Typ);
7988 end loop;
7990 -- Handle views created for tagged types with unknown
7991 -- discriminants.
7993 if Is_Underlying_Record_View (Parent_Typ) then
7994 Parent_Typ := Underlying_Record_View (Parent_Typ);
7995 end if;
7997 Parent_Utyp := Underlying_Type (Parent_Typ);
7999 -- Handle views created for a synchronized private extension with
8000 -- known, non-defaulted discriminants. In that case, parent_typ
8001 -- will be the private extension, as it is the first "non
8002 -- -constrained" type in the parent chain. Unfortunately, the
8003 -- underlying type, being a protected or task type, is not the
8004 -- "real" type needing finalization. Rather, the "corresponding
8005 -- record type" should be the designated type here. In fact, TSS
8006 -- finalizer generation is specifically skipped for the nominal
8007 -- class-wide type of (the full view of) a concurrent type (see
8008 -- exp_ch7.Expand_Freeze_Class_Wide_Type). If we don't designate
8009 -- the underlying record (Tprot_typeVC), we will end up trying to
8010 -- dispatch to prot_typeVDF from an incorrectly designated
8011 -- Tprot_typeC, which is, of course, not actually a member of
8012 -- prot_typeV'Class, and thus incompatible.
8014 if Ekind (Parent_Utyp) in Concurrent_Kind
8015 and then Present (Corresponding_Record_Type (Parent_Utyp))
8016 then
8017 Parent_Utyp := Corresponding_Record_Type (Parent_Utyp);
8018 end if;
8020 Desig_Typ := Class_Wide_Type (Parent_Utyp);
8021 end;
8023 -- General case
8025 else
8026 Desig_Typ := Typ;
8027 end if;
8029 -- Generate:
8030 -- type Ptr_Typ is access all Typ;
8031 -- for Ptr_Typ'Storage_Size use 0;
8033 Ptr_Typ := Make_Temporary (Loc, 'P');
8035 Decls := New_List (
8036 Make_Full_Type_Declaration (Loc,
8037 Defining_Identifier => Ptr_Typ,
8038 Type_Definition =>
8039 Make_Access_To_Object_Definition (Loc,
8040 All_Present => True,
8041 Subtype_Indication => New_Occurrence_Of (Desig_Typ, Loc))),
8043 Make_Attribute_Definition_Clause (Loc,
8044 Name => New_Occurrence_Of (Ptr_Typ, Loc),
8045 Chars => Name_Storage_Size,
8046 Expression => Make_Integer_Literal (Loc, 0)));
8048 Obj_Expr := Make_Identifier (Loc, Name_V);
8050 -- Unconstrained arrays require special processing in order to retrieve
8051 -- the elements. To achieve this, we have to skip the dope vector which
8052 -- lays in front of the elements and then use a thin pointer to perform
8053 -- the address-to-access conversion.
8055 if Is_Array_Type (Typ)
8056 and then not Is_Constrained (First_Subtype (Typ))
8057 then
8058 declare
8059 Dope_Id : Entity_Id;
8061 begin
8062 -- Ensure that Ptr_Typ is a thin pointer; generate:
8063 -- for Ptr_Typ'Size use System.Address'Size;
8065 Append_To (Decls,
8066 Make_Attribute_Definition_Clause (Loc,
8067 Name => New_Occurrence_Of (Ptr_Typ, Loc),
8068 Chars => Name_Size,
8069 Expression =>
8070 Make_Integer_Literal (Loc, System_Address_Size)));
8072 -- Generate:
8073 -- Dnn : constant Storage_Offset :=
8074 -- Desig_Typ'Descriptor_Size / Storage_Unit;
8076 Dope_Id := Make_Temporary (Loc, 'D');
8078 Append_To (Decls,
8079 Make_Object_Declaration (Loc,
8080 Defining_Identifier => Dope_Id,
8081 Constant_Present => True,
8082 Object_Definition =>
8083 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc),
8084 Expression =>
8085 Make_Op_Divide (Loc,
8086 Left_Opnd =>
8087 Make_Attribute_Reference (Loc,
8088 Prefix => New_Occurrence_Of (Desig_Typ, Loc),
8089 Attribute_Name => Name_Descriptor_Size),
8090 Right_Opnd =>
8091 Make_Integer_Literal (Loc, System_Storage_Unit))));
8093 -- Shift the address from the start of the dope vector to the
8094 -- start of the elements:
8096 -- V + Dnn
8098 -- Note that this is done through a wrapper routine since RTSfind
8099 -- cannot retrieve operations with string names of the form "+".
8101 Obj_Expr :=
8102 Make_Function_Call (Loc,
8103 Name =>
8104 New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
8105 Parameter_Associations => New_List (
8106 Obj_Expr,
8107 New_Occurrence_Of (Dope_Id, Loc)));
8108 end;
8109 end if;
8111 Fin_Call :=
8112 Make_Final_Call (
8113 Obj_Ref =>
8114 Make_Explicit_Dereference (Loc,
8115 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
8116 Typ => Desig_Typ);
8118 if Present (Fin_Call) then
8119 Fin_Block :=
8120 Make_Block_Statement (Loc,
8121 Declarations => Decls,
8122 Handled_Statement_Sequence =>
8123 Make_Handled_Sequence_Of_Statements (Loc,
8124 Statements => New_List (Fin_Call)));
8126 -- Otherwise previous errors or a missing full view may prevent the
8127 -- proper freezing of the designated type. If this is the case, there
8128 -- is no [Deep_]Finalize primitive to call.
8130 else
8131 Fin_Block := Make_Null_Statement (Loc);
8132 end if;
8134 return New_List (Fin_Block);
8135 end Make_Finalize_Address_Stmts;
8137 -------------------------------------
8138 -- Make_Handler_For_Ctrl_Operation --
8139 -------------------------------------
8141 -- Generate:
8143 -- when E : others =>
8144 -- Raise_From_Controlled_Operation (E);
8146 -- or:
8148 -- when others =>
8149 -- raise Program_Error [finalize raised exception];
8151 -- depending on whether Raise_From_Controlled_Operation is available
8153 function Make_Handler_For_Ctrl_Operation
8154 (Loc : Source_Ptr) return Node_Id
8156 E_Occ : Entity_Id;
8157 -- Choice parameter (for the first case above)
8159 Raise_Node : Node_Id;
8160 -- Procedure call or raise statement
8162 begin
8163 -- Standard run-time: add choice parameter E and pass it to
8164 -- Raise_From_Controlled_Operation so that the original exception
8165 -- name and message can be recorded in the exception message for
8166 -- Program_Error.
8168 if RTE_Available (RE_Raise_From_Controlled_Operation) then
8169 E_Occ := Make_Defining_Identifier (Loc, Name_E);
8170 Raise_Node :=
8171 Make_Procedure_Call_Statement (Loc,
8172 Name =>
8173 New_Occurrence_Of
8174 (RTE (RE_Raise_From_Controlled_Operation), Loc),
8175 Parameter_Associations => New_List (
8176 New_Occurrence_Of (E_Occ, Loc)));
8178 -- Restricted run-time: exception messages are not supported
8180 else
8181 E_Occ := Empty;
8182 Raise_Node :=
8183 Make_Raise_Program_Error (Loc,
8184 Reason => PE_Finalize_Raised_Exception);
8185 end if;
8187 return
8188 Make_Implicit_Exception_Handler (Loc,
8189 Exception_Choices => New_List (Make_Others_Choice (Loc)),
8190 Choice_Parameter => E_Occ,
8191 Statements => New_List (Raise_Node));
8192 end Make_Handler_For_Ctrl_Operation;
8194 --------------------
8195 -- Make_Init_Call --
8196 --------------------
8198 function Make_Init_Call
8199 (Obj_Ref : Node_Id;
8200 Typ : Entity_Id) return Node_Id
8202 Loc : constant Source_Ptr := Sloc (Obj_Ref);
8203 Is_Conc : Boolean;
8204 Proc : Entity_Id;
8205 Ref : Node_Id;
8206 Utyp : Entity_Id;
8208 begin
8209 Ref := Obj_Ref;
8211 -- Deal with the type and object reference. Depending on the context, an
8212 -- object reference may need several conversions.
8214 if Is_Concurrent_Type (Typ) then
8215 Is_Conc := True;
8216 Utyp := Corresponding_Record_Type (Typ);
8217 Ref := Convert_Concurrent (Ref, Typ);
8219 elsif Is_Private_Type (Typ)
8220 and then Present (Full_View (Typ))
8221 and then Is_Concurrent_Type (Underlying_Type (Typ))
8222 then
8223 Is_Conc := True;
8224 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
8225 Ref := Convert_Concurrent (Ref, Underlying_Type (Typ));
8227 else
8228 Is_Conc := False;
8229 Utyp := Typ;
8230 end if;
8232 Utyp := Underlying_Type (Base_Type (Utyp));
8233 Set_Assignment_OK (Ref);
8235 -- Deal with untagged derivation of private views
8237 if Is_Untagged_Derivation (Typ) and then not Is_Conc then
8238 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
8239 Ref := Unchecked_Convert_To (Utyp, Ref);
8241 -- The following is to prevent problems with UC see 1.156 RH ???
8243 Set_Assignment_OK (Ref);
8244 end if;
8246 -- If the underlying_type is a subtype, then we are dealing with the
8247 -- completion of a private type. We need to access the base type and
8248 -- generate a conversion to it.
8250 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
8251 pragma Assert (Is_Private_Type (Typ));
8252 Utyp := Base_Type (Utyp);
8253 Ref := Unchecked_Convert_To (Utyp, Ref);
8254 end if;
8256 -- The underlying type may not be present due to a missing full view.
8257 -- In this case freezing did not take place and there is no suitable
8258 -- [Deep_]Initialize primitive to call.
8259 -- If Typ is protected then no additional processing is needed either.
8261 if No (Utyp)
8262 or else Is_Protected_Type (Typ)
8263 then
8264 return Empty;
8265 end if;
8267 -- Select the appropriate version of initialize
8269 if Has_Controlled_Component (Utyp) then
8270 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
8271 else
8272 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
8273 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
8274 end if;
8276 -- If initialization procedure for an array of controlled objects is
8277 -- trivial, do not generate a useless call to it.
8278 -- The initialization procedure may be missing altogether in the case
8279 -- of a derived container whose components have trivial initialization.
8281 if No (Proc)
8282 or else (Is_Array_Type (Utyp) and then Is_Trivial_Subprogram (Proc))
8283 or else
8284 (not Comes_From_Source (Proc)
8285 and then Present (Alias (Proc))
8286 and then Is_Trivial_Subprogram (Alias (Proc)))
8287 then
8288 return Empty;
8289 end if;
8291 -- The object reference may need another conversion depending on the
8292 -- type of the formal and that of the actual.
8294 Ref := Convert_View (Proc, Ref);
8296 -- Generate:
8297 -- [Deep_]Initialize (Ref);
8299 return
8300 Make_Procedure_Call_Statement (Loc,
8301 Name => New_Occurrence_Of (Proc, Loc),
8302 Parameter_Associations => New_List (Ref));
8303 end Make_Init_Call;
8305 ------------------------------
8306 -- Make_Local_Deep_Finalize --
8307 ------------------------------
8309 function Make_Local_Deep_Finalize
8310 (Typ : Entity_Id;
8311 Nam : Entity_Id) return Node_Id
8313 Loc : constant Source_Ptr := Sloc (Typ);
8314 Formals : List_Id;
8316 begin
8317 Formals := New_List (
8319 -- V : in out Typ
8321 Make_Parameter_Specification (Loc,
8322 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
8323 In_Present => True,
8324 Out_Present => True,
8325 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
8327 -- F : Boolean := True
8329 Make_Parameter_Specification (Loc,
8330 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
8331 Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc),
8332 Expression => New_Occurrence_Of (Standard_True, Loc)));
8334 -- Add the necessary number of counters to represent the initialization
8335 -- state of an object.
8337 return
8338 Make_Subprogram_Body (Loc,
8339 Specification =>
8340 Make_Procedure_Specification (Loc,
8341 Defining_Unit_Name => Nam,
8342 Parameter_Specifications => Formals),
8344 Declarations => No_List,
8346 Handled_Statement_Sequence =>
8347 Make_Handled_Sequence_Of_Statements (Loc,
8348 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
8349 end Make_Local_Deep_Finalize;
8351 ----------------------------------
8352 -- Make_Master_Node_Declaration --
8353 ----------------------------------
8355 function Make_Master_Node_Declaration
8356 (Loc : Source_Ptr;
8357 Master_Node : Entity_Id;
8358 Obj : Entity_Id) return Node_Id
8360 begin
8361 Set_Finalization_Master_Node (Obj, Master_Node);
8363 return
8364 Make_Object_Declaration (Loc,
8365 Defining_Identifier => Master_Node,
8366 Aliased_Present => True,
8367 Object_Definition =>
8368 New_Occurrence_Of (RTE (RE_Master_Node), Loc));
8369 end Make_Master_Node_Declaration;
8371 ----------------------------------------
8372 -- Make_Suppress_Object_Finalize_Call --
8373 ----------------------------------------
8375 function Make_Suppress_Object_Finalize_Call
8376 (Loc : Source_Ptr;
8377 Obj : Entity_Id) return Node_Id
8379 Obj_Decl : constant Node_Id := Declaration_Node (Obj);
8381 Master_Node_Decl : Node_Id;
8382 Master_Node_Id : Entity_Id;
8384 begin
8385 -- Create the declaration of the Master_Node for the object and
8386 -- insert it before the declaration of the object itself.
8388 if Present (Finalization_Master_Node (Obj)) then
8389 Master_Node_Id := Finalization_Master_Node (Obj);
8391 else
8392 Master_Node_Id := Make_Temporary (Loc, 'N');
8393 Master_Node_Decl :=
8394 Make_Master_Node_Declaration (Loc, Master_Node_Id, Obj);
8395 Insert_Before_And_Analyze (Obj_Decl, Master_Node_Decl);
8397 -- Generate the attachment of the object to the Master_Node
8399 Attach_Object_To_Master_Node (Obj_Decl, Master_Node_Id);
8401 -- Mark the object to avoid double finalization
8403 Set_Is_Ignored_For_Finalization (Obj);
8404 end if;
8406 return
8407 Make_Procedure_Call_Statement (Loc,
8408 Name =>
8409 New_Occurrence_Of (RTE (RE_Suppress_Object_Finalize_At_End), Loc),
8410 Parameter_Associations => New_List (
8411 New_Occurrence_Of (Master_Node_Id, Loc)));
8412 end Make_Suppress_Object_Finalize_Call;
8414 --------------------------
8415 -- Make_Transient_Block --
8416 --------------------------
8418 function Make_Transient_Block
8419 (Loc : Source_Ptr;
8420 Action : Node_Id;
8421 Par : Node_Id) return Node_Id
8423 function Manages_Sec_Stack (Id : Entity_Id) return Boolean;
8424 -- Determine whether scoping entity Id manages the secondary stack
8426 function Within_Loop_Statement (N : Node_Id) return Boolean;
8427 -- Return True when N appears within a loop and no block is containing N
8429 -----------------------
8430 -- Manages_Sec_Stack --
8431 -----------------------
8433 function Manages_Sec_Stack (Id : Entity_Id) return Boolean is
8434 begin
8435 case Ekind (Id) is
8437 -- An exception handler with a choice parameter utilizes a dummy
8438 -- block to provide a declarative region. Such a block should not
8439 -- be considered because it never manifests in the tree and can
8440 -- never release the secondary stack.
8442 when E_Block =>
8443 return
8444 Uses_Sec_Stack (Id) and then not Is_Exception_Handler (Id);
8446 when E_Entry
8447 | E_Entry_Family
8448 | E_Function
8449 | E_Procedure
8451 return Uses_Sec_Stack (Id);
8453 when others =>
8454 return False;
8455 end case;
8456 end Manages_Sec_Stack;
8458 ---------------------------
8459 -- Within_Loop_Statement --
8460 ---------------------------
8462 function Within_Loop_Statement (N : Node_Id) return Boolean is
8463 Par : Node_Id := Parent (N);
8465 begin
8466 while Nkind (Par) not in
8467 N_Handled_Sequence_Of_Statements | N_Loop_Statement |
8468 N_Package_Specification | N_Proper_Body
8469 loop
8470 pragma Assert (Present (Par));
8471 Par := Parent (Par);
8472 end loop;
8474 return Nkind (Par) = N_Loop_Statement;
8475 end Within_Loop_Statement;
8477 -- Local variables
8479 Decls : constant List_Id := New_List;
8480 Instrs : constant List_Id := New_List (Action);
8481 Trans_Id : constant Entity_Id := Current_Scope;
8483 Block : Node_Id;
8484 Insert : Node_Id;
8485 Scop : Entity_Id;
8487 -- Start of processing for Make_Transient_Block
8489 begin
8490 -- Even though the transient block is tasked with managing the secondary
8491 -- stack, the block may forgo this functionality depending on how the
8492 -- secondary stack is managed by enclosing scopes.
8494 if Manages_Sec_Stack (Trans_Id) then
8496 -- Determine whether an enclosing scope already manages the secondary
8497 -- stack.
8499 Scop := Scope (Trans_Id);
8500 while Present (Scop) loop
8502 -- It should not be possible to reach Standard without hitting one
8503 -- of the other cases first unless Standard was manually pushed.
8505 if Scop = Standard_Standard then
8506 exit;
8508 -- The transient block is within a function which returns on the
8509 -- secondary stack. Take a conservative approach and assume that
8510 -- the value on the secondary stack is part of the result. Note
8511 -- that it is not possible to detect this dependency without flow
8512 -- analysis which the compiler does not have. Letting the object
8513 -- live longer than the transient block will not leak any memory
8514 -- because the caller will reclaim the total storage used by the
8515 -- function.
8517 elsif Ekind (Scop) = E_Function
8518 and then Sec_Stack_Needed_For_Return (Scop)
8519 then
8520 Set_Uses_Sec_Stack (Trans_Id, False);
8521 exit;
8523 -- The transient block must manage the secondary stack when the
8524 -- block appears within a loop in order to reclaim the memory at
8525 -- each iteration.
8527 elsif Ekind (Scop) = E_Loop then
8528 exit;
8530 -- Ditto when the block appears without a block that does not
8531 -- manage the secondary stack and is located within a loop.
8533 elsif Ekind (Scop) = E_Block
8534 and then not Manages_Sec_Stack (Scop)
8535 and then Present (Block_Node (Scop))
8536 and then Within_Loop_Statement (Block_Node (Scop))
8537 then
8538 exit;
8540 -- The transient block does not need to manage the secondary stack
8541 -- when there is an enclosing construct which already does that.
8542 -- This optimization saves on SS_Mark and SS_Release calls but may
8543 -- allow objects to live a little longer than required.
8545 -- The transient block must manage the secondary stack when switch
8546 -- -gnatd.s (strict management) is in effect.
8548 elsif Manages_Sec_Stack (Scop) and then not Debug_Flag_Dot_S then
8549 Set_Uses_Sec_Stack (Trans_Id, False);
8550 exit;
8552 -- Prevent the search from going too far because transient blocks
8553 -- are bounded by packages and subprogram scopes.
8555 elsif Ekind (Scop) in E_Entry
8556 | E_Entry_Family
8557 | E_Function
8558 | E_Package
8559 | E_Procedure
8560 | E_Subprogram_Body
8561 then
8562 exit;
8563 end if;
8565 Scop := Scope (Scop);
8566 end loop;
8567 end if;
8569 -- Create the transient block. Set the parent now since the block itself
8570 -- is not part of the tree. The current scope is the E_Block entity that
8571 -- has been pushed by Establish_Transient_Scope.
8573 pragma Assert (Ekind (Trans_Id) = E_Block);
8575 Block :=
8576 Make_Block_Statement (Loc,
8577 Identifier => New_Occurrence_Of (Trans_Id, Loc),
8578 Declarations => Decls,
8579 Handled_Statement_Sequence =>
8580 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
8581 Has_Created_Identifier => True);
8582 Set_Parent (Block, Par);
8584 -- Insert actions stuck in the transient scopes as well as all freezing
8585 -- nodes needed by those actions. Do not insert cleanup actions here,
8586 -- they will be transferred to the newly created block.
8588 Insert_Actions_In_Scope_Around
8589 (Action, Clean => False, Manage_SS => False);
8591 Insert := Prev (Action);
8593 if Present (Insert) then
8594 Freeze_All (First_Entity (Trans_Id), Insert);
8595 end if;
8597 -- Transfer cleanup actions to the newly created block
8599 declare
8600 Cleanup_Actions : List_Id
8601 renames Scope_Stack.Table (Scope_Stack.Last).
8602 Actions_To_Be_Wrapped (Cleanup);
8603 begin
8604 Set_Cleanup_Actions (Block, Cleanup_Actions);
8605 Cleanup_Actions := No_List;
8606 end;
8608 -- When the transient scope was established, we pushed the entry for the
8609 -- transient scope onto the scope stack, so that the scope was active
8610 -- for the installation of finalizable entities etc. Now we must remove
8611 -- this entry, since we have constructed a proper block.
8613 Pop_Scope;
8615 return Block;
8616 end Make_Transient_Block;
8618 ------------------------
8619 -- Node_To_Be_Wrapped --
8620 ------------------------
8622 function Node_To_Be_Wrapped return Node_Id is
8623 begin
8624 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
8625 end Node_To_Be_Wrapped;
8627 ----------------------------
8628 -- Store_Actions_In_Scope --
8629 ----------------------------
8631 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id) is
8632 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
8633 Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK);
8635 begin
8636 if Is_Empty_List (Actions) then
8637 Actions := L;
8639 if Is_List_Member (SE.Node_To_Be_Wrapped) then
8640 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
8641 else
8642 Set_Parent (L, SE.Node_To_Be_Wrapped);
8643 end if;
8645 Analyze_List (L);
8647 elsif AK = Before then
8648 Insert_List_After_And_Analyze (Last (Actions), L);
8650 else
8651 Insert_List_Before_And_Analyze (First (Actions), L);
8652 end if;
8653 end Store_Actions_In_Scope;
8655 ----------------------------------
8656 -- Store_After_Actions_In_Scope --
8657 ----------------------------------
8659 procedure Store_After_Actions_In_Scope (L : List_Id) is
8660 begin
8661 Store_Actions_In_Scope (After, L);
8662 end Store_After_Actions_In_Scope;
8664 -----------------------------------
8665 -- Store_Before_Actions_In_Scope --
8666 -----------------------------------
8668 procedure Store_Before_Actions_In_Scope (L : List_Id) is
8669 begin
8670 Store_Actions_In_Scope (Before, L);
8671 end Store_Before_Actions_In_Scope;
8673 -----------------------------------
8674 -- Store_Cleanup_Actions_In_Scope --
8675 -----------------------------------
8677 procedure Store_Cleanup_Actions_In_Scope (L : List_Id) is
8678 begin
8679 Store_Actions_In_Scope (Cleanup, L);
8680 end Store_Cleanup_Actions_In_Scope;
8682 ------------------
8683 -- Unnest_Block --
8684 ------------------
8686 procedure Unnest_Block (Decl : Node_Id) is
8687 Loc : constant Source_Ptr := Sloc (Decl);
8688 Ent : Entity_Id;
8689 Local_Body : Node_Id;
8690 Local_Call : Node_Id;
8691 Local_Proc : Entity_Id;
8692 Local_Scop : Entity_Id;
8694 begin
8695 Local_Scop := Entity (Identifier (Decl));
8696 Ent := First_Entity (Local_Scop);
8698 Local_Proc := Make_Temporary (Loc, 'P');
8700 Local_Body :=
8701 Make_Subprogram_Body (Loc,
8702 Specification =>
8703 Make_Procedure_Specification (Loc,
8704 Defining_Unit_Name => Local_Proc),
8705 Declarations => Declarations (Decl),
8706 Handled_Statement_Sequence =>
8707 Handled_Statement_Sequence (Decl));
8709 -- Handlers in the block may contain nested subprograms that require
8710 -- unnesting.
8712 Check_Unnesting_In_Handlers (Local_Body);
8714 Rewrite (Decl, Local_Body);
8715 Analyze (Decl);
8716 Set_Has_Nested_Subprogram (Local_Proc);
8718 Local_Call :=
8719 Make_Procedure_Call_Statement (Loc,
8720 Name => New_Occurrence_Of (Local_Proc, Loc));
8722 Insert_After (Decl, Local_Call);
8723 Analyze (Local_Call);
8725 -- The new subprogram has the same scope as the original block
8727 Set_Scope (Local_Proc, Scope (Local_Scop));
8729 -- And the entity list of the new procedure is that of the block
8731 Set_First_Entity (Local_Proc, Ent);
8733 -- Reset the scopes of all the entities to the new procedure
8735 while Present (Ent) loop
8736 Set_Scope (Ent, Local_Proc);
8737 Next_Entity (Ent);
8738 end loop;
8739 end Unnest_Block;
8741 -------------------------
8742 -- Unnest_If_Statement --
8743 -------------------------
8745 procedure Unnest_If_Statement (If_Stmt : Node_Id) is
8747 procedure Check_Stmts_For_Subp_Unnesting (Stmts : in out List_Id);
8748 -- A list of statements (that may be a list associated with a then,
8749 -- elsif, or else part of an if-statement) is traversed at the top
8750 -- level to determine whether it contains a subprogram body, and if so,
8751 -- the statements will be replaced with a new procedure body containing
8752 -- the statements followed by a call to the procedure. The individual
8753 -- statements may also be blocks, loops, or other if statements that
8754 -- themselves may require contain nested subprograms needing unnesting.
8756 procedure Check_Stmts_For_Subp_Unnesting (Stmts : in out List_Id) is
8757 Subp_Found : Boolean := False;
8759 begin
8760 if Is_Empty_List (Stmts) then
8761 return;
8762 end if;
8764 declare
8765 Stmt : Node_Id := First (Stmts);
8766 begin
8767 while Present (Stmt) loop
8768 if Nkind (Stmt) = N_Subprogram_Body then
8769 Subp_Found := True;
8770 exit;
8771 end if;
8773 Next (Stmt);
8774 end loop;
8775 end;
8777 -- The statements themselves may be blocks, loops, etc. that in turn
8778 -- contain nested subprograms requiring an unnesting transformation.
8779 -- We perform this traversal after looking for subprogram bodies, to
8780 -- avoid considering procedures created for one of those statements
8781 -- (such as a block rewritten as a procedure) as a nested subprogram
8782 -- of the statement list (which could result in an unneeded wrapper
8783 -- procedure).
8785 Check_Unnesting_In_Decls_Or_Stmts (Stmts);
8787 -- If there was a top-level subprogram body in the statement list,
8788 -- then perform an unnesting transformation on the list by replacing
8789 -- the statements with a wrapper procedure body containing the
8790 -- original statements followed by a call to that procedure.
8792 if Subp_Found then
8793 Unnest_Statement_List (Stmts);
8794 end if;
8795 end Check_Stmts_For_Subp_Unnesting;
8797 -- Local variables
8799 Then_Stmts : List_Id := Then_Statements (If_Stmt);
8800 Else_Stmts : List_Id := Else_Statements (If_Stmt);
8802 -- Start of processing for Unnest_If_Statement
8804 begin
8805 Check_Stmts_For_Subp_Unnesting (Then_Stmts);
8806 Set_Then_Statements (If_Stmt, Then_Stmts);
8808 if not Is_Empty_List (Elsif_Parts (If_Stmt)) then
8809 declare
8810 Elsif_Part : Node_Id :=
8811 First (Elsif_Parts (If_Stmt));
8812 Elsif_Stmts : List_Id;
8813 begin
8814 while Present (Elsif_Part) loop
8815 Elsif_Stmts := Then_Statements (Elsif_Part);
8817 Check_Stmts_For_Subp_Unnesting (Elsif_Stmts);
8818 Set_Then_Statements (Elsif_Part, Elsif_Stmts);
8820 Next (Elsif_Part);
8821 end loop;
8822 end;
8823 end if;
8825 Check_Stmts_For_Subp_Unnesting (Else_Stmts);
8826 Set_Else_Statements (If_Stmt, Else_Stmts);
8827 end Unnest_If_Statement;
8829 -----------------
8830 -- Unnest_Loop --
8831 -----------------
8833 procedure Unnest_Loop (Loop_Stmt : Node_Id) is
8835 procedure Fixup_Inner_Scopes (Loop_Or_Block : Node_Id);
8836 -- This procedure fixes the scope for 2 identified cases of incorrect
8837 -- scope information.
8839 -- 1) The loops created by the compiler for array aggregates can have
8840 -- nested finalization procedure when the type of the array components
8841 -- needs finalization. It has the following form:
8843 -- for J4b in 10 .. 12 loop
8844 -- declare
8845 -- procedure __finalizer;
8846 -- begin
8847 -- procedure __finalizer is
8848 -- ...
8849 -- end;
8850 -- ...
8851 -- obj (J4b) := ...;
8853 -- When the compiler creates the N_Block_Statement, it sets its scope to
8854 -- the outer scope (the one containing the loop).
8856 -- The Unnest_Loop procedure moves the N_Loop_Statement inside a new
8857 -- procedure and correctly sets the scopes for both the new procedure
8858 -- and the loop entity. The inner block scope is not modified and this
8859 -- leaves the Tree in an incoherent state (i.e. the inner procedure must
8860 -- have its enclosing procedure in its scope ancestries).
8862 -- 2) The second case happens when an object declaration is created
8863 -- within a loop used to initialize the 'others' components of an
8864 -- aggregate that is nested within a transient scope. When the transient
8865 -- scope is removed, the object scope is set to the outer scope. For
8866 -- example:
8868 -- package pack
8869 -- ...
8870 -- L98s : for J90s in 2 .. 19 loop
8871 -- B101s : declare
8872 -- R92s : aliased some_type;
8873 -- ...
8875 -- The loop L98s was initially wrapped in a transient scope B72s and
8876 -- R92s was nested within it. Then the transient scope is removed and
8877 -- the scope of R92s is set to 'pack'. And finally, when the unnester
8878 -- moves the loop body in a new procedure, R92s's scope is still left
8879 -- unchanged.
8881 -- This procedure finds the two previous patterns and fixes the scope
8882 -- information.
8884 -- Another (better) fix would be to have the block scope set to be the
8885 -- loop entity earlier (when the block is created or when the loop gets
8886 -- an actual entity set). But unfortunately this proved harder to
8887 -- implement ???
8889 procedure Fixup_Inner_Scopes (Loop_Or_Block : Node_Id) is
8890 Stmt : Node_Id;
8891 Loop_Or_Block_Ent : Entity_Id;
8892 Ent_To_Fix : Entity_Id;
8893 Decl : Node_Id := Empty;
8894 begin
8895 pragma Assert (Nkind (Loop_Or_Block) in
8896 N_Loop_Statement | N_Block_Statement);
8898 Loop_Or_Block_Ent := Entity (Identifier (Loop_Or_Block));
8899 if Nkind (Loop_Or_Block) = N_Loop_Statement then
8900 Stmt := First (Statements (Loop_Or_Block));
8901 else -- N_Block_Statement
8902 Stmt := First
8903 (Statements (Handled_Statement_Sequence (Loop_Or_Block)));
8904 Decl := First (Declarations (Loop_Or_Block));
8905 end if;
8907 -- Fix scopes for any object declaration found in the block
8908 while Present (Decl) loop
8909 if Nkind (Decl) = N_Object_Declaration then
8910 Ent_To_Fix := Defining_Identifier (Decl);
8911 Set_Scope (Ent_To_Fix, Loop_Or_Block_Ent);
8912 end if;
8913 Next (Decl);
8914 end loop;
8916 while Present (Stmt) loop
8917 if Nkind (Stmt) = N_Block_Statement
8918 and then Is_Abort_Block (Stmt)
8919 then
8920 Ent_To_Fix := Entity (Identifier (Stmt));
8921 Set_Scope (Ent_To_Fix, Loop_Or_Block_Ent);
8922 elsif Nkind (Stmt) in N_Block_Statement | N_Loop_Statement
8923 then
8924 Fixup_Inner_Scopes (Stmt);
8925 end if;
8926 Next (Stmt);
8927 end loop;
8928 end Fixup_Inner_Scopes;
8930 Loc : constant Source_Ptr := Sloc (Loop_Stmt);
8931 Ent : Entity_Id;
8932 Local_Body : Node_Id;
8933 Local_Call : Node_Id;
8934 Loop_Ent : Entity_Id;
8935 Local_Proc : Entity_Id;
8936 Loop_Copy : constant Node_Id :=
8937 Relocate_Node (Loop_Stmt);
8938 begin
8939 Loop_Ent := Entity (Identifier (Loop_Stmt));
8940 Ent := First_Entity (Loop_Ent);
8942 Local_Proc := Make_Temporary (Loc, 'P');
8944 Local_Body :=
8945 Make_Subprogram_Body (Loc,
8946 Specification =>
8947 Make_Procedure_Specification (Loc,
8948 Defining_Unit_Name => Local_Proc),
8949 Declarations => Empty_List,
8950 Handled_Statement_Sequence =>
8951 Make_Handled_Sequence_Of_Statements (Loc,
8952 Statements => New_List (Loop_Copy)));
8954 Rewrite (Loop_Stmt, Local_Body);
8955 Analyze (Loop_Stmt);
8957 Set_Has_Nested_Subprogram (Local_Proc);
8959 Local_Call :=
8960 Make_Procedure_Call_Statement (Loc,
8961 Name => New_Occurrence_Of (Local_Proc, Loc));
8963 Insert_After (Loop_Stmt, Local_Call);
8964 Analyze (Local_Call);
8966 -- New procedure has the same scope as the original loop, and the scope
8967 -- of the loop is the new procedure.
8969 Set_Scope (Local_Proc, Scope (Loop_Ent));
8970 Set_Scope (Loop_Ent, Local_Proc);
8972 Fixup_Inner_Scopes (Loop_Copy);
8974 -- The entity list of the new procedure is that of the loop
8976 Set_First_Entity (Local_Proc, Ent);
8978 -- Note that the entities associated with the loop don't need to have
8979 -- their Scope fields reset, since they're still associated with the
8980 -- same loop entity that now belongs to the copied loop statement.
8981 end Unnest_Loop;
8983 ---------------------------
8984 -- Unnest_Statement_List --
8985 ---------------------------
8987 procedure Unnest_Statement_List (Stmts : in out List_Id) is
8988 Loc : constant Source_Ptr := Sloc (First (Stmts));
8989 Local_Body : Node_Id;
8990 Local_Call : Node_Id;
8991 Local_Proc : Entity_Id;
8992 New_Stmts : constant List_Id := Empty_List;
8994 begin
8995 Local_Proc := Make_Temporary (Loc, 'P');
8997 Local_Body :=
8998 Make_Subprogram_Body (Loc,
8999 Specification =>
9000 Make_Procedure_Specification (Loc,
9001 Defining_Unit_Name => Local_Proc),
9002 Declarations => Empty_List,
9003 Handled_Statement_Sequence =>
9004 Make_Handled_Sequence_Of_Statements (Loc,
9005 Statements => Stmts));
9007 Append_To (New_Stmts, Local_Body);
9009 Analyze (Local_Body);
9011 Set_Has_Nested_Subprogram (Local_Proc);
9013 Local_Call :=
9014 Make_Procedure_Call_Statement (Loc,
9015 Name => New_Occurrence_Of (Local_Proc, Loc));
9017 Append_To (New_Stmts, Local_Call);
9018 Analyze (Local_Call);
9020 -- Traverse the statements, and for any that are declarations or
9021 -- subprogram bodies that have entities, set the Scope of those
9022 -- entities to the new procedure's Entity_Id.
9024 declare
9025 Stmt : Node_Id := First (Stmts);
9027 begin
9028 while Present (Stmt) loop
9029 case Nkind (Stmt) is
9030 when N_Declaration
9031 | N_Renaming_Declaration
9033 Set_Scope (Defining_Identifier (Stmt), Local_Proc);
9035 when N_Subprogram_Body =>
9036 Set_Scope
9037 (Defining_Unit_Name (Specification (Stmt)), Local_Proc);
9039 when others =>
9040 null;
9041 end case;
9043 Next (Stmt);
9044 end loop;
9045 end;
9047 Stmts := New_Stmts;
9048 end Unnest_Statement_List;
9050 --------------------------------
9051 -- Wrap_Transient_Declaration --
9052 --------------------------------
9054 -- If a transient scope has been established during the processing of the
9055 -- Expression of an Object_Declaration, it is not possible to wrap the
9056 -- declaration into a transient block as usual case, otherwise the object
9057 -- would be itself declared in the wrong scope. Therefore, all entities (if
9058 -- any) defined in the transient block are moved to the proper enclosing
9059 -- scope. Furthermore, if they are controlled variables they are finalized
9060 -- right after the declaration. The finalization list of the transient
9061 -- scope is defined as a renaming of the enclosing one so during their
9062 -- initialization they will be attached to the proper finalization list.
9063 -- For instance, the following declaration :
9065 -- X : Typ := F (G (A), G (B));
9067 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
9068 -- is expanded into :
9070 -- X : Typ := [ complex Expression-Action ];
9071 -- [Deep_]Finalize (_v1);
9072 -- [Deep_]Finalize (_v2);
9074 procedure Wrap_Transient_Declaration (N : Node_Id) is
9075 Curr_S : Entity_Id;
9076 Encl_S : Entity_Id;
9078 begin
9079 Curr_S := Current_Scope;
9080 Encl_S := Scope (Curr_S);
9082 -- Insert all actions including cleanup generated while analyzing or
9083 -- expanding the transient context back into the tree. Manage the
9084 -- secondary stack when the object declaration appears in a library
9085 -- level package [body].
9087 Insert_Actions_In_Scope_Around
9088 (N => N,
9089 Clean => True,
9090 Manage_SS =>
9091 Uses_Sec_Stack (Curr_S)
9092 and then Nkind (N) = N_Object_Declaration
9093 and then Ekind (Encl_S) in E_Package | E_Package_Body
9094 and then Is_Library_Level_Entity (Encl_S));
9095 Pop_Scope;
9097 -- Relocate local entities declared within the transient scope to the
9098 -- enclosing scope. This action sets their Is_Public flag accordingly.
9100 Transfer_Entities (Curr_S, Encl_S);
9102 -- Mark the enclosing dynamic scope to ensure that the secondary stack
9103 -- is properly released upon exiting the said scope.
9105 if Uses_Sec_Stack (Curr_S) then
9106 Curr_S := Enclosing_Dynamic_Scope (Curr_S);
9108 -- Do not mark a function that returns on the secondary stack as the
9109 -- reclamation is done by the caller.
9111 if Ekind (Curr_S) = E_Function
9112 and then Needs_Secondary_Stack (Etype (Curr_S))
9113 then
9114 null;
9116 -- Otherwise mark the enclosing dynamic scope
9118 else
9119 Set_Uses_Sec_Stack (Curr_S);
9120 Check_Restriction (No_Secondary_Stack, N);
9121 end if;
9122 end if;
9123 end Wrap_Transient_Declaration;
9125 -------------------------------
9126 -- Wrap_Transient_Expression --
9127 -------------------------------
9129 procedure Wrap_Transient_Expression (N : Node_Id) is
9130 Loc : constant Source_Ptr := Sloc (N);
9131 Expr : Node_Id := Relocate_Node (N);
9132 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
9133 Typ : constant Entity_Id := Etype (N);
9135 begin
9136 -- Generate:
9138 -- Temp : Typ;
9139 -- declare
9140 -- M : constant Mark_Id := SS_Mark;
9141 -- procedure Finalizer is ... (See Build_Finalizer)
9143 -- begin
9144 -- Temp := <Expr>; -- general case
9145 -- Temp := (if <Expr> then True else False); -- boolean case
9147 -- at end
9148 -- Finalizer;
9149 -- end;
9151 -- A special case is made for Boolean expressions so that the back end
9152 -- knows to generate a conditional branch instruction, if running with
9153 -- -fpreserve-control-flow. This ensures that a control-flow change
9154 -- signaling the decision outcome occurs before the cleanup actions.
9156 if Opt.Suppress_Control_Flow_Optimizations
9157 and then Is_Boolean_Type (Typ)
9158 then
9159 Expr :=
9160 Make_If_Expression (Loc,
9161 Expressions => New_List (
9162 Expr,
9163 New_Occurrence_Of (Standard_True, Loc),
9164 New_Occurrence_Of (Standard_False, Loc)));
9165 end if;
9167 Insert_Actions (N, New_List (
9168 Make_Object_Declaration (Loc,
9169 Defining_Identifier => Temp,
9170 Object_Definition => New_Occurrence_Of (Typ, Loc)),
9172 Make_Transient_Block (Loc,
9173 Action =>
9174 Make_Assignment_Statement (Loc,
9175 Name => New_Occurrence_Of (Temp, Loc),
9176 Expression => Expr),
9177 Par => Parent (N))));
9179 if Debug_Generated_Code then
9180 Set_Debug_Info_Needed (Temp);
9181 end if;
9183 Rewrite (N, New_Occurrence_Of (Temp, Loc));
9184 Analyze_And_Resolve (N, Typ);
9185 end Wrap_Transient_Expression;
9187 ------------------------------
9188 -- Wrap_Transient_Statement --
9189 ------------------------------
9191 procedure Wrap_Transient_Statement (N : Node_Id) is
9192 Loc : constant Source_Ptr := Sloc (N);
9193 New_Stmt : constant Node_Id := Relocate_Node (N);
9195 begin
9196 -- Generate:
9197 -- declare
9198 -- M : constant Mark_Id := SS_Mark;
9199 -- procedure Finalizer is ... (See Build_Finalizer)
9201 -- begin
9202 -- <New_Stmt>;
9204 -- at end
9205 -- Finalizer;
9206 -- end;
9208 Rewrite (N,
9209 Make_Transient_Block (Loc,
9210 Action => New_Stmt,
9211 Par => Parent (N)));
9213 -- With the scope stack back to normal, we can call analyze on the
9214 -- resulting block. At this point, the transient scope is being
9215 -- treated like a perfectly normal scope, so there is nothing
9216 -- special about it.
9218 -- Note: Wrap_Transient_Statement is called with the node already
9219 -- analyzed (i.e. Analyzed (N) is True). This is important, since
9220 -- otherwise we would get a recursive processing of the node when
9221 -- we do this Analyze call.
9223 Analyze (N);
9224 end Wrap_Transient_Statement;
9226 end Exp_Ch7;