comparison gcc/ada/exp_ch7.adb @ 111:04ced10e8804

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