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