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