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