compiler: Do not declare type switch variable outside case statements.
[official-gcc.git] / gcc / ada / exp_ch7.adb
blob2c6683d0ff66ab875028ce5ef4e3e4cd3ce51375
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-2015, Free Software Foundation, Inc. --
10 -- --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- This package contains virtually all expansion mechanisms related to
27 -- - controlled types
28 -- - transient scopes
30 with Atree; use Atree;
31 with Debug; use Debug;
32 with Einfo; use Einfo;
33 with 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 Targparm; use Targparm;
64 with Tbuild; use Tbuild;
65 with Ttypes; use Ttypes;
66 with Uintp; use Uintp;
68 package body Exp_Ch7 is
70 --------------------------------
71 -- Transient Scope Management --
72 --------------------------------
74 -- A transient scope is created when temporary objects are created by the
75 -- compiler. These temporary objects are allocated on the secondary stack
76 -- and the transient scope is responsible for finalizing the object when
77 -- appropriate and reclaiming the memory at the right time. The temporary
78 -- objects are generally the objects allocated to store the result of a
79 -- function returning an unconstrained or a tagged value. Expressions
80 -- needing to be wrapped in a transient scope (functions calls returning
81 -- unconstrained or tagged values) may appear in 3 different contexts which
82 -- lead to 3 different kinds of transient scope expansion:
84 -- 1. In a simple statement (procedure call, assignment, ...). In this
85 -- case the instruction is wrapped into a transient block. See
86 -- Wrap_Transient_Statement for details.
88 -- 2. In an expression of a control structure (test in a IF statement,
89 -- expression in a CASE statement, ...). See Wrap_Transient_Expression
90 -- for details.
92 -- 3. In a expression of an object_declaration. No wrapping is possible
93 -- here, so the finalization actions, if any, are done right after the
94 -- declaration and the secondary stack deallocation is done in the
95 -- proper enclosing scope. See Wrap_Transient_Declaration for details.
97 -- Note about functions returning tagged types: it has been decided to
98 -- always allocate their result in the secondary stack, even though is not
99 -- absolutely mandatory when the tagged type is constrained because the
100 -- caller knows the size of the returned object and thus could allocate the
101 -- result in the primary stack. An exception to this is when the function
102 -- builds its result in place, as is done for functions with inherently
103 -- limited result types for Ada 2005. In that case, certain callers may
104 -- pass the address of a constrained object as the target object for the
105 -- function result.
107 -- By allocating tagged results in the secondary stack a number of
108 -- implementation difficulties are avoided:
110 -- - If it is a dispatching function call, the computation of the size of
111 -- the result is possible but complex from the outside.
113 -- - If the returned type is controlled, the assignment of the returned
114 -- value to the anonymous object involves an Adjust, and we have no
115 -- easy way to access the anonymous object created by the back end.
117 -- - If the returned type is class-wide, this is an unconstrained type
118 -- anyway.
120 -- Furthermore, the small loss in efficiency which is the result of this
121 -- decision is not such a big deal because functions returning tagged types
122 -- are not as common in practice compared to functions returning access to
123 -- a tagged type.
125 --------------------------------------------------
126 -- Transient Blocks and Finalization Management --
127 --------------------------------------------------
129 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id;
130 -- N is a node which may generate a transient scope. Loop over the parent
131 -- pointers of N until it find the appropriate node to wrap. If it returns
132 -- Empty, it means that no transient scope is needed in this context.
134 procedure Insert_Actions_In_Scope_Around
135 (N : Node_Id;
136 Clean : Boolean;
137 Manage_SS : Boolean);
138 -- Insert the before-actions kept in the scope stack before N, and the
139 -- after-actions after N, which must be a member of a list. If flag Clean
140 -- is set, insert any cleanup actions. If flag Manage_SS is set, insert
141 -- calls to mark and release the secondary stack.
143 function Make_Transient_Block
144 (Loc : Source_Ptr;
145 Action : Node_Id;
146 Par : Node_Id) return Node_Id;
147 -- Action is a single statement or object declaration. Par is the proper
148 -- parent of the generated block. Create a transient block whose name is
149 -- the current scope and the only handled statement is Action. If Action
150 -- involves controlled objects or secondary stack usage, the corresponding
151 -- cleanup actions are performed at the end of the block.
153 procedure Set_Node_To_Be_Wrapped (N : Node_Id);
154 -- Set the field Node_To_Be_Wrapped of the current scope
156 -- ??? The entire comment needs to be rewritten
157 -- ??? which entire comment?
159 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
160 -- Shared processing for Store_xxx_Actions_In_Scope
162 -----------------------------
163 -- Finalization Management --
164 -----------------------------
166 -- This part describe how Initialization/Adjustment/Finalization procedures
167 -- are generated and called. Two cases must be considered, types that are
168 -- Controlled (Is_Controlled flag set) and composite types that contain
169 -- controlled components (Has_Controlled_Component flag set). In the first
170 -- case the procedures to call are the user-defined primitive operations
171 -- Initialize/Adjust/Finalize. In the second case, GNAT generates
172 -- Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
173 -- of calling the former procedures on the controlled components.
175 -- For records with Has_Controlled_Component set, a hidden "controller"
176 -- component is inserted. This controller component contains its own
177 -- finalization list on which all controlled components are attached
178 -- creating an indirection on the upper-level Finalization list. This
179 -- technique facilitates the management of objects whose number of
180 -- controlled components changes during execution. This controller
181 -- component is itself controlled and is attached to the upper-level
182 -- finalization chain. Its adjust primitive is in charge of calling adjust
183 -- on the components and adjusting the finalization pointer to match their
184 -- new location (see a-finali.adb).
186 -- It is not possible to use a similar technique for arrays that have
187 -- Has_Controlled_Component set. In this case, deep procedures are
188 -- generated that call initialize/adjust/finalize + attachment or
189 -- detachment on the finalization list for all component.
191 -- Initialize calls: they are generated for declarations or dynamic
192 -- allocations of Controlled objects with no initial value. They are always
193 -- followed by an attachment to the current Finalization Chain. For the
194 -- dynamic allocation case this the chain attached to the scope of the
195 -- access type definition otherwise, this is the chain of the current
196 -- scope.
198 -- Adjust Calls: They are generated on 2 occasions: (1) for declarations
199 -- or dynamic allocations of Controlled objects with an initial value.
200 -- (2) after an assignment. In the first case they are followed by an
201 -- attachment to the final chain, in the second case they are not.
203 -- Finalization Calls: They are generated on (1) scope exit, (2)
204 -- assignments, (3) unchecked deallocations. In case (3) they have to
205 -- be detached from the final chain, in case (2) they must not and in
206 -- case (1) this is not important since we are exiting the scope anyway.
208 -- Other details:
210 -- Type extensions will have a new record controller at each derivation
211 -- level containing controlled components. The record controller for
212 -- the parent/ancestor is attached to the finalization list of the
213 -- extension's record controller (i.e. the parent is like a component
214 -- of the extension).
216 -- For types that are both Is_Controlled and Has_Controlled_Components,
217 -- the record controller and the object itself are handled separately.
218 -- It could seem simpler to attach the object at the end of its record
219 -- controller but this would not tackle view conversions properly.
221 -- A classwide type can always potentially have controlled components
222 -- but the record controller of the corresponding actual type may not
223 -- be known at compile time so the dispatch table contains a special
224 -- field that allows computation of the offset of the record controller
225 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
227 -- Here is a simple example of the expansion of a controlled block :
229 -- declare
230 -- X : Controlled;
231 -- Y : Controlled := Init;
233 -- type R is record
234 -- C : Controlled;
235 -- end record;
236 -- W : R;
237 -- Z : R := (C => X);
239 -- begin
240 -- X := Y;
241 -- W := Z;
242 -- end;
244 -- is expanded into
246 -- declare
247 -- _L : System.FI.Finalizable_Ptr;
249 -- procedure _Clean is
250 -- begin
251 -- Abort_Defer;
252 -- System.FI.Finalize_List (_L);
253 -- Abort_Undefer;
254 -- end _Clean;
256 -- X : Controlled;
257 -- begin
258 -- Abort_Defer;
259 -- Initialize (X);
260 -- Attach_To_Final_List (_L, Finalizable (X), 1);
261 -- at end: Abort_Undefer;
262 -- Y : Controlled := Init;
263 -- Adjust (Y);
264 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
266 -- type R is record
267 -- C : Controlled;
268 -- end record;
269 -- W : R;
270 -- begin
271 -- Abort_Defer;
272 -- Deep_Initialize (W, _L, 1);
273 -- at end: Abort_Under;
274 -- Z : R := (C => X);
275 -- Deep_Adjust (Z, _L, 1);
277 -- begin
278 -- _Assign (X, Y);
279 -- Deep_Finalize (W, False);
280 -- <save W's final pointers>
281 -- W := Z;
282 -- <restore W's final pointers>
283 -- Deep_Adjust (W, _L, 0);
284 -- at end
285 -- _Clean;
286 -- end;
288 type Final_Primitives is
289 (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
290 -- This enumeration type is defined in order to ease sharing code for
291 -- building finalization procedures for composite types.
293 Name_Of : constant array (Final_Primitives) of Name_Id :=
294 (Initialize_Case => Name_Initialize,
295 Adjust_Case => Name_Adjust,
296 Finalize_Case => Name_Finalize,
297 Address_Case => Name_Finalize_Address);
298 Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
299 (Initialize_Case => TSS_Deep_Initialize,
300 Adjust_Case => TSS_Deep_Adjust,
301 Finalize_Case => TSS_Deep_Finalize,
302 Address_Case => TSS_Finalize_Address);
304 procedure Build_Array_Deep_Procs (Typ : Entity_Id);
305 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
306 -- Has_Controlled_Component set and store them using the TSS mechanism.
308 function Build_Cleanup_Statements
309 (N : Node_Id;
310 Additional_Cleanup : List_Id) return List_Id;
311 -- Create the clean up calls for an asynchronous call block, task master,
312 -- protected subprogram body, task allocation block or task body, or
313 -- additional cleanup actions parked on a transient block. If the context
314 -- does not contain the above constructs, the routine returns an empty
315 -- list.
317 procedure Build_Finalizer
318 (N : Node_Id;
319 Clean_Stmts : List_Id;
320 Mark_Id : Entity_Id;
321 Top_Decls : List_Id;
322 Defer_Abort : Boolean;
323 Fin_Id : out Entity_Id);
324 -- N may denote an accept statement, block, entry body, package body,
325 -- package spec, protected body, subprogram body, or a task body. Create
326 -- a procedure which contains finalization calls for all controlled objects
327 -- declared in the declarative or statement region of N. The calls are
328 -- built in reverse order relative to the original declarations. In the
329 -- case of a task body, the routine delays the creation of the finalizer
330 -- until all statements have been moved to the task body procedure.
331 -- Clean_Stmts may contain additional context-dependent code used to abort
332 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
333 -- Mark_Id is the secondary stack used in the current context or Empty if
334 -- missing. Top_Decls is the list on which the declaration of the finalizer
335 -- is attached in the non-package case. Defer_Abort indicates that the
336 -- statements passed in perform actions that require abort to be deferred,
337 -- such as for task termination. Fin_Id is the finalizer declaration
338 -- entity.
340 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
341 -- N is a construct which contains a handled sequence of statements, Fin_Id
342 -- is the entity of a finalizer. Create an At_End handler which covers the
343 -- statements of N and calls Fin_Id. If the handled statement sequence has
344 -- an exception handler, the statements will be wrapped in a block to avoid
345 -- unwanted interaction with the new At_End handler.
347 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
348 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
349 -- Has_Component_Component set and store them using the TSS mechanism.
351 procedure Check_Visibly_Controlled
352 (Prim : Final_Primitives;
353 Typ : Entity_Id;
354 E : in out Entity_Id;
355 Cref : in out Node_Id);
356 -- The controlled operation declared for a derived type may not be
357 -- overriding, if the controlled operations of the parent type are hidden,
358 -- for example when the parent is a private type whose full view is
359 -- controlled. For other primitive operations we modify the name of the
360 -- operation to indicate that it is not overriding, but this is not
361 -- possible for Initialize, etc. because they have to be retrievable by
362 -- name. Before generating the proper call to one of these operations we
363 -- check whether Typ is known to be controlled at the point of definition.
364 -- If it is not then we must retrieve the hidden operation of the parent
365 -- and use it instead. This is one case that might be solved more cleanly
366 -- once Overriding pragmas or declarations are in place.
368 function Convert_View
369 (Proc : Entity_Id;
370 Arg : Node_Id;
371 Ind : Pos := 1) return Node_Id;
372 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
373 -- argument being passed to it. Ind indicates which formal of procedure
374 -- Proc we are trying to match. This function will, if necessary, generate
375 -- a conversion between the partial and full view of Arg to match the type
376 -- of the formal of Proc, or force a conversion to the class-wide type in
377 -- the case where the operation is abstract.
379 function Enclosing_Function (E : Entity_Id) return Entity_Id;
380 -- Given an arbitrary entity, traverse the scope chain looking for the
381 -- first enclosing function. Return Empty if no function was found.
383 function Make_Call
384 (Loc : Source_Ptr;
385 Proc_Id : Entity_Id;
386 Param : Node_Id;
387 Skip_Self : Boolean := False) return Node_Id;
388 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
389 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
390 -- an adjust or finalization call. Wnen flag Skip_Self is set, the related
391 -- action has an effect on the components only (if any).
393 function Make_Deep_Proc
394 (Prim : Final_Primitives;
395 Typ : Entity_Id;
396 Stmts : List_Id) return Node_Id;
397 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
398 -- Deep_Finalize procedures according to the first parameter, these
399 -- procedures operate on the type Typ. The Stmts parameter gives the body
400 -- of the procedure.
402 function Make_Deep_Array_Body
403 (Prim : Final_Primitives;
404 Typ : Entity_Id) return List_Id;
405 -- This function generates the list of statements for implementing
406 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
407 -- the first parameter, these procedures operate on the array type Typ.
409 function Make_Deep_Record_Body
410 (Prim : Final_Primitives;
411 Typ : Entity_Id;
412 Is_Local : Boolean := False) return List_Id;
413 -- This function generates the list of statements for implementing
414 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
415 -- the first parameter, these procedures operate on the record type Typ.
416 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
417 -- whether the inner logic should be dictated by state counters.
419 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
420 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
421 -- Make_Deep_Record_Body. Generate the following statements:
423 -- declare
424 -- type Acc_Typ is access all Typ;
425 -- for Acc_Typ'Storage_Size use 0;
426 -- begin
427 -- [Deep_]Finalize (Acc_Typ (V).all);
428 -- end;
430 ----------------------------
431 -- Build_Array_Deep_Procs --
432 ----------------------------
434 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
435 begin
436 Set_TSS (Typ,
437 Make_Deep_Proc
438 (Prim => Initialize_Case,
439 Typ => Typ,
440 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
442 if not Is_Limited_View (Typ) then
443 Set_TSS (Typ,
444 Make_Deep_Proc
445 (Prim => Adjust_Case,
446 Typ => Typ,
447 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
448 end if;
450 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
451 -- suppressed since these routine will not be used.
453 if not Restriction_Active (No_Finalization) then
454 Set_TSS (Typ,
455 Make_Deep_Proc
456 (Prim => Finalize_Case,
457 Typ => Typ,
458 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
460 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
461 -- .NET do not support address arithmetic and unchecked conversions.
463 if VM_Target = No_VM then
464 Set_TSS (Typ,
465 Make_Deep_Proc
466 (Prim => Address_Case,
467 Typ => Typ,
468 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
469 end if;
470 end if;
471 end Build_Array_Deep_Procs;
473 ------------------------------
474 -- Build_Cleanup_Statements --
475 ------------------------------
477 function Build_Cleanup_Statements
478 (N : Node_Id;
479 Additional_Cleanup : List_Id) return List_Id
481 Is_Asynchronous_Call : constant Boolean :=
482 Nkind (N) = N_Block_Statement
483 and then Is_Asynchronous_Call_Block (N);
484 Is_Master : constant Boolean :=
485 Nkind (N) /= N_Entry_Body
486 and then Is_Task_Master (N);
487 Is_Protected_Body : constant Boolean :=
488 Nkind (N) = N_Subprogram_Body
489 and then Is_Protected_Subprogram_Body (N);
490 Is_Task_Allocation : constant Boolean :=
491 Nkind (N) = N_Block_Statement
492 and then Is_Task_Allocation_Block (N);
493 Is_Task_Body : constant Boolean :=
494 Nkind (Original_Node (N)) = N_Task_Body;
496 Loc : constant Source_Ptr := Sloc (N);
497 Stmts : constant List_Id := New_List;
499 begin
500 if Is_Task_Body then
501 if Restricted_Profile then
502 Append_To (Stmts,
503 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
504 else
505 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
506 end if;
508 elsif Is_Master then
509 if Restriction_Active (No_Task_Hierarchy) = False then
510 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
511 end if;
513 -- Add statements to unlock the protected object parameter and to
514 -- undefer abort. If the context is a protected procedure and the object
515 -- has entries, call the entry service routine.
517 -- NOTE: The generated code references _object, a parameter to the
518 -- procedure.
520 elsif Is_Protected_Body then
521 declare
522 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
523 Conc_Typ : Entity_Id;
524 Param : Node_Id;
525 Param_Typ : Entity_Id;
527 begin
528 -- Find the _object parameter representing the protected object
530 Param := First (Parameter_Specifications (Spec));
531 loop
532 Param_Typ := Etype (Parameter_Type (Param));
534 if Ekind (Param_Typ) = E_Record_Type then
535 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
536 end if;
538 exit when No (Param) or else Present (Conc_Typ);
539 Next (Param);
540 end loop;
542 pragma Assert (Present (Param));
544 -- Historical note: In earlier versions of GNAT, there was code
545 -- at this point to generate stuff to service entry queues. It is
546 -- now abstracted in Build_Protected_Subprogram_Call_Cleanup.
548 Build_Protected_Subprogram_Call_Cleanup
549 (Specification (N), Conc_Typ, Loc, Stmts);
550 end;
552 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
553 -- tasks. Other unactivated tasks are completed by Complete_Task or
554 -- Complete_Master.
556 -- NOTE: The generated code references _chain, a local object
558 elsif Is_Task_Allocation then
560 -- Generate:
561 -- Expunge_Unactivated_Tasks (_chain);
563 -- where _chain is the list of tasks created by the allocator but not
564 -- yet activated. This list will be empty unless the block completes
565 -- abnormally.
567 Append_To (Stmts,
568 Make_Procedure_Call_Statement (Loc,
569 Name =>
570 New_Occurrence_Of
571 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
572 Parameter_Associations => New_List (
573 New_Occurrence_Of (Activation_Chain_Entity (N), Loc))));
575 -- Attempt to cancel an asynchronous entry call whenever the block which
576 -- contains the abortable part is exited.
578 -- NOTE: The generated code references Cnn, a local object
580 elsif Is_Asynchronous_Call then
581 declare
582 Cancel_Param : constant Entity_Id :=
583 Entry_Cancel_Parameter (Entity (Identifier (N)));
585 begin
586 -- If it is of type Communication_Block, this must be a protected
587 -- entry call. Generate:
589 -- if Enqueued (Cancel_Param) then
590 -- Cancel_Protected_Entry_Call (Cancel_Param);
591 -- end if;
593 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
594 Append_To (Stmts,
595 Make_If_Statement (Loc,
596 Condition =>
597 Make_Function_Call (Loc,
598 Name =>
599 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
600 Parameter_Associations => New_List (
601 New_Occurrence_Of (Cancel_Param, Loc))),
603 Then_Statements => New_List (
604 Make_Procedure_Call_Statement (Loc,
605 Name =>
606 New_Occurrence_Of
607 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
608 Parameter_Associations => New_List (
609 New_Occurrence_Of (Cancel_Param, Loc))))));
611 -- Asynchronous delay, generate:
612 -- Cancel_Async_Delay (Cancel_Param);
614 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
615 Append_To (Stmts,
616 Make_Procedure_Call_Statement (Loc,
617 Name =>
618 New_Occurrence_Of (RTE (RE_Cancel_Async_Delay), Loc),
619 Parameter_Associations => New_List (
620 Make_Attribute_Reference (Loc,
621 Prefix =>
622 New_Occurrence_Of (Cancel_Param, Loc),
623 Attribute_Name => Name_Unchecked_Access))));
625 -- Task entry call, generate:
626 -- Cancel_Task_Entry_Call (Cancel_Param);
628 else
629 Append_To (Stmts,
630 Make_Procedure_Call_Statement (Loc,
631 Name =>
632 New_Occurrence_Of (RTE (RE_Cancel_Task_Entry_Call), Loc),
633 Parameter_Associations => New_List (
634 New_Occurrence_Of (Cancel_Param, Loc))));
635 end if;
636 end;
637 end if;
639 Append_List_To (Stmts, Additional_Cleanup);
640 return Stmts;
641 end Build_Cleanup_Statements;
643 -----------------------------
644 -- Build_Controlling_Procs --
645 -----------------------------
647 procedure Build_Controlling_Procs (Typ : Entity_Id) is
648 begin
649 if Is_Array_Type (Typ) then
650 Build_Array_Deep_Procs (Typ);
651 else pragma Assert (Is_Record_Type (Typ));
652 Build_Record_Deep_Procs (Typ);
653 end if;
654 end Build_Controlling_Procs;
656 -----------------------------
657 -- Build_Exception_Handler --
658 -----------------------------
660 function Build_Exception_Handler
661 (Data : Finalization_Exception_Data;
662 For_Library : Boolean := False) return Node_Id
664 Actuals : List_Id;
665 Proc_To_Call : Entity_Id;
666 Except : Node_Id;
667 Stmts : List_Id;
669 begin
670 pragma Assert (Present (Data.Raised_Id));
672 if Exception_Extra_Info
673 or else (For_Library and not Restricted_Profile)
674 then
675 if Exception_Extra_Info then
677 -- Generate:
679 -- Get_Current_Excep.all
681 Except :=
682 Make_Function_Call (Data.Loc,
683 Name =>
684 Make_Explicit_Dereference (Data.Loc,
685 Prefix =>
686 New_Occurrence_Of
687 (RTE (RE_Get_Current_Excep), Data.Loc)));
689 else
690 -- Generate:
692 -- null
694 Except := Make_Null (Data.Loc);
695 end if;
697 if For_Library and then not Restricted_Profile then
698 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
699 Actuals := New_List (Except);
701 else
702 Proc_To_Call := RTE (RE_Save_Occurrence);
704 -- The dereference occurs only when Exception_Extra_Info is true,
705 -- and therefore Except is not null.
707 Actuals :=
708 New_List (
709 New_Occurrence_Of (Data.E_Id, Data.Loc),
710 Make_Explicit_Dereference (Data.Loc, Except));
711 end if;
713 -- Generate:
715 -- when others =>
716 -- if not Raised_Id then
717 -- Raised_Id := True;
719 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
720 -- or
721 -- Save_Library_Occurrence (Get_Current_Excep.all);
722 -- end if;
724 Stmts :=
725 New_List (
726 Make_If_Statement (Data.Loc,
727 Condition =>
728 Make_Op_Not (Data.Loc,
729 Right_Opnd => New_Occurrence_Of (Data.Raised_Id, Data.Loc)),
731 Then_Statements => New_List (
732 Make_Assignment_Statement (Data.Loc,
733 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
734 Expression => New_Occurrence_Of (Standard_True, Data.Loc)),
736 Make_Procedure_Call_Statement (Data.Loc,
737 Name =>
738 New_Occurrence_Of (Proc_To_Call, Data.Loc),
739 Parameter_Associations => Actuals))));
741 else
742 -- Generate:
744 -- Raised_Id := True;
746 Stmts := New_List (
747 Make_Assignment_Statement (Data.Loc,
748 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
749 Expression => New_Occurrence_Of (Standard_True, Data.Loc)));
750 end if;
752 -- Generate:
754 -- when others =>
756 return
757 Make_Exception_Handler (Data.Loc,
758 Exception_Choices => New_List (Make_Others_Choice (Data.Loc)),
759 Statements => Stmts);
760 end Build_Exception_Handler;
762 -------------------------------
763 -- Build_Finalization_Master --
764 -------------------------------
766 procedure Build_Finalization_Master
767 (Typ : Entity_Id;
768 For_Anonymous : Boolean := False;
769 For_Private : Boolean := False;
770 Context_Scope : Entity_Id := Empty;
771 Insertion_Node : Node_Id := Empty)
773 procedure Add_Pending_Access_Type
774 (Typ : Entity_Id;
775 Ptr_Typ : Entity_Id);
776 -- Add access type Ptr_Typ to the pending access type list for type Typ
778 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
779 -- Determine whether entity E is inside a wrapper package created for
780 -- an instance of Ada.Unchecked_Deallocation.
782 -----------------------------
783 -- Add_Pending_Access_Type --
784 -----------------------------
786 procedure Add_Pending_Access_Type
787 (Typ : Entity_Id;
788 Ptr_Typ : Entity_Id)
790 List : Elist_Id;
792 begin
793 if Present (Pending_Access_Types (Typ)) then
794 List := Pending_Access_Types (Typ);
795 else
796 List := New_Elmt_List;
797 Set_Pending_Access_Types (Typ, List);
798 end if;
800 Prepend_Elmt (Ptr_Typ, List);
801 end Add_Pending_Access_Type;
803 ------------------------------
804 -- In_Deallocation_Instance --
805 ------------------------------
807 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
808 Pkg : constant Entity_Id := Scope (E);
809 Par : Node_Id := Empty;
811 begin
812 if Ekind (Pkg) = E_Package
813 and then Present (Related_Instance (Pkg))
814 and then Ekind (Related_Instance (Pkg)) = E_Procedure
815 then
816 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
818 return
819 Present (Par)
820 and then Chars (Par) = Name_Unchecked_Deallocation
821 and then Chars (Scope (Par)) = Name_Ada
822 and then Scope (Scope (Par)) = Standard_Standard;
823 end if;
825 return False;
826 end In_Deallocation_Instance;
828 -- Local variables
830 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
832 Ptr_Typ : constant Entity_Id := Root_Type_Of_Full_View (Base_Type (Typ));
833 -- A finalization master created for a named access type is associated
834 -- with the full view (if applicable) as a consequence of freezing. The
835 -- full view criteria does not apply to anonymous access types because
836 -- those cannot have a private and a full view.
838 -- Start of processing for Build_Finalization_Master
840 begin
841 -- Certain run-time configurations and targets do not provide support
842 -- for controlled types.
844 if Restriction_Active (No_Finalization) then
845 return;
847 -- Do not process C, C++, CIL and Java types since it is assumend that
848 -- the non-Ada side will handle their clean up.
850 elsif Convention (Desig_Typ) = Convention_C
851 or else Convention (Desig_Typ) = Convention_CIL
852 or else Convention (Desig_Typ) = Convention_CPP
853 or else Convention (Desig_Typ) = Convention_Java
854 then
855 return;
857 -- Various machinery such as freezing may have already created a
858 -- finalization master.
860 elsif Present (Finalization_Master (Ptr_Typ)) then
861 return;
863 -- Do not process types that return on the secondary stack
865 elsif Present (Associated_Storage_Pool (Ptr_Typ))
866 and then Is_RTE (Associated_Storage_Pool (Ptr_Typ), RE_SS_Pool)
867 then
868 return;
870 -- Do not process types which may never allocate an object
872 elsif No_Pool_Assigned (Ptr_Typ) then
873 return;
875 -- Do not process access types coming from Ada.Unchecked_Deallocation
876 -- instances. Even though the designated type may be controlled, the
877 -- access type will never participate in allocation.
879 elsif In_Deallocation_Instance (Ptr_Typ) then
880 return;
882 -- Ignore the general use of anonymous access types unless the context
883 -- requires a finalization master.
885 elsif Ekind (Ptr_Typ) = E_Anonymous_Access_Type
886 and then not For_Anonymous
887 then
888 return;
890 -- Do not process non-library access types when restriction No_Nested_
891 -- Finalization is in effect since masters are controlled objects.
893 elsif Restriction_Active (No_Nested_Finalization)
894 and then not Is_Library_Level_Entity (Ptr_Typ)
895 then
896 return;
898 -- For .NET/JVM targets, allow the processing of access-to-controlled
899 -- types where the designated type is explicitly derived from [Limited_]
900 -- Controlled.
902 elsif VM_Target /= No_VM and then not Is_Controlled (Desig_Typ) then
903 return;
905 -- Do not create finalization masters in GNATprove mode because this
906 -- unwanted extra expansion. A compilation in this mode keeps the tree
907 -- as close as possible to the original sources.
909 elsif GNATprove_Mode then
910 return;
911 end if;
913 declare
914 Actions : constant List_Id := New_List;
915 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
916 Fin_Mas_Id : Entity_Id;
917 Pool_Id : Entity_Id;
919 begin
920 -- Source access types use fixed master names since the master is
921 -- inserted in the same source unit only once. The only exception to
922 -- this are instances using the same access type as generic actual.
924 if Comes_From_Source (Ptr_Typ) and then not Inside_A_Generic then
925 Fin_Mas_Id :=
926 Make_Defining_Identifier (Loc,
927 Chars => New_External_Name (Chars (Ptr_Typ), "FM"));
929 -- Internally generated access types use temporaries as their names
930 -- due to possible collision with identical names coming from other
931 -- packages.
933 else
934 Fin_Mas_Id := Make_Temporary (Loc, 'F');
935 end if;
937 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
939 -- Generate:
940 -- <Ptr_Typ>FM : aliased Finalization_Master;
942 Append_To (Actions,
943 Make_Object_Declaration (Loc,
944 Defining_Identifier => Fin_Mas_Id,
945 Aliased_Present => True,
946 Object_Definition =>
947 New_Occurrence_Of (RTE (RE_Finalization_Master), Loc)));
949 -- Set the associated pool and primitive Finalize_Address of the new
950 -- finalization master. This step is skipped on .NET/JVM because the
951 -- target does not support storage pools or address arithmetic.
953 if VM_Target = No_VM then
955 -- The access type has a user-defined storage pool, use it
957 if Present (Associated_Storage_Pool (Ptr_Typ)) then
958 Pool_Id := Associated_Storage_Pool (Ptr_Typ);
960 -- Otherwise the default choice is the global storage pool
962 else
963 Pool_Id := RTE (RE_Global_Pool_Object);
964 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
965 end if;
967 -- Generate:
968 -- Set_Base_Pool (<Ptr_Typ>FM, Pool_Id'Unchecked_Access);
970 Append_To (Actions,
971 Make_Procedure_Call_Statement (Loc,
972 Name =>
973 New_Occurrence_Of (RTE (RE_Set_Base_Pool), Loc),
974 Parameter_Associations => New_List (
975 New_Occurrence_Of (Fin_Mas_Id, Loc),
976 Make_Attribute_Reference (Loc,
977 Prefix => New_Occurrence_Of (Pool_Id, Loc),
978 Attribute_Name => Name_Unrestricted_Access))));
980 -- Finalize_Address is not generated in CodePeer mode because the
981 -- body contains address arithmetic. Skip this step.
983 if CodePeer_Mode then
984 null;
986 -- Associate the Finalize_Address primitive of the designated type
987 -- with the finalization master of the access type. The designated
988 -- type must be forzen as Finalize_Address is generated when the
989 -- freeze node is expanded.
991 elsif Is_Frozen (Desig_Typ)
992 and then Present (Finalize_Address (Desig_Typ))
994 -- The finalization master of an anonymous access type may need
995 -- to be inserted in a specific place in the tree. For instance:
997 -- type Comp_Typ;
999 -- <finalization master of "access Comp_Typ">
1001 -- type Rec_Typ is record
1002 -- Comp : access Comp_Typ;
1003 -- end record;
1005 -- <freeze node for Comp_Typ>
1006 -- <freeze node for Rec_Typ>
1008 -- Due to this oddity, the anonymous access type is stored for
1009 -- later processing (see below).
1011 and then Ekind (Ptr_Typ) /= E_Anonymous_Access_Type
1012 then
1013 -- Generate:
1014 -- Set_Finalize_Address
1015 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
1017 Append_To (Actions,
1018 Make_Set_Finalize_Address_Call
1019 (Loc => Loc,
1020 Ptr_Typ => Ptr_Typ));
1022 -- Otherwise the designated type is either anonymous access or a
1023 -- Taft-amendment type and has not been frozen. Store the access
1024 -- type for later processing (see Freeze_Type).
1026 else
1027 Add_Pending_Access_Type (Desig_Typ, Ptr_Typ);
1028 end if;
1029 end if;
1031 -- A finalization master created for an anonymous access type or an
1032 -- access designating a type with private components must be inserted
1033 -- before a context-dependent node.
1035 if For_Anonymous or For_Private then
1037 -- At this point both the scope of the context and the insertion
1038 -- mode must be known.
1040 pragma Assert (Present (Context_Scope));
1041 pragma Assert (Present (Insertion_Node));
1043 Push_Scope (Context_Scope);
1045 -- Treat use clauses as declarations and insert directly in front
1046 -- of them.
1048 if Nkind_In (Insertion_Node, N_Use_Package_Clause,
1049 N_Use_Type_Clause)
1050 then
1051 Insert_List_Before_And_Analyze (Insertion_Node, Actions);
1052 else
1053 Insert_Actions (Insertion_Node, Actions);
1054 end if;
1056 Pop_Scope;
1058 -- Otherwise the finalization master and its initialization become a
1059 -- part of the freeze node.
1061 else
1062 Append_Freeze_Actions (Ptr_Typ, Actions);
1063 end if;
1064 end;
1065 end Build_Finalization_Master;
1067 ---------------------
1068 -- Build_Finalizer --
1069 ---------------------
1071 procedure Build_Finalizer
1072 (N : Node_Id;
1073 Clean_Stmts : List_Id;
1074 Mark_Id : Entity_Id;
1075 Top_Decls : List_Id;
1076 Defer_Abort : Boolean;
1077 Fin_Id : out Entity_Id)
1079 Acts_As_Clean : constant Boolean :=
1080 Present (Mark_Id)
1081 or else
1082 (Present (Clean_Stmts)
1083 and then Is_Non_Empty_List (Clean_Stmts));
1084 Exceptions_OK : constant Boolean :=
1085 not Restriction_Active (No_Exception_Propagation);
1086 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1087 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1088 For_Package : constant Boolean :=
1089 For_Package_Body or else For_Package_Spec;
1090 Loc : constant Source_Ptr := Sloc (N);
1092 -- NOTE: Local variable declarations are conservative and do not create
1093 -- structures right from the start. Entities and lists are created once
1094 -- it has been established that N has at least one controlled object.
1096 Components_Built : Boolean := False;
1097 -- A flag used to avoid double initialization of entities and lists. If
1098 -- the flag is set then the following variables have been initialized:
1099 -- Counter_Id
1100 -- Finalizer_Decls
1101 -- Finalizer_Stmts
1102 -- Jump_Alts
1104 Counter_Id : Entity_Id := Empty;
1105 Counter_Val : Int := 0;
1106 -- Name and value of the state counter
1108 Decls : List_Id := No_List;
1109 -- Declarative region of N (if available). If N is a package declaration
1110 -- Decls denotes the visible declarations.
1112 Finalizer_Data : Finalization_Exception_Data;
1113 -- Data for the exception
1115 Finalizer_Decls : List_Id := No_List;
1116 -- Local variable declarations. This list holds the label declarations
1117 -- of all jump block alternatives as well as the declaration of the
1118 -- local exception occurence and the raised flag:
1119 -- E : Exception_Occurrence;
1120 -- Raised : Boolean := False;
1121 -- L<counter value> : label;
1123 Finalizer_Insert_Nod : Node_Id := Empty;
1124 -- Insertion point for the finalizer body. Depending on the context
1125 -- (Nkind of N) and the individual grouping of controlled objects, this
1126 -- node may denote a package declaration or body, package instantiation,
1127 -- block statement or a counter update statement.
1129 Finalizer_Stmts : List_Id := No_List;
1130 -- The statement list of the finalizer body. It contains the following:
1132 -- Abort_Defer; -- Added if abort is allowed
1133 -- <call to Prev_At_End> -- Added if exists
1134 -- <cleanup statements> -- Added if Acts_As_Clean
1135 -- <jump block> -- Added if Has_Ctrl_Objs
1136 -- <finalization statements> -- Added if Has_Ctrl_Objs
1137 -- <stack release> -- Added if Mark_Id exists
1138 -- Abort_Undefer; -- Added if abort is allowed
1140 Has_Ctrl_Objs : Boolean := False;
1141 -- A general flag which denotes whether N has at least one controlled
1142 -- object.
1144 Has_Tagged_Types : Boolean := False;
1145 -- A general flag which indicates whether N has at least one library-
1146 -- level tagged type declaration.
1148 HSS : Node_Id := Empty;
1149 -- The sequence of statements of N (if available)
1151 Jump_Alts : List_Id := No_List;
1152 -- Jump block alternatives. Depending on the value of the state counter,
1153 -- the control flow jumps to a sequence of finalization statements. This
1154 -- list contains the following:
1156 -- when <counter value> =>
1157 -- goto L<counter value>;
1159 Jump_Block_Insert_Nod : Node_Id := Empty;
1160 -- Specific point in the finalizer statements where the jump block is
1161 -- inserted.
1163 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1164 -- The last controlled construct encountered when processing the top
1165 -- level lists of N. This can be a nested package, an instantiation or
1166 -- an object declaration.
1168 Prev_At_End : Entity_Id := Empty;
1169 -- The previous at end procedure of the handled statements block of N
1171 Priv_Decls : List_Id := No_List;
1172 -- The private declarations of N if N is a package declaration
1174 Spec_Id : Entity_Id := Empty;
1175 Spec_Decls : List_Id := Top_Decls;
1176 Stmts : List_Id := No_List;
1178 Tagged_Type_Stmts : List_Id := No_List;
1179 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1180 -- tagged types found in N.
1182 -----------------------
1183 -- Local subprograms --
1184 -----------------------
1186 procedure Build_Components;
1187 -- Create all entites and initialize all lists used in the creation of
1188 -- the finalizer.
1190 procedure Create_Finalizer;
1191 -- Create the spec and body of the finalizer and insert them in the
1192 -- proper place in the tree depending on the context.
1194 procedure Process_Declarations
1195 (Decls : List_Id;
1196 Preprocess : Boolean := False;
1197 Top_Level : Boolean := False);
1198 -- Inspect a list of declarations or statements which may contain
1199 -- objects that need finalization. When flag Preprocess is set, the
1200 -- routine will simply count the total number of controlled objects in
1201 -- Decls. Flag Top_Level denotes whether the processing is done for
1202 -- objects in nested package declarations or instances.
1204 procedure Process_Object_Declaration
1205 (Decl : Node_Id;
1206 Has_No_Init : Boolean := False;
1207 Is_Protected : Boolean := False);
1208 -- Generate all the machinery associated with the finalization of a
1209 -- single object. Flag Has_No_Init is used to denote certain contexts
1210 -- where Decl does not have initialization call(s). Flag Is_Protected
1211 -- is set when Decl denotes a simple protected object.
1213 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1214 -- Generate all the code necessary to unregister the external tag of a
1215 -- tagged type.
1217 ----------------------
1218 -- Build_Components --
1219 ----------------------
1221 procedure Build_Components is
1222 Counter_Decl : Node_Id;
1223 Counter_Typ : Entity_Id;
1224 Counter_Typ_Decl : Node_Id;
1226 begin
1227 pragma Assert (Present (Decls));
1229 -- This routine might be invoked several times when dealing with
1230 -- constructs that have two lists (either two declarative regions
1231 -- or declarations and statements). Avoid double initialization.
1233 if Components_Built then
1234 return;
1235 end if;
1237 Components_Built := True;
1239 if Has_Ctrl_Objs then
1241 -- Create entities for the counter, its type, the local exception
1242 -- and the raised flag.
1244 Counter_Id := Make_Temporary (Loc, 'C');
1245 Counter_Typ := Make_Temporary (Loc, 'T');
1247 Finalizer_Decls := New_List;
1249 Build_Object_Declarations
1250 (Finalizer_Data, Finalizer_Decls, Loc, For_Package);
1252 -- Since the total number of controlled objects is always known,
1253 -- build a subtype of Natural with precise bounds. This allows
1254 -- the backend to optimize the case statement. Generate:
1256 -- subtype Tnn is Natural range 0 .. Counter_Val;
1258 Counter_Typ_Decl :=
1259 Make_Subtype_Declaration (Loc,
1260 Defining_Identifier => Counter_Typ,
1261 Subtype_Indication =>
1262 Make_Subtype_Indication (Loc,
1263 Subtype_Mark => New_Occurrence_Of (Standard_Natural, Loc),
1264 Constraint =>
1265 Make_Range_Constraint (Loc,
1266 Range_Expression =>
1267 Make_Range (Loc,
1268 Low_Bound =>
1269 Make_Integer_Literal (Loc, Uint_0),
1270 High_Bound =>
1271 Make_Integer_Literal (Loc, Counter_Val)))));
1273 -- Generate the declaration of the counter itself:
1275 -- Counter : Integer := 0;
1277 Counter_Decl :=
1278 Make_Object_Declaration (Loc,
1279 Defining_Identifier => Counter_Id,
1280 Object_Definition => New_Occurrence_Of (Counter_Typ, Loc),
1281 Expression => Make_Integer_Literal (Loc, 0));
1283 -- Set the type of the counter explicitly to prevent errors when
1284 -- examining object declarations later on.
1286 Set_Etype (Counter_Id, Counter_Typ);
1288 -- The counter and its type are inserted before the source
1289 -- declarations of N.
1291 Prepend_To (Decls, Counter_Decl);
1292 Prepend_To (Decls, Counter_Typ_Decl);
1294 -- The counter and its associated type must be manually analized
1295 -- since N has already been analyzed. Use the scope of the spec
1296 -- when inserting in a package.
1298 if For_Package then
1299 Push_Scope (Spec_Id);
1300 Analyze (Counter_Typ_Decl);
1301 Analyze (Counter_Decl);
1302 Pop_Scope;
1304 else
1305 Analyze (Counter_Typ_Decl);
1306 Analyze (Counter_Decl);
1307 end if;
1309 Jump_Alts := New_List;
1310 end if;
1312 -- If the context requires additional clean up, the finalization
1313 -- machinery is added after the clean up code.
1315 if Acts_As_Clean then
1316 Finalizer_Stmts := Clean_Stmts;
1317 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1318 else
1319 Finalizer_Stmts := New_List;
1320 end if;
1322 if Has_Tagged_Types then
1323 Tagged_Type_Stmts := New_List;
1324 end if;
1325 end Build_Components;
1327 ----------------------
1328 -- Create_Finalizer --
1329 ----------------------
1331 procedure Create_Finalizer is
1332 Body_Id : Entity_Id;
1333 Fin_Body : Node_Id;
1334 Fin_Spec : Node_Id;
1335 Jump_Block : Node_Id;
1336 Label : Node_Id;
1337 Label_Id : Entity_Id;
1339 function New_Finalizer_Name return Name_Id;
1340 -- Create a fully qualified name of a package spec or body finalizer.
1341 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1343 ------------------------
1344 -- New_Finalizer_Name --
1345 ------------------------
1347 function New_Finalizer_Name return Name_Id is
1348 procedure New_Finalizer_Name (Id : Entity_Id);
1349 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1350 -- has a non-standard scope, process the scope first.
1352 ------------------------
1353 -- New_Finalizer_Name --
1354 ------------------------
1356 procedure New_Finalizer_Name (Id : Entity_Id) is
1357 begin
1358 if Scope (Id) = Standard_Standard then
1359 Get_Name_String (Chars (Id));
1361 else
1362 New_Finalizer_Name (Scope (Id));
1363 Add_Str_To_Name_Buffer ("__");
1364 Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1365 end if;
1366 end New_Finalizer_Name;
1368 -- Start of processing for New_Finalizer_Name
1370 begin
1371 -- Create the fully qualified name of the enclosing scope
1373 New_Finalizer_Name (Spec_Id);
1375 -- Generate:
1376 -- __finalize_[spec|body]
1378 Add_Str_To_Name_Buffer ("__finalize_");
1380 if For_Package_Spec then
1381 Add_Str_To_Name_Buffer ("spec");
1382 else
1383 Add_Str_To_Name_Buffer ("body");
1384 end if;
1386 return Name_Find;
1387 end New_Finalizer_Name;
1389 -- Start of processing for Create_Finalizer
1391 begin
1392 -- Step 1: Creation of the finalizer name
1394 -- Packages must use a distinct name for their finalizers since the
1395 -- binder will have to generate calls to them by name. The name is
1396 -- of the following form:
1398 -- xx__yy__finalize_[spec|body]
1400 if For_Package then
1401 Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1402 Set_Has_Qualified_Name (Fin_Id);
1403 Set_Has_Fully_Qualified_Name (Fin_Id);
1405 -- The default name is _finalizer
1407 else
1408 Fin_Id :=
1409 Make_Defining_Identifier (Loc,
1410 Chars => New_External_Name (Name_uFinalizer));
1412 -- The visibility semantics of AT_END handlers force a strange
1413 -- separation of spec and body for stack-related finalizers:
1415 -- declare : Enclosing_Scope
1416 -- procedure _finalizer;
1417 -- begin
1418 -- <controlled objects>
1419 -- procedure _finalizer is
1420 -- ...
1421 -- at end
1422 -- _finalizer;
1423 -- end;
1425 -- Both spec and body are within the same construct and scope, but
1426 -- the body is part of the handled sequence of statements. This
1427 -- placement confuses the elaboration mechanism on targets where
1428 -- AT_END handlers are expanded into "when all others" handlers:
1430 -- exception
1431 -- when all others =>
1432 -- _finalizer; -- appears to require elab checks
1433 -- at end
1434 -- _finalizer;
1435 -- end;
1437 -- Since the compiler guarantees that the body of a _finalizer is
1438 -- always inserted in the same construct where the AT_END handler
1439 -- resides, there is no need for elaboration checks.
1441 Set_Kill_Elaboration_Checks (Fin_Id);
1442 end if;
1444 -- Step 2: Creation of the finalizer specification
1446 -- Generate:
1447 -- procedure Fin_Id;
1449 Fin_Spec :=
1450 Make_Subprogram_Declaration (Loc,
1451 Specification =>
1452 Make_Procedure_Specification (Loc,
1453 Defining_Unit_Name => Fin_Id));
1455 -- Step 3: Creation of the finalizer body
1457 if Has_Ctrl_Objs then
1459 -- Add L0, the default destination to the jump block
1461 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1462 Set_Entity (Label_Id,
1463 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1464 Label := Make_Label (Loc, Label_Id);
1466 -- Generate:
1467 -- L0 : label;
1469 Prepend_To (Finalizer_Decls,
1470 Make_Implicit_Label_Declaration (Loc,
1471 Defining_Identifier => Entity (Label_Id),
1472 Label_Construct => Label));
1474 -- Generate:
1475 -- when others =>
1476 -- goto L0;
1478 Append_To (Jump_Alts,
1479 Make_Case_Statement_Alternative (Loc,
1480 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1481 Statements => New_List (
1482 Make_Goto_Statement (Loc,
1483 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
1485 -- Generate:
1486 -- <<L0>>
1488 Append_To (Finalizer_Stmts, Label);
1490 -- Create the jump block which controls the finalization flow
1491 -- depending on the value of the state counter.
1493 Jump_Block :=
1494 Make_Case_Statement (Loc,
1495 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
1496 Alternatives => Jump_Alts);
1498 if Acts_As_Clean and then Present (Jump_Block_Insert_Nod) then
1499 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1500 else
1501 Prepend_To (Finalizer_Stmts, Jump_Block);
1502 end if;
1503 end if;
1505 -- Add the library-level tagged type unregistration machinery before
1506 -- the jump block circuitry. This ensures that external tags will be
1507 -- removed even if a finalization exception occurs at some point.
1509 if Has_Tagged_Types then
1510 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1511 end if;
1513 -- Add a call to the previous At_End handler if it exists. The call
1514 -- must always precede the jump block.
1516 if Present (Prev_At_End) then
1517 Prepend_To (Finalizer_Stmts,
1518 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1520 -- Clear the At_End handler since we have already generated the
1521 -- proper replacement call for it.
1523 Set_At_End_Proc (HSS, Empty);
1524 end if;
1526 -- Release the secondary stack mark
1528 if Present (Mark_Id) then
1529 Append_To (Finalizer_Stmts, Build_SS_Release_Call (Loc, Mark_Id));
1530 end if;
1532 -- Protect the statements with abort defer/undefer. This is only when
1533 -- aborts are allowed and the clean up statements require deferral or
1534 -- there are controlled objects to be finalized.
1536 if Abort_Allowed and then (Defer_Abort or Has_Ctrl_Objs) then
1537 Prepend_To (Finalizer_Stmts,
1538 Make_Procedure_Call_Statement (Loc,
1539 Name => New_Occurrence_Of (RTE (RE_Abort_Defer), Loc)));
1541 Append_To (Finalizer_Stmts,
1542 Make_Procedure_Call_Statement (Loc,
1543 Name => New_Occurrence_Of (RTE (RE_Abort_Undefer), Loc)));
1544 end if;
1546 -- The local exception does not need to be reraised for library-level
1547 -- finalizers. Note that this action must be carried out after object
1548 -- clean up, secondary stack release and abort undeferral. Generate:
1550 -- if Raised and then not Abort then
1551 -- Raise_From_Controlled_Operation (E);
1552 -- end if;
1554 if Has_Ctrl_Objs and Exceptions_OK and not For_Package then
1555 Append_To (Finalizer_Stmts,
1556 Build_Raise_Statement (Finalizer_Data));
1557 end if;
1559 -- Generate:
1560 -- procedure Fin_Id is
1561 -- Abort : constant Boolean := Triggered_By_Abort;
1562 -- <or>
1563 -- Abort : constant Boolean := False; -- no abort
1565 -- E : Exception_Occurrence; -- All added if flag
1566 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1567 -- L0 : label;
1568 -- ...
1569 -- Lnn : label;
1571 -- begin
1572 -- Abort_Defer; -- Added if abort is allowed
1573 -- <call to Prev_At_End> -- Added if exists
1574 -- <cleanup statements> -- Added if Acts_As_Clean
1575 -- <jump block> -- Added if Has_Ctrl_Objs
1576 -- <finalization statements> -- Added if Has_Ctrl_Objs
1577 -- <stack release> -- Added if Mark_Id exists
1578 -- Abort_Undefer; -- Added if abort is allowed
1579 -- <exception propagation> -- Added if Has_Ctrl_Objs
1580 -- end Fin_Id;
1582 -- Create the body of the finalizer
1584 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1586 if For_Package then
1587 Set_Has_Qualified_Name (Body_Id);
1588 Set_Has_Fully_Qualified_Name (Body_Id);
1589 end if;
1591 Fin_Body :=
1592 Make_Subprogram_Body (Loc,
1593 Specification =>
1594 Make_Procedure_Specification (Loc,
1595 Defining_Unit_Name => Body_Id),
1596 Declarations => Finalizer_Decls,
1597 Handled_Statement_Sequence =>
1598 Make_Handled_Sequence_Of_Statements (Loc, Finalizer_Stmts));
1600 -- Step 4: Spec and body insertion, analysis
1602 if For_Package then
1604 -- If the package spec has private declarations, the finalizer
1605 -- body must be added to the end of the list in order to have
1606 -- visibility of all private controlled objects.
1608 if For_Package_Spec then
1609 if Present (Priv_Decls) then
1610 Append_To (Priv_Decls, Fin_Spec);
1611 Append_To (Priv_Decls, Fin_Body);
1612 else
1613 Append_To (Decls, Fin_Spec);
1614 Append_To (Decls, Fin_Body);
1615 end if;
1617 -- For package bodies, both the finalizer spec and body are
1618 -- inserted at the end of the package declarations.
1620 else
1621 Append_To (Decls, Fin_Spec);
1622 Append_To (Decls, Fin_Body);
1623 end if;
1625 -- Push the name of the package
1627 Push_Scope (Spec_Id);
1628 Analyze (Fin_Spec);
1629 Analyze (Fin_Body);
1630 Pop_Scope;
1632 -- Non-package case
1634 else
1635 -- Create the spec for the finalizer. The At_End handler must be
1636 -- able to call the body which resides in a nested structure.
1638 -- Generate:
1639 -- declare
1640 -- procedure Fin_Id; -- Spec
1641 -- begin
1642 -- <objects and possibly statements>
1643 -- procedure Fin_Id is ... -- Body
1644 -- <statements>
1645 -- at end
1646 -- Fin_Id; -- At_End handler
1647 -- end;
1649 pragma Assert (Present (Spec_Decls));
1651 Append_To (Spec_Decls, Fin_Spec);
1652 Analyze (Fin_Spec);
1654 -- When the finalizer acts solely as a clean up routine, the body
1655 -- is inserted right after the spec.
1657 if Acts_As_Clean and not Has_Ctrl_Objs then
1658 Insert_After (Fin_Spec, Fin_Body);
1660 -- In all other cases the body is inserted after either:
1662 -- 1) The counter update statement of the last controlled object
1663 -- 2) The last top level nested controlled package
1664 -- 3) The last top level controlled instantiation
1666 else
1667 -- Manually freeze the spec. This is somewhat of a hack because
1668 -- a subprogram is frozen when its body is seen and the freeze
1669 -- node appears right before the body. However, in this case,
1670 -- the spec must be frozen earlier since the At_End handler
1671 -- must be able to call it.
1673 -- declare
1674 -- procedure Fin_Id; -- Spec
1675 -- [Fin_Id] -- Freeze node
1676 -- begin
1677 -- ...
1678 -- at end
1679 -- Fin_Id; -- At_End handler
1680 -- end;
1682 Ensure_Freeze_Node (Fin_Id);
1683 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1684 Set_Is_Frozen (Fin_Id);
1686 -- In the case where the last construct to contain a controlled
1687 -- object is either a nested package, an instantiation or a
1688 -- freeze node, the body must be inserted directly after the
1689 -- construct.
1691 if Nkind_In (Last_Top_Level_Ctrl_Construct,
1692 N_Freeze_Entity,
1693 N_Package_Declaration,
1694 N_Package_Body)
1695 then
1696 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1697 end if;
1699 Insert_After (Finalizer_Insert_Nod, Fin_Body);
1700 end if;
1702 Analyze (Fin_Body);
1703 end if;
1704 end Create_Finalizer;
1706 --------------------------
1707 -- Process_Declarations --
1708 --------------------------
1710 procedure Process_Declarations
1711 (Decls : List_Id;
1712 Preprocess : Boolean := False;
1713 Top_Level : Boolean := False)
1715 Decl : Node_Id;
1716 Expr : Node_Id;
1717 Obj_Id : Entity_Id;
1718 Obj_Typ : Entity_Id;
1719 Pack_Id : Entity_Id;
1720 Spec : Node_Id;
1721 Typ : Entity_Id;
1723 Old_Counter_Val : Int;
1724 -- This variable is used to determine whether a nested package or
1725 -- instance contains at least one controlled object.
1727 procedure Processing_Actions
1728 (Has_No_Init : Boolean := False;
1729 Is_Protected : Boolean := False);
1730 -- Depending on the mode of operation of Process_Declarations, either
1731 -- increment the controlled object counter, set the controlled object
1732 -- flag and store the last top level construct or process the current
1733 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1734 -- the current declaration may not have initialization proc(s). Flag
1735 -- Is_Protected should be set when the current declaration denotes a
1736 -- simple protected object.
1738 ------------------------
1739 -- Processing_Actions --
1740 ------------------------
1742 procedure Processing_Actions
1743 (Has_No_Init : Boolean := False;
1744 Is_Protected : Boolean := False)
1746 begin
1747 -- Library-level tagged type
1749 if Nkind (Decl) = N_Full_Type_Declaration then
1750 if Preprocess then
1751 Has_Tagged_Types := True;
1753 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
1754 Last_Top_Level_Ctrl_Construct := Decl;
1755 end if;
1757 else
1758 Process_Tagged_Type_Declaration (Decl);
1759 end if;
1761 -- Controlled object declaration
1763 else
1764 if Preprocess then
1765 Counter_Val := Counter_Val + 1;
1766 Has_Ctrl_Objs := True;
1768 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
1769 Last_Top_Level_Ctrl_Construct := Decl;
1770 end if;
1772 else
1773 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
1774 end if;
1775 end if;
1776 end Processing_Actions;
1778 -- Start of processing for Process_Declarations
1780 begin
1781 if No (Decls) or else Is_Empty_List (Decls) then
1782 return;
1783 end if;
1785 -- Process all declarations in reverse order
1787 Decl := Last_Non_Pragma (Decls);
1788 while Present (Decl) loop
1790 -- Library-level tagged types
1792 if Nkind (Decl) = N_Full_Type_Declaration then
1793 Typ := Defining_Identifier (Decl);
1795 -- Ignored Ghost types do not need any cleanup actions because
1796 -- they will not appear in the final tree.
1798 if Is_Ignored_Ghost_Entity (Typ) then
1799 null;
1801 elsif Is_Tagged_Type (Typ)
1802 and then Is_Library_Level_Entity (Typ)
1803 and then Convention (Typ) = Convention_Ada
1804 and then Present (Access_Disp_Table (Typ))
1805 and then RTE_Available (RE_Register_Tag)
1806 and then not Is_Abstract_Type (Typ)
1807 and then not No_Run_Time_Mode
1808 then
1809 Processing_Actions;
1810 end if;
1812 -- Regular object declarations
1814 elsif Nkind (Decl) = N_Object_Declaration then
1815 Obj_Id := Defining_Identifier (Decl);
1816 Obj_Typ := Base_Type (Etype (Obj_Id));
1817 Expr := Expression (Decl);
1819 -- Bypass any form of processing for objects which have their
1820 -- finalization disabled. This applies only to objects at the
1821 -- library level.
1823 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
1824 null;
1826 -- Transient variables are treated separately in order to
1827 -- minimize the size of the generated code. For details, see
1828 -- Process_Transient_Objects.
1830 elsif Is_Processed_Transient (Obj_Id) then
1831 null;
1833 -- Ignored Ghost objects do not need any cleanup actions
1834 -- because they will not appear in the final tree.
1836 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
1837 null;
1839 -- The object is of the form:
1840 -- Obj : Typ [:= Expr];
1842 -- Do not process the incomplete view of a deferred constant.
1843 -- Do not consider tag-to-class-wide conversions.
1845 elsif not Is_Imported (Obj_Id)
1846 and then Needs_Finalization (Obj_Typ)
1847 and then not (Ekind (Obj_Id) = E_Constant
1848 and then not Has_Completion (Obj_Id))
1849 and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id)
1850 then
1851 Processing_Actions;
1853 -- The object is of the form:
1854 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1856 -- Obj : Access_Typ :=
1857 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
1859 elsif Is_Access_Type (Obj_Typ)
1860 and then Needs_Finalization
1861 (Available_View (Designated_Type (Obj_Typ)))
1862 and then Present (Expr)
1863 and then
1864 (Is_Secondary_Stack_BIP_Func_Call (Expr)
1865 or else
1866 (Is_Non_BIP_Func_Call (Expr)
1867 and then not Is_Related_To_Func_Return (Obj_Id)))
1868 then
1869 Processing_Actions (Has_No_Init => True);
1871 -- Processing for "hook" objects generated for controlled
1872 -- transients declared inside an Expression_With_Actions.
1874 elsif Is_Access_Type (Obj_Typ)
1875 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
1876 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
1877 N_Object_Declaration
1878 then
1879 Processing_Actions (Has_No_Init => True);
1881 -- Process intermediate results of an if expression with one
1882 -- of the alternatives using a controlled function call.
1884 elsif Is_Access_Type (Obj_Typ)
1885 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
1886 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
1887 N_Defining_Identifier
1888 and then Present (Expr)
1889 and then Nkind (Expr) = N_Null
1890 then
1891 Processing_Actions (Has_No_Init => True);
1893 -- Simple protected objects which use type System.Tasking.
1894 -- Protected_Objects.Protection to manage their locks should
1895 -- be treated as controlled since they require manual cleanup.
1896 -- The only exception is illustrated in the following example:
1898 -- package Pkg is
1899 -- type Ctrl is new Controlled ...
1900 -- procedure Finalize (Obj : in out Ctrl);
1901 -- Lib_Obj : Ctrl;
1902 -- end Pkg;
1904 -- package body Pkg is
1905 -- protected Prot is
1906 -- procedure Do_Something (Obj : in out Ctrl);
1907 -- end Prot;
1909 -- protected body Prot is
1910 -- procedure Do_Something (Obj : in out Ctrl) is ...
1911 -- end Prot;
1913 -- procedure Finalize (Obj : in out Ctrl) is
1914 -- begin
1915 -- Prot.Do_Something (Obj);
1916 -- end Finalize;
1917 -- end Pkg;
1919 -- Since for the most part entities in package bodies depend on
1920 -- those in package specs, Prot's lock should be cleaned up
1921 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1922 -- This act however attempts to invoke Do_Something and fails
1923 -- because the lock has disappeared.
1925 elsif Ekind (Obj_Id) = E_Variable
1926 and then not In_Library_Level_Package_Body (Obj_Id)
1927 and then (Is_Simple_Protected_Type (Obj_Typ)
1928 or else Has_Simple_Protected_Object (Obj_Typ))
1929 then
1930 Processing_Actions (Is_Protected => True);
1931 end if;
1933 -- Specific cases of object renamings
1935 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
1936 Obj_Id := Defining_Identifier (Decl);
1937 Obj_Typ := Base_Type (Etype (Obj_Id));
1939 -- Bypass any form of processing for objects which have their
1940 -- finalization disabled. This applies only to objects at the
1941 -- library level.
1943 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
1944 null;
1946 -- Ignored Ghost object renamings do not need any cleanup
1947 -- actions because they will not appear in the final tree.
1949 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
1950 null;
1952 -- Return object of a build-in-place function. This case is
1953 -- recognized and marked by the expansion of an extended return
1954 -- statement (see Expand_N_Extended_Return_Statement).
1956 elsif Needs_Finalization (Obj_Typ)
1957 and then Is_Return_Object (Obj_Id)
1958 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
1959 then
1960 Processing_Actions (Has_No_Init => True);
1962 -- Detect a case where a source object has been initialized by
1963 -- a controlled function call or another object which was later
1964 -- rewritten as a class-wide conversion of Ada.Tags.Displace.
1966 -- Obj1 : CW_Type := Src_Obj;
1967 -- Obj2 : CW_Type := Function_Call (...);
1969 -- Obj1 : CW_Type renames (... Ada.Tags.Displace (Src_Obj));
1970 -- Tmp : ... := Function_Call (...)'reference;
1971 -- Obj2 : CW_Type renames (... Ada.Tags.Displace (Tmp));
1973 elsif Is_Displacement_Of_Object_Or_Function_Result (Obj_Id) then
1974 Processing_Actions (Has_No_Init => True);
1975 end if;
1977 -- Inspect the freeze node of an access-to-controlled type and
1978 -- look for a delayed finalization master. This case arises when
1979 -- the freeze actions are inserted at a later time than the
1980 -- expansion of the context. Since Build_Finalizer is never called
1981 -- on a single construct twice, the master will be ultimately
1982 -- left out and never finalized. This is also needed for freeze
1983 -- actions of designated types themselves, since in some cases the
1984 -- finalization master is associated with a designated type's
1985 -- freeze node rather than that of the access type (see handling
1986 -- for freeze actions in Build_Finalization_Master).
1988 elsif Nkind (Decl) = N_Freeze_Entity
1989 and then Present (Actions (Decl))
1990 then
1991 Typ := Entity (Decl);
1993 -- Freeze nodes for ignored Ghost types do not need cleanup
1994 -- actions because they will never appear in the final tree.
1996 if Is_Ignored_Ghost_Entity (Typ) then
1997 null;
1999 elsif (Is_Access_Type (Typ)
2000 and then not Is_Access_Subprogram_Type (Typ)
2001 and then Needs_Finalization
2002 (Available_View (Designated_Type (Typ))))
2003 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
2004 then
2005 Old_Counter_Val := Counter_Val;
2007 -- Freeze nodes are considered to be identical to packages
2008 -- and blocks in terms of nesting. The difference is that
2009 -- a finalization master created inside the freeze node is
2010 -- at the same nesting level as the node itself.
2012 Process_Declarations (Actions (Decl), Preprocess);
2014 -- The freeze node contains a finalization master
2016 if Preprocess
2017 and then Top_Level
2018 and then No (Last_Top_Level_Ctrl_Construct)
2019 and then Counter_Val > Old_Counter_Val
2020 then
2021 Last_Top_Level_Ctrl_Construct := Decl;
2022 end if;
2023 end if;
2025 -- Nested package declarations, avoid generics
2027 elsif Nkind (Decl) = N_Package_Declaration then
2028 Pack_Id := Defining_Entity (Decl);
2029 Spec := Specification (Decl);
2031 -- Do not inspect an ignored Ghost package because all code
2032 -- found within will not appear in the final tree.
2034 if Is_Ignored_Ghost_Entity (Pack_Id) then
2035 null;
2037 elsif Ekind (Pack_Id) /= E_Generic_Package then
2038 Old_Counter_Val := Counter_Val;
2039 Process_Declarations
2040 (Private_Declarations (Spec), Preprocess);
2041 Process_Declarations
2042 (Visible_Declarations (Spec), Preprocess);
2044 -- Either the visible or the private declarations contain a
2045 -- controlled object. The nested package declaration is the
2046 -- last such construct.
2048 if Preprocess
2049 and then Top_Level
2050 and then No (Last_Top_Level_Ctrl_Construct)
2051 and then Counter_Val > Old_Counter_Val
2052 then
2053 Last_Top_Level_Ctrl_Construct := Decl;
2054 end if;
2055 end if;
2057 -- Nested package bodies, avoid generics
2059 elsif Nkind (Decl) = N_Package_Body then
2061 -- Do not inspect an ignored Ghost package body because all
2062 -- code found within will not appear in the final tree.
2064 if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then
2065 null;
2067 elsif Ekind (Corresponding_Spec (Decl)) /=
2068 E_Generic_Package
2069 then
2070 Old_Counter_Val := Counter_Val;
2071 Process_Declarations (Declarations (Decl), Preprocess);
2073 -- The nested package body is the last construct to contain
2074 -- a controlled object.
2076 if Preprocess
2077 and then Top_Level
2078 and then No (Last_Top_Level_Ctrl_Construct)
2079 and then Counter_Val > Old_Counter_Val
2080 then
2081 Last_Top_Level_Ctrl_Construct := Decl;
2082 end if;
2083 end if;
2085 -- Handle a rare case caused by a controlled transient variable
2086 -- created as part of a record init proc. The variable is wrapped
2087 -- in a block, but the block is not associated with a transient
2088 -- scope.
2090 elsif Nkind (Decl) = N_Block_Statement
2091 and then Inside_Init_Proc
2092 then
2093 Old_Counter_Val := Counter_Val;
2095 if Present (Handled_Statement_Sequence (Decl)) then
2096 Process_Declarations
2097 (Statements (Handled_Statement_Sequence (Decl)),
2098 Preprocess);
2099 end if;
2101 Process_Declarations (Declarations (Decl), Preprocess);
2103 -- Either the declaration or statement list of the block has a
2104 -- controlled object.
2106 if Preprocess
2107 and then Top_Level
2108 and then No (Last_Top_Level_Ctrl_Construct)
2109 and then Counter_Val > Old_Counter_Val
2110 then
2111 Last_Top_Level_Ctrl_Construct := Decl;
2112 end if;
2114 -- Handle the case where the original context has been wrapped in
2115 -- a block to avoid interference between exception handlers and
2116 -- At_End handlers. Treat the block as transparent and process its
2117 -- contents.
2119 elsif Nkind (Decl) = N_Block_Statement
2120 and then Is_Finalization_Wrapper (Decl)
2121 then
2122 if Present (Handled_Statement_Sequence (Decl)) then
2123 Process_Declarations
2124 (Statements (Handled_Statement_Sequence (Decl)),
2125 Preprocess);
2126 end if;
2128 Process_Declarations (Declarations (Decl), Preprocess);
2129 end if;
2131 Prev_Non_Pragma (Decl);
2132 end loop;
2133 end Process_Declarations;
2135 --------------------------------
2136 -- Process_Object_Declaration --
2137 --------------------------------
2139 procedure Process_Object_Declaration
2140 (Decl : Node_Id;
2141 Has_No_Init : Boolean := False;
2142 Is_Protected : Boolean := False)
2144 Loc : constant Source_Ptr := Sloc (Decl);
2145 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2147 Init_Typ : Entity_Id;
2148 -- The initialization type of the related object declaration. Note
2149 -- that this is not necessarely the same type as Obj_Typ because of
2150 -- possible type derivations.
2152 Obj_Typ : Entity_Id;
2153 -- The type of the related object declaration
2155 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2156 -- Func_Id denotes a build-in-place function. Generate the following
2157 -- cleanup code:
2159 -- if BIPallocfrom > Secondary_Stack'Pos
2160 -- and then BIPfinalizationmaster /= null
2161 -- then
2162 -- declare
2163 -- type Ptr_Typ is access Obj_Typ;
2164 -- for Ptr_Typ'Storage_Pool
2165 -- use Base_Pool (BIPfinalizationmaster);
2166 -- begin
2167 -- Free (Ptr_Typ (Temp));
2168 -- end;
2169 -- end if;
2171 -- Obj_Typ is the type of the current object, Temp is the original
2172 -- allocation which Obj_Id renames.
2174 procedure Find_Last_Init
2175 (Last_Init : out Node_Id;
2176 Body_Insert : out Node_Id);
2177 -- Find the last initialization call related to object declaration
2178 -- Decl. Last_Init denotes the last initialization call which follows
2179 -- Decl. Body_Insert denotes a node where the finalizer body could be
2180 -- potentially inserted after (if blocks are involved).
2182 -----------------------------
2183 -- Build_BIP_Cleanup_Stmts --
2184 -----------------------------
2186 function Build_BIP_Cleanup_Stmts
2187 (Func_Id : Entity_Id) return Node_Id
2189 Decls : constant List_Id := New_List;
2190 Fin_Mas_Id : constant Entity_Id :=
2191 Build_In_Place_Formal
2192 (Func_Id, BIP_Finalization_Master);
2193 Func_Typ : constant Entity_Id := Etype (Func_Id);
2194 Temp_Id : constant Entity_Id :=
2195 Entity (Prefix (Name (Parent (Obj_Id))));
2197 Cond : Node_Id;
2198 Free_Blk : Node_Id;
2199 Free_Stmt : Node_Id;
2200 Pool_Id : Entity_Id;
2201 Ptr_Typ : Entity_Id;
2203 begin
2204 -- Generate:
2205 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2207 Pool_Id := Make_Temporary (Loc, 'P');
2209 Append_To (Decls,
2210 Make_Object_Renaming_Declaration (Loc,
2211 Defining_Identifier => Pool_Id,
2212 Subtype_Mark =>
2213 New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
2214 Name =>
2215 Make_Explicit_Dereference (Loc,
2216 Prefix =>
2217 Make_Function_Call (Loc,
2218 Name =>
2219 New_Occurrence_Of (RTE (RE_Base_Pool), Loc),
2220 Parameter_Associations => New_List (
2221 Make_Explicit_Dereference (Loc,
2222 Prefix =>
2223 New_Occurrence_Of (Fin_Mas_Id, Loc)))))));
2225 -- Create an access type which uses the storage pool of the
2226 -- caller's finalization master.
2228 -- Generate:
2229 -- type Ptr_Typ is access Func_Typ;
2231 Ptr_Typ := Make_Temporary (Loc, 'P');
2233 Append_To (Decls,
2234 Make_Full_Type_Declaration (Loc,
2235 Defining_Identifier => Ptr_Typ,
2236 Type_Definition =>
2237 Make_Access_To_Object_Definition (Loc,
2238 Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
2240 -- Perform minor decoration in order to set the master and the
2241 -- storage pool attributes.
2243 Set_Ekind (Ptr_Typ, E_Access_Type);
2244 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
2245 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2247 -- Create an explicit free statement. Note that the free uses the
2248 -- caller's pool expressed as a renaming.
2250 Free_Stmt :=
2251 Make_Free_Statement (Loc,
2252 Expression =>
2253 Unchecked_Convert_To (Ptr_Typ,
2254 New_Occurrence_Of (Temp_Id, Loc)));
2256 Set_Storage_Pool (Free_Stmt, Pool_Id);
2258 -- Create a block to house the dummy type and the instantiation as
2259 -- well as to perform the cleanup the temporary.
2261 -- Generate:
2262 -- declare
2263 -- <Decls>
2264 -- begin
2265 -- Free (Ptr_Typ (Temp_Id));
2266 -- end;
2268 Free_Blk :=
2269 Make_Block_Statement (Loc,
2270 Declarations => Decls,
2271 Handled_Statement_Sequence =>
2272 Make_Handled_Sequence_Of_Statements (Loc,
2273 Statements => New_List (Free_Stmt)));
2275 -- Generate:
2276 -- if BIPfinalizationmaster /= null then
2278 Cond :=
2279 Make_Op_Ne (Loc,
2280 Left_Opnd => New_Occurrence_Of (Fin_Mas_Id, Loc),
2281 Right_Opnd => Make_Null (Loc));
2283 -- For constrained or tagged results escalate the condition to
2284 -- include the allocation format. Generate:
2286 -- if BIPallocform > Secondary_Stack'Pos
2287 -- and then BIPfinalizationmaster /= null
2288 -- then
2290 if not Is_Constrained (Func_Typ)
2291 or else Is_Tagged_Type (Func_Typ)
2292 then
2293 declare
2294 Alloc : constant Entity_Id :=
2295 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2296 begin
2297 Cond :=
2298 Make_And_Then (Loc,
2299 Left_Opnd =>
2300 Make_Op_Gt (Loc,
2301 Left_Opnd => New_Occurrence_Of (Alloc, Loc),
2302 Right_Opnd =>
2303 Make_Integer_Literal (Loc,
2304 UI_From_Int
2305 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2307 Right_Opnd => Cond);
2308 end;
2309 end if;
2311 -- Generate:
2312 -- if <Cond> then
2313 -- <Free_Blk>
2314 -- end if;
2316 return
2317 Make_If_Statement (Loc,
2318 Condition => Cond,
2319 Then_Statements => New_List (Free_Blk));
2320 end Build_BIP_Cleanup_Stmts;
2322 --------------------
2323 -- Find_Last_Init --
2324 --------------------
2326 procedure Find_Last_Init
2327 (Last_Init : out Node_Id;
2328 Body_Insert : out Node_Id)
2330 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id;
2331 -- Find the last initialization call within the statements of
2332 -- block Blk.
2334 function Is_Init_Call (N : Node_Id) return Boolean;
2335 -- Determine whether node N denotes one of the initialization
2336 -- procedures of types Init_Typ or Obj_Typ.
2338 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
2339 -- Given a statement which is part of a list, return the next
2340 -- statement while skipping over dynamic elab checks.
2342 -----------------------------
2343 -- Find_Last_Init_In_Block --
2344 -----------------------------
2346 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id is
2347 HSS : constant Node_Id := Handled_Statement_Sequence (Blk);
2348 Stmt : Node_Id;
2350 begin
2351 -- Examine the individual statements of the block in reverse to
2352 -- locate the last initialization call.
2354 if Present (HSS) and then Present (Statements (HSS)) then
2355 Stmt := Last (Statements (HSS));
2356 while Present (Stmt) loop
2358 -- Peek inside nested blocks in case aborts are allowed
2360 if Nkind (Stmt) = N_Block_Statement then
2361 return Find_Last_Init_In_Block (Stmt);
2363 elsif Is_Init_Call (Stmt) then
2364 return Stmt;
2365 end if;
2367 Prev (Stmt);
2368 end loop;
2369 end if;
2371 return Empty;
2372 end Find_Last_Init_In_Block;
2374 ------------------
2375 -- Is_Init_Call --
2376 ------------------
2378 function Is_Init_Call (N : Node_Id) return Boolean is
2379 function Is_Init_Proc_Of
2380 (Subp_Id : Entity_Id;
2381 Typ : Entity_Id) return Boolean;
2382 -- Determine whether subprogram Subp_Id is a valid init proc of
2383 -- type Typ.
2385 ---------------------
2386 -- Is_Init_Proc_Of --
2387 ---------------------
2389 function Is_Init_Proc_Of
2390 (Subp_Id : Entity_Id;
2391 Typ : Entity_Id) return Boolean
2393 Deep_Init : Entity_Id := Empty;
2394 Prim_Init : Entity_Id := Empty;
2395 Type_Init : Entity_Id := Empty;
2397 begin
2398 -- Obtain all possible initialization routines of the
2399 -- related type and try to match the subprogram entity
2400 -- against one of them.
2402 -- Deep_Initialize
2404 Deep_Init := TSS (Typ, TSS_Deep_Initialize);
2406 -- Primitive Initialize
2408 if Is_Controlled (Typ) then
2409 Prim_Init := Find_Prim_Op (Typ, Name_Initialize);
2411 if Present (Prim_Init) then
2412 Prim_Init := Ultimate_Alias (Prim_Init);
2413 end if;
2414 end if;
2416 -- Type initialization routine
2418 if Has_Non_Null_Base_Init_Proc (Typ) then
2419 Type_Init := Base_Init_Proc (Typ);
2420 end if;
2422 return
2423 (Present (Deep_Init) and then Subp_Id = Deep_Init)
2424 or else
2425 (Present (Prim_Init) and then Subp_Id = Prim_Init)
2426 or else
2427 (Present (Type_Init) and then Subp_Id = Type_Init);
2428 end Is_Init_Proc_Of;
2430 -- Local variables
2432 Call_Id : Entity_Id;
2434 -- Start of processing for Is_Init_Call
2436 begin
2437 if Nkind (N) = N_Procedure_Call_Statement
2438 and then Nkind (Name (N)) = N_Identifier
2439 then
2440 Call_Id := Entity (Name (N));
2442 -- Consider both the type of the object declaration and its
2443 -- related initialization type.
2445 return
2446 Is_Init_Proc_Of (Call_Id, Init_Typ)
2447 or else
2448 Is_Init_Proc_Of (Call_Id, Obj_Typ);
2449 end if;
2451 return False;
2452 end Is_Init_Call;
2454 -----------------------------
2455 -- Next_Suitable_Statement --
2456 -----------------------------
2458 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
2459 Result : Node_Id := Next (Stmt);
2461 begin
2462 -- Skip over access-before-elaboration checks
2464 if Dynamic_Elaboration_Checks
2465 and then Nkind (Result) = N_Raise_Program_Error
2466 then
2467 Result := Next (Result);
2468 end if;
2470 return Result;
2471 end Next_Suitable_Statement;
2473 -- Local variables
2475 Call : Node_Id;
2476 Stmt : Node_Id;
2477 Stmt_2 : Node_Id;
2479 Deep_Init_Found : Boolean := False;
2480 -- A flag set when a call to [Deep_]Initialize has been found
2482 -- Start of processing for Find_Last_Init
2484 begin
2485 Last_Init := Decl;
2486 Body_Insert := Empty;
2488 -- Object renamings and objects associated with controlled
2489 -- function results do not require initialization.
2491 if Has_No_Init then
2492 return;
2493 end if;
2495 Stmt := Next_Suitable_Statement (Decl);
2497 -- A limited controlled object initialized by a function call uses
2498 -- the build-in-place machinery to obtain its value.
2500 -- Obj : Lim_Controlled_Type := Func_Call;
2502 -- is expanded into
2504 -- Obj : Lim_Controlled_Type;
2505 -- type Ptr_Typ is access Lim_Controlled_Type;
2506 -- Temp : constant Ptr_Typ :=
2507 -- Func_Call
2508 -- (BIPalloc => 1,
2509 -- BIPaccess => Obj'Unrestricted_Access)'reference;
2511 -- In this scenario the declaration of the temporary acts as the
2512 -- last initialization statement.
2514 if Is_Limited_Type (Obj_Typ)
2515 and then Has_Init_Expression (Decl)
2516 and then No (Expression (Decl))
2517 then
2518 while Present (Stmt) loop
2519 if Nkind (Stmt) = N_Object_Declaration
2520 and then Present (Expression (Stmt))
2521 and then Is_Object_Access_BIP_Func_Call
2522 (Expr => Expression (Stmt),
2523 Obj_Id => Obj_Id)
2524 then
2525 Last_Init := Stmt;
2526 exit;
2527 end if;
2529 Next (Stmt);
2530 end loop;
2532 -- Nothing to do for an object with supporessed initialization.
2533 -- Note that this check is not performed at the beginning of the
2534 -- routine because a declaration marked with No_Initialization
2535 -- may still be initialized by a build-in-place call (the case
2536 -- above).
2538 elsif No_Initialization (Decl) then
2539 return;
2541 -- In all other cases the initialization calls follow the related
2542 -- object. The general structure of object initialization built by
2543 -- routine Default_Initialize_Object is as follows:
2545 -- [begin -- aborts allowed
2546 -- Abort_Defer;]
2547 -- Type_Init_Proc (Obj);
2548 -- [begin] -- exceptions allowed
2549 -- Deep_Initialize (Obj);
2550 -- [exception -- exceptions allowed
2551 -- when others =>
2552 -- Deep_Finalize (Obj, Self => False);
2553 -- raise;
2554 -- end;]
2555 -- [at end -- aborts allowed
2556 -- Abort_Undefer;
2557 -- end;]
2559 -- When aborts are allowed, the initialization calls are housed
2560 -- within a block.
2562 elsif Nkind (Stmt) = N_Block_Statement then
2563 Last_Init := Find_Last_Init_In_Block (Stmt);
2564 Body_Insert := Stmt;
2566 -- Otherwise the initialization calls follow the related object
2568 else
2569 Stmt_2 := Next_Suitable_Statement (Stmt);
2571 -- Check for an optional call to Deep_Initialize which may
2572 -- appear within a block depending on whether the object has
2573 -- controlled components.
2575 if Present (Stmt_2) then
2576 if Nkind (Stmt_2) = N_Block_Statement then
2577 Call := Find_Last_Init_In_Block (Stmt_2);
2579 if Present (Call) then
2580 Deep_Init_Found := True;
2581 Last_Init := Call;
2582 Body_Insert := Stmt_2;
2583 end if;
2585 elsif Is_Init_Call (Stmt_2) then
2586 Deep_Init_Found := True;
2587 Last_Init := Stmt_2;
2588 Body_Insert := Last_Init;
2589 end if;
2590 end if;
2592 -- If the object lacks a call to Deep_Initialize, then it must
2593 -- have a call to its related type init proc.
2595 if not Deep_Init_Found and then Is_Init_Call (Stmt) then
2596 Last_Init := Stmt;
2597 Body_Insert := Last_Init;
2598 end if;
2599 end if;
2600 end Find_Last_Init;
2602 -- Local variables
2604 Body_Ins : Node_Id;
2605 Count_Ins : Node_Id;
2606 Fin_Call : Node_Id;
2607 Fin_Stmts : List_Id;
2608 Inc_Decl : Node_Id;
2609 Label : Node_Id;
2610 Label_Id : Entity_Id;
2611 Obj_Ref : Node_Id;
2613 -- Start of processing for Process_Object_Declaration
2615 begin
2616 -- Handle the object type and the reference to the object
2618 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
2619 Obj_Typ := Base_Type (Etype (Obj_Id));
2621 loop
2622 if Is_Access_Type (Obj_Typ) then
2623 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2624 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2626 elsif Is_Concurrent_Type (Obj_Typ)
2627 and then Present (Corresponding_Record_Type (Obj_Typ))
2628 then
2629 Obj_Typ := Corresponding_Record_Type (Obj_Typ);
2630 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2632 elsif Is_Private_Type (Obj_Typ)
2633 and then Present (Full_View (Obj_Typ))
2634 then
2635 Obj_Typ := Full_View (Obj_Typ);
2636 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2638 elsif Obj_Typ /= Base_Type (Obj_Typ) then
2639 Obj_Typ := Base_Type (Obj_Typ);
2640 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2642 else
2643 exit;
2644 end if;
2645 end loop;
2647 Set_Etype (Obj_Ref, Obj_Typ);
2649 -- Handle the initialization type of the object declaration
2651 Init_Typ := Obj_Typ;
2652 loop
2653 if Is_Private_Type (Init_Typ)
2654 and then Present (Full_View (Init_Typ))
2655 then
2656 Init_Typ := Full_View (Init_Typ);
2658 elsif Is_Untagged_Derivation (Init_Typ) then
2659 Init_Typ := Root_Type (Init_Typ);
2661 else
2662 exit;
2663 end if;
2664 end loop;
2666 -- Set a new value for the state counter and insert the statement
2667 -- after the object declaration. Generate:
2669 -- Counter := <value>;
2671 Inc_Decl :=
2672 Make_Assignment_Statement (Loc,
2673 Name => New_Occurrence_Of (Counter_Id, Loc),
2674 Expression => Make_Integer_Literal (Loc, Counter_Val));
2676 -- Insert the counter after all initialization has been done. The
2677 -- place of insertion depends on the context. If an object is being
2678 -- initialized via an aggregate, then the counter must be inserted
2679 -- after the last aggregate assignment.
2681 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2682 and then Present (Last_Aggregate_Assignment (Obj_Id))
2683 then
2684 Count_Ins := Last_Aggregate_Assignment (Obj_Id);
2685 Body_Ins := Empty;
2687 -- In all other cases the counter is inserted after the last call to
2688 -- either [Deep_]Initialize or the type specific init proc.
2690 else
2691 Find_Last_Init (Count_Ins, Body_Ins);
2692 end if;
2694 Insert_After (Count_Ins, Inc_Decl);
2695 Analyze (Inc_Decl);
2697 -- If the current declaration is the last in the list, the finalizer
2698 -- body needs to be inserted after the set counter statement for the
2699 -- current object declaration. This is complicated by the fact that
2700 -- the set counter statement may appear in abort deferred block. In
2701 -- that case, the proper insertion place is after the block.
2703 if No (Finalizer_Insert_Nod) then
2705 -- Insertion after an abort deffered block
2707 if Present (Body_Ins) then
2708 Finalizer_Insert_Nod := Body_Ins;
2709 else
2710 Finalizer_Insert_Nod := Inc_Decl;
2711 end if;
2712 end if;
2714 -- Create the associated label with this object, generate:
2716 -- L<counter> : label;
2718 Label_Id :=
2719 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2720 Set_Entity
2721 (Label_Id, Make_Defining_Identifier (Loc, Chars (Label_Id)));
2722 Label := Make_Label (Loc, Label_Id);
2724 Prepend_To (Finalizer_Decls,
2725 Make_Implicit_Label_Declaration (Loc,
2726 Defining_Identifier => Entity (Label_Id),
2727 Label_Construct => Label));
2729 -- Create the associated jump with this object, generate:
2731 -- when <counter> =>
2732 -- goto L<counter>;
2734 Prepend_To (Jump_Alts,
2735 Make_Case_Statement_Alternative (Loc,
2736 Discrete_Choices => New_List (
2737 Make_Integer_Literal (Loc, Counter_Val)),
2738 Statements => New_List (
2739 Make_Goto_Statement (Loc,
2740 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
2742 -- Insert the jump destination, generate:
2744 -- <<L<counter>>>
2746 Append_To (Finalizer_Stmts, Label);
2748 -- Processing for simple protected objects. Such objects require
2749 -- manual finalization of their lock managers.
2751 if Is_Protected then
2752 Fin_Stmts := No_List;
2754 if Is_Simple_Protected_Type (Obj_Typ) then
2755 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
2757 if Present (Fin_Call) then
2758 Fin_Stmts := New_List (Fin_Call);
2759 end if;
2761 elsif Has_Simple_Protected_Object (Obj_Typ) then
2762 if Is_Record_Type (Obj_Typ) then
2763 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2764 elsif Is_Array_Type (Obj_Typ) then
2765 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2766 end if;
2767 end if;
2769 -- Generate:
2770 -- begin
2771 -- System.Tasking.Protected_Objects.Finalize_Protection
2772 -- (Obj._object);
2774 -- exception
2775 -- when others =>
2776 -- null;
2777 -- end;
2779 if Present (Fin_Stmts) then
2780 Append_To (Finalizer_Stmts,
2781 Make_Block_Statement (Loc,
2782 Handled_Statement_Sequence =>
2783 Make_Handled_Sequence_Of_Statements (Loc,
2784 Statements => Fin_Stmts,
2786 Exception_Handlers => New_List (
2787 Make_Exception_Handler (Loc,
2788 Exception_Choices => New_List (
2789 Make_Others_Choice (Loc)),
2791 Statements => New_List (
2792 Make_Null_Statement (Loc)))))));
2793 end if;
2795 -- Processing for regular controlled objects
2797 else
2798 -- Generate:
2799 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2801 -- begin -- Exception handlers allowed
2802 -- [Deep_]Finalize (Obj);
2804 -- exception
2805 -- when Id : others =>
2806 -- if not Raised then
2807 -- Raised := True;
2808 -- Save_Occurrence (E, Id);
2809 -- end if;
2810 -- end;
2812 Fin_Call :=
2813 Make_Final_Call (
2814 Obj_Ref => Obj_Ref,
2815 Typ => Obj_Typ);
2817 -- For CodePeer, the exception handlers normally generated here
2818 -- generate complex flowgraphs which result in capacity problems.
2819 -- Omitting these handlers for CodePeer is justified as follows:
2821 -- If a handler is dead, then omitting it is surely ok
2823 -- If a handler is live, then CodePeer should flag the
2824 -- potentially-exception-raising construct that causes it
2825 -- to be live. That is what we are interested in, not what
2826 -- happens after the exception is raised.
2828 if Exceptions_OK and not CodePeer_Mode then
2829 Fin_Stmts := New_List (
2830 Make_Block_Statement (Loc,
2831 Handled_Statement_Sequence =>
2832 Make_Handled_Sequence_Of_Statements (Loc,
2833 Statements => New_List (Fin_Call),
2835 Exception_Handlers => New_List (
2836 Build_Exception_Handler
2837 (Finalizer_Data, For_Package)))));
2839 -- When exception handlers are prohibited, the finalization call
2840 -- appears unprotected. Any exception raised during finalization
2841 -- will bypass the circuitry which ensures the cleanup of all
2842 -- remaining objects.
2844 else
2845 Fin_Stmts := New_List (Fin_Call);
2846 end if;
2848 -- If we are dealing with a return object of a build-in-place
2849 -- function, generate the following cleanup statements:
2851 -- if BIPallocfrom > Secondary_Stack'Pos
2852 -- and then BIPfinalizationmaster /= null
2853 -- then
2854 -- declare
2855 -- type Ptr_Typ is access Obj_Typ;
2856 -- for Ptr_Typ'Storage_Pool use
2857 -- Base_Pool (BIPfinalizationmaster.all).all;
2858 -- begin
2859 -- Free (Ptr_Typ (Temp));
2860 -- end;
2861 -- end if;
2863 -- The generated code effectively detaches the temporary from the
2864 -- caller finalization master and deallocates the object. This is
2865 -- disabled on .NET/JVM because pools are not supported.
2867 if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2868 declare
2869 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2870 begin
2871 if Is_Build_In_Place_Function (Func_Id)
2872 and then Needs_BIP_Finalization_Master (Func_Id)
2873 then
2874 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2875 end if;
2876 end;
2877 end if;
2879 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2880 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2881 then
2882 -- Temporaries created for the purpose of "exporting" a
2883 -- controlled transient out of an Expression_With_Actions (EWA)
2884 -- need guards. The following illustrates the usage of such
2885 -- temporaries.
2887 -- Access_Typ : access [all] Obj_Typ;
2888 -- Temp : Access_Typ := null;
2889 -- <Counter> := ...;
2891 -- do
2892 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2893 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2894 -- <or>
2895 -- Temp := Ctrl_Trans'Unchecked_Access;
2896 -- in ... end;
2898 -- The finalization machinery does not process EWA nodes as
2899 -- this may lead to premature finalization of expressions. Note
2900 -- that Temp is marked as being properly initialized regardless
2901 -- of whether the initialization of Ctrl_Trans succeeded. Since
2902 -- a failed initialization may leave Temp with a value of null,
2903 -- add a guard to handle this case:
2905 -- if Obj /= null then
2906 -- <object finalization statements>
2907 -- end if;
2909 if Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
2910 N_Object_Declaration
2911 then
2912 Fin_Stmts := New_List (
2913 Make_If_Statement (Loc,
2914 Condition =>
2915 Make_Op_Ne (Loc,
2916 Left_Opnd => New_Occurrence_Of (Obj_Id, Loc),
2917 Right_Opnd => Make_Null (Loc)),
2918 Then_Statements => Fin_Stmts));
2920 -- Return objects use a flag to aid in processing their
2921 -- potential finalization when the enclosing function fails
2922 -- to return properly. Generate:
2924 -- if not Flag then
2925 -- <object finalization statements>
2926 -- end if;
2928 else
2929 Fin_Stmts := New_List (
2930 Make_If_Statement (Loc,
2931 Condition =>
2932 Make_Op_Not (Loc,
2933 Right_Opnd =>
2934 New_Occurrence_Of
2935 (Status_Flag_Or_Transient_Decl (Obj_Id), Loc)),
2937 Then_Statements => Fin_Stmts));
2938 end if;
2939 end if;
2940 end if;
2942 Append_List_To (Finalizer_Stmts, Fin_Stmts);
2944 -- Since the declarations are examined in reverse, the state counter
2945 -- must be decremented in order to keep with the true position of
2946 -- objects.
2948 Counter_Val := Counter_Val - 1;
2949 end Process_Object_Declaration;
2951 -------------------------------------
2952 -- Process_Tagged_Type_Declaration --
2953 -------------------------------------
2955 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2956 Typ : constant Entity_Id := Defining_Identifier (Decl);
2957 DT_Ptr : constant Entity_Id :=
2958 Node (First_Elmt (Access_Disp_Table (Typ)));
2959 begin
2960 -- Generate:
2961 -- Ada.Tags.Unregister_Tag (<Typ>P);
2963 Append_To (Tagged_Type_Stmts,
2964 Make_Procedure_Call_Statement (Loc,
2965 Name =>
2966 New_Occurrence_Of (RTE (RE_Unregister_Tag), Loc),
2967 Parameter_Associations => New_List (
2968 New_Occurrence_Of (DT_Ptr, Loc))));
2969 end Process_Tagged_Type_Declaration;
2971 -- Start of processing for Build_Finalizer
2973 begin
2974 Fin_Id := Empty;
2976 -- Do not perform this expansion in SPARK mode because it is not
2977 -- necessary.
2979 if GNATprove_Mode then
2980 return;
2981 end if;
2983 -- Step 1: Extract all lists which may contain controlled objects or
2984 -- library-level tagged types.
2986 if For_Package_Spec then
2987 Decls := Visible_Declarations (Specification (N));
2988 Priv_Decls := Private_Declarations (Specification (N));
2990 -- Retrieve the package spec id
2992 Spec_Id := Defining_Unit_Name (Specification (N));
2994 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2995 Spec_Id := Defining_Identifier (Spec_Id);
2996 end if;
2998 -- Accept statement, block, entry body, package body, protected body,
2999 -- subprogram body or task body.
3001 else
3002 Decls := Declarations (N);
3003 HSS := Handled_Statement_Sequence (N);
3005 if Present (HSS) then
3006 if Present (Statements (HSS)) then
3007 Stmts := Statements (HSS);
3008 end if;
3010 if Present (At_End_Proc (HSS)) then
3011 Prev_At_End := At_End_Proc (HSS);
3012 end if;
3013 end if;
3015 -- Retrieve the package spec id for package bodies
3017 if For_Package_Body then
3018 Spec_Id := Corresponding_Spec (N);
3019 end if;
3020 end if;
3022 -- Do not process nested packages since those are handled by the
3023 -- enclosing scope's finalizer. Do not process non-expanded package
3024 -- instantiations since those will be re-analyzed and re-expanded.
3026 if For_Package
3027 and then
3028 (not Is_Library_Level_Entity (Spec_Id)
3030 -- Nested packages are considered to be library level entities,
3031 -- but do not need to be processed separately. True library level
3032 -- packages have a scope value of 1.
3034 or else Scope_Depth_Value (Spec_Id) /= Uint_1
3035 or else (Is_Generic_Instance (Spec_Id)
3036 and then Package_Instantiation (Spec_Id) /= N))
3037 then
3038 return;
3039 end if;
3041 -- Step 2: Object [pre]processing
3043 if For_Package then
3045 -- Preprocess the visible declarations now in order to obtain the
3046 -- correct number of controlled object by the time the private
3047 -- declarations are processed.
3049 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3051 -- From all the possible contexts, only package specifications may
3052 -- have private declarations.
3054 if For_Package_Spec then
3055 Process_Declarations
3056 (Priv_Decls, Preprocess => True, Top_Level => True);
3057 end if;
3059 -- The current context may lack controlled objects, but require some
3060 -- other form of completion (task termination for instance). In such
3061 -- cases, the finalizer must be created and carry the additional
3062 -- statements.
3064 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3065 Build_Components;
3066 end if;
3068 -- The preprocessing has determined that the context has controlled
3069 -- objects or library-level tagged types.
3071 if Has_Ctrl_Objs or Has_Tagged_Types then
3073 -- Private declarations are processed first in order to preserve
3074 -- possible dependencies between public and private objects.
3076 if For_Package_Spec then
3077 Process_Declarations (Priv_Decls);
3078 end if;
3080 Process_Declarations (Decls);
3081 end if;
3083 -- Non-package case
3085 else
3086 -- Preprocess both declarations and statements
3088 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3089 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
3091 -- At this point it is known that N has controlled objects. Ensure
3092 -- that N has a declarative list since the finalizer spec will be
3093 -- attached to it.
3095 if Has_Ctrl_Objs and then No (Decls) then
3096 Set_Declarations (N, New_List);
3097 Decls := Declarations (N);
3098 Spec_Decls := Decls;
3099 end if;
3101 -- The current context may lack controlled objects, but require some
3102 -- other form of completion (task termination for instance). In such
3103 -- cases, the finalizer must be created and carry the additional
3104 -- statements.
3106 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3107 Build_Components;
3108 end if;
3110 if Has_Ctrl_Objs or Has_Tagged_Types then
3111 Process_Declarations (Stmts);
3112 Process_Declarations (Decls);
3113 end if;
3114 end if;
3116 -- Step 3: Finalizer creation
3118 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3119 Create_Finalizer;
3120 end if;
3121 end Build_Finalizer;
3123 --------------------------
3124 -- Build_Finalizer_Call --
3125 --------------------------
3127 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
3128 Is_Prot_Body : constant Boolean :=
3129 Nkind (N) = N_Subprogram_Body
3130 and then Is_Protected_Subprogram_Body (N);
3131 -- Determine whether N denotes the protected version of a subprogram
3132 -- which belongs to a protected type.
3134 Loc : constant Source_Ptr := Sloc (N);
3135 HSS : Node_Id;
3137 begin
3138 -- Do not perform this expansion in SPARK mode because we do not create
3139 -- finalizers in the first place.
3141 if GNATprove_Mode then
3142 return;
3143 end if;
3145 -- The At_End handler should have been assimilated by the finalizer
3147 HSS := Handled_Statement_Sequence (N);
3148 pragma Assert (No (At_End_Proc (HSS)));
3150 -- If the construct to be cleaned up is a protected subprogram body, the
3151 -- finalizer call needs to be associated with the block which wraps the
3152 -- unprotected version of the subprogram. The following illustrates this
3153 -- scenario:
3155 -- procedure Prot_SubpP is
3156 -- procedure finalizer is
3157 -- begin
3158 -- Service_Entries (Prot_Obj);
3159 -- Abort_Undefer;
3160 -- end finalizer;
3162 -- begin
3163 -- . . .
3164 -- begin
3165 -- Prot_SubpN (Prot_Obj);
3166 -- at end
3167 -- finalizer;
3168 -- end;
3169 -- end Prot_SubpP;
3171 if Is_Prot_Body then
3172 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
3174 -- An At_End handler and regular exception handlers cannot coexist in
3175 -- the same statement sequence. Wrap the original statements in a block.
3177 elsif Present (Exception_Handlers (HSS)) then
3178 declare
3179 End_Lab : constant Node_Id := End_Label (HSS);
3180 Block : Node_Id;
3182 begin
3183 Block :=
3184 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
3186 Set_Handled_Statement_Sequence (N,
3187 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3189 HSS := Handled_Statement_Sequence (N);
3190 Set_End_Label (HSS, End_Lab);
3191 end;
3192 end if;
3194 Set_At_End_Proc (HSS, New_Occurrence_Of (Fin_Id, Loc));
3196 Analyze (At_End_Proc (HSS));
3197 Expand_At_End_Handler (HSS, Empty);
3198 end Build_Finalizer_Call;
3200 ---------------------
3201 -- Build_Late_Proc --
3202 ---------------------
3204 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
3205 begin
3206 for Final_Prim in Name_Of'Range loop
3207 if Name_Of (Final_Prim) = Nam then
3208 Set_TSS (Typ,
3209 Make_Deep_Proc
3210 (Prim => Final_Prim,
3211 Typ => Typ,
3212 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
3213 end if;
3214 end loop;
3215 end Build_Late_Proc;
3217 -------------------------------
3218 -- Build_Object_Declarations --
3219 -------------------------------
3221 procedure Build_Object_Declarations
3222 (Data : out Finalization_Exception_Data;
3223 Decls : List_Id;
3224 Loc : Source_Ptr;
3225 For_Package : Boolean := False)
3227 Decl : Node_Id;
3229 Dummy : Entity_Id;
3230 -- This variable captures an unused dummy internal entity, see the
3231 -- comment associated with its use.
3233 begin
3234 pragma Assert (Decls /= No_List);
3236 -- Always set the proper location as it may be needed even when
3237 -- exception propagation is forbidden.
3239 Data.Loc := Loc;
3241 if Restriction_Active (No_Exception_Propagation) then
3242 Data.Abort_Id := Empty;
3243 Data.E_Id := Empty;
3244 Data.Raised_Id := Empty;
3245 return;
3246 end if;
3248 Data.Raised_Id := Make_Temporary (Loc, 'R');
3250 -- In certain scenarios, finalization can be triggered by an abort. If
3251 -- the finalization itself fails and raises an exception, the resulting
3252 -- Program_Error must be supressed and replaced by an abort signal. In
3253 -- order to detect this scenario, save the state of entry into the
3254 -- finalization code.
3256 -- No need to do this for VM case, since VM version of Ada.Exceptions
3257 -- does not include routine Raise_From_Controlled_Operation which is the
3258 -- the sole user of flag Abort.
3260 -- This is not needed for library-level finalizers as they are called by
3261 -- the environment task and cannot be aborted.
3263 if VM_Target = No_VM and then not For_Package then
3264 if Abort_Allowed then
3265 Data.Abort_Id := Make_Temporary (Loc, 'A');
3267 -- Generate:
3268 -- Abort_Id : constant Boolean := <A_Expr>;
3270 Append_To (Decls,
3271 Make_Object_Declaration (Loc,
3272 Defining_Identifier => Data.Abort_Id,
3273 Constant_Present => True,
3274 Object_Definition =>
3275 New_Occurrence_Of (Standard_Boolean, Loc),
3276 Expression =>
3277 New_Occurrence_Of (RTE (RE_Triggered_By_Abort), Loc)));
3279 -- Abort is not required
3281 else
3282 -- Generate a dummy entity to ensure that the internal symbols are
3283 -- in sync when a unit is compiled with and without aborts.
3285 Dummy := Make_Temporary (Loc, 'A');
3286 Data.Abort_Id := Empty;
3287 end if;
3289 -- .NET/JVM or library-level finalizers
3291 else
3292 Data.Abort_Id := Empty;
3293 end if;
3295 if Exception_Extra_Info then
3296 Data.E_Id := Make_Temporary (Loc, 'E');
3298 -- Generate:
3299 -- E_Id : Exception_Occurrence;
3301 Decl :=
3302 Make_Object_Declaration (Loc,
3303 Defining_Identifier => Data.E_Id,
3304 Object_Definition =>
3305 New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc));
3306 Set_No_Initialization (Decl);
3308 Append_To (Decls, Decl);
3310 else
3311 Data.E_Id := Empty;
3312 end if;
3314 -- Generate:
3315 -- Raised_Id : Boolean := False;
3317 Append_To (Decls,
3318 Make_Object_Declaration (Loc,
3319 Defining_Identifier => Data.Raised_Id,
3320 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
3321 Expression => New_Occurrence_Of (Standard_False, Loc)));
3322 end Build_Object_Declarations;
3324 ---------------------------
3325 -- Build_Raise_Statement --
3326 ---------------------------
3328 function Build_Raise_Statement
3329 (Data : Finalization_Exception_Data) return Node_Id
3331 Stmt : Node_Id;
3332 Expr : Node_Id;
3334 begin
3335 -- Standard run-time and .NET/JVM targets use the specialized routine
3336 -- Raise_From_Controlled_Operation.
3338 if Exception_Extra_Info
3339 and then RTE_Available (RE_Raise_From_Controlled_Operation)
3340 then
3341 Stmt :=
3342 Make_Procedure_Call_Statement (Data.Loc,
3343 Name =>
3344 New_Occurrence_Of
3345 (RTE (RE_Raise_From_Controlled_Operation), Data.Loc),
3346 Parameter_Associations =>
3347 New_List (New_Occurrence_Of (Data.E_Id, Data.Loc)));
3349 -- Restricted run-time: exception messages are not supported and hence
3350 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3351 -- instead.
3353 else
3354 Stmt :=
3355 Make_Raise_Program_Error (Data.Loc,
3356 Reason => PE_Finalize_Raised_Exception);
3357 end if;
3359 -- Generate:
3361 -- Raised_Id and then not Abort_Id
3362 -- <or>
3363 -- Raised_Id
3365 Expr := New_Occurrence_Of (Data.Raised_Id, Data.Loc);
3367 if Present (Data.Abort_Id) then
3368 Expr := Make_And_Then (Data.Loc,
3369 Left_Opnd => Expr,
3370 Right_Opnd =>
3371 Make_Op_Not (Data.Loc,
3372 Right_Opnd => New_Occurrence_Of (Data.Abort_Id, Data.Loc)));
3373 end if;
3375 -- Generate:
3377 -- if Raised_Id and then not Abort_Id then
3378 -- Raise_From_Controlled_Operation (E_Id);
3379 -- <or>
3380 -- raise Program_Error; -- restricted runtime
3381 -- end if;
3383 return
3384 Make_If_Statement (Data.Loc,
3385 Condition => Expr,
3386 Then_Statements => New_List (Stmt));
3387 end Build_Raise_Statement;
3389 -----------------------------
3390 -- Build_Record_Deep_Procs --
3391 -----------------------------
3393 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3394 begin
3395 Set_TSS (Typ,
3396 Make_Deep_Proc
3397 (Prim => Initialize_Case,
3398 Typ => Typ,
3399 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3401 if not Is_Limited_View (Typ) then
3402 Set_TSS (Typ,
3403 Make_Deep_Proc
3404 (Prim => Adjust_Case,
3405 Typ => Typ,
3406 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3407 end if;
3409 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3410 -- suppressed since these routine will not be used.
3412 if not Restriction_Active (No_Finalization) then
3413 Set_TSS (Typ,
3414 Make_Deep_Proc
3415 (Prim => Finalize_Case,
3416 Typ => Typ,
3417 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3419 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3420 -- .NET do not support address arithmetic and unchecked conversions.
3422 if VM_Target = No_VM then
3423 Set_TSS (Typ,
3424 Make_Deep_Proc
3425 (Prim => Address_Case,
3426 Typ => Typ,
3427 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3428 end if;
3429 end if;
3430 end Build_Record_Deep_Procs;
3432 -------------------
3433 -- Cleanup_Array --
3434 -------------------
3436 function Cleanup_Array
3437 (N : Node_Id;
3438 Obj : Node_Id;
3439 Typ : Entity_Id) return List_Id
3441 Loc : constant Source_Ptr := Sloc (N);
3442 Index_List : constant List_Id := New_List;
3444 function Free_Component return List_Id;
3445 -- Generate the code to finalize the task or protected subcomponents
3446 -- of a single component of the array.
3448 function Free_One_Dimension (Dim : Int) return List_Id;
3449 -- Generate a loop over one dimension of the array
3451 --------------------
3452 -- Free_Component --
3453 --------------------
3455 function Free_Component return List_Id is
3456 Stmts : List_Id := New_List;
3457 Tsk : Node_Id;
3458 C_Typ : constant Entity_Id := Component_Type (Typ);
3460 begin
3461 -- Component type is known to contain tasks or protected objects
3463 Tsk :=
3464 Make_Indexed_Component (Loc,
3465 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3466 Expressions => Index_List);
3468 Set_Etype (Tsk, C_Typ);
3470 if Is_Task_Type (C_Typ) then
3471 Append_To (Stmts, Cleanup_Task (N, Tsk));
3473 elsif Is_Simple_Protected_Type (C_Typ) then
3474 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3476 elsif Is_Record_Type (C_Typ) then
3477 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3479 elsif Is_Array_Type (C_Typ) then
3480 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3481 end if;
3483 return Stmts;
3484 end Free_Component;
3486 ------------------------
3487 -- Free_One_Dimension --
3488 ------------------------
3490 function Free_One_Dimension (Dim : Int) return List_Id is
3491 Index : Entity_Id;
3493 begin
3494 if Dim > Number_Dimensions (Typ) then
3495 return Free_Component;
3497 -- Here we generate the required loop
3499 else
3500 Index := Make_Temporary (Loc, 'J');
3501 Append (New_Occurrence_Of (Index, Loc), Index_List);
3503 return New_List (
3504 Make_Implicit_Loop_Statement (N,
3505 Identifier => Empty,
3506 Iteration_Scheme =>
3507 Make_Iteration_Scheme (Loc,
3508 Loop_Parameter_Specification =>
3509 Make_Loop_Parameter_Specification (Loc,
3510 Defining_Identifier => Index,
3511 Discrete_Subtype_Definition =>
3512 Make_Attribute_Reference (Loc,
3513 Prefix => Duplicate_Subexpr (Obj),
3514 Attribute_Name => Name_Range,
3515 Expressions => New_List (
3516 Make_Integer_Literal (Loc, Dim))))),
3517 Statements => Free_One_Dimension (Dim + 1)));
3518 end if;
3519 end Free_One_Dimension;
3521 -- Start of processing for Cleanup_Array
3523 begin
3524 return Free_One_Dimension (1);
3525 end Cleanup_Array;
3527 --------------------
3528 -- Cleanup_Record --
3529 --------------------
3531 function Cleanup_Record
3532 (N : Node_Id;
3533 Obj : Node_Id;
3534 Typ : Entity_Id) return List_Id
3536 Loc : constant Source_Ptr := Sloc (N);
3537 Tsk : Node_Id;
3538 Comp : Entity_Id;
3539 Stmts : constant List_Id := New_List;
3540 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3542 begin
3543 if Has_Discriminants (U_Typ)
3544 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3545 and then Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3546 and then
3547 Present
3548 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3549 then
3550 -- For now, do not attempt to free a component that may appear in a
3551 -- variant, and instead issue a warning. Doing this "properly" would
3552 -- require building a case statement and would be quite a mess. Note
3553 -- that the RM only requires that free "work" for the case of a task
3554 -- access value, so already we go way beyond this in that we deal
3555 -- with the array case and non-discriminated record cases.
3557 Error_Msg_N
3558 ("task/protected object in variant record will not be freed??", N);
3559 return New_List (Make_Null_Statement (Loc));
3560 end if;
3562 Comp := First_Component (Typ);
3563 while Present (Comp) loop
3564 if Has_Task (Etype (Comp))
3565 or else Has_Simple_Protected_Object (Etype (Comp))
3566 then
3567 Tsk :=
3568 Make_Selected_Component (Loc,
3569 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3570 Selector_Name => New_Occurrence_Of (Comp, Loc));
3571 Set_Etype (Tsk, Etype (Comp));
3573 if Is_Task_Type (Etype (Comp)) then
3574 Append_To (Stmts, Cleanup_Task (N, Tsk));
3576 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3577 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3579 elsif Is_Record_Type (Etype (Comp)) then
3581 -- Recurse, by generating the prefix of the argument to
3582 -- the eventual cleanup call.
3584 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3586 elsif Is_Array_Type (Etype (Comp)) then
3587 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3588 end if;
3589 end if;
3591 Next_Component (Comp);
3592 end loop;
3594 return Stmts;
3595 end Cleanup_Record;
3597 ------------------------------
3598 -- Cleanup_Protected_Object --
3599 ------------------------------
3601 function Cleanup_Protected_Object
3602 (N : Node_Id;
3603 Ref : Node_Id) return Node_Id
3605 Loc : constant Source_Ptr := Sloc (N);
3607 begin
3608 -- For restricted run-time libraries (Ravenscar), tasks are
3609 -- non-terminating, and protected objects can only appear at library
3610 -- level, so we do not want finalization of protected objects.
3612 if Restricted_Profile then
3613 return Empty;
3615 else
3616 return
3617 Make_Procedure_Call_Statement (Loc,
3618 Name =>
3619 New_Occurrence_Of (RTE (RE_Finalize_Protection), Loc),
3620 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3621 end if;
3622 end Cleanup_Protected_Object;
3624 ------------------
3625 -- Cleanup_Task --
3626 ------------------
3628 function Cleanup_Task
3629 (N : Node_Id;
3630 Ref : Node_Id) return Node_Id
3632 Loc : constant Source_Ptr := Sloc (N);
3634 begin
3635 -- For restricted run-time libraries (Ravenscar), tasks are
3636 -- non-terminating and they can only appear at library level, so we do
3637 -- not want finalization of task objects.
3639 if Restricted_Profile then
3640 return Empty;
3642 else
3643 return
3644 Make_Procedure_Call_Statement (Loc,
3645 Name =>
3646 New_Occurrence_Of (RTE (RE_Free_Task), Loc),
3647 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3648 end if;
3649 end Cleanup_Task;
3651 ------------------------------
3652 -- Check_Visibly_Controlled --
3653 ------------------------------
3655 procedure Check_Visibly_Controlled
3656 (Prim : Final_Primitives;
3657 Typ : Entity_Id;
3658 E : in out Entity_Id;
3659 Cref : in out Node_Id)
3661 Parent_Type : Entity_Id;
3662 Op : Entity_Id;
3664 begin
3665 if Is_Derived_Type (Typ)
3666 and then Comes_From_Source (E)
3667 and then not Present (Overridden_Operation (E))
3668 then
3669 -- We know that the explicit operation on the type does not override
3670 -- the inherited operation of the parent, and that the derivation
3671 -- is from a private type that is not visibly controlled.
3673 Parent_Type := Etype (Typ);
3674 Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3676 if Present (Op) then
3677 E := Op;
3679 -- Wrap the object to be initialized into the proper
3680 -- unchecked conversion, to be compatible with the operation
3681 -- to be called.
3683 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3684 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3685 else
3686 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3687 end if;
3688 end if;
3689 end if;
3690 end Check_Visibly_Controlled;
3692 -------------------------------
3693 -- CW_Or_Has_Controlled_Part --
3694 -------------------------------
3696 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3697 begin
3698 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3699 end CW_Or_Has_Controlled_Part;
3701 ------------------
3702 -- Convert_View --
3703 ------------------
3705 function Convert_View
3706 (Proc : Entity_Id;
3707 Arg : Node_Id;
3708 Ind : Pos := 1) return Node_Id
3710 Fent : Entity_Id := First_Entity (Proc);
3711 Ftyp : Entity_Id;
3712 Atyp : Entity_Id;
3714 begin
3715 for J in 2 .. Ind loop
3716 Next_Entity (Fent);
3717 end loop;
3719 Ftyp := Etype (Fent);
3721 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3722 Atyp := Entity (Subtype_Mark (Arg));
3723 else
3724 Atyp := Etype (Arg);
3725 end if;
3727 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3728 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3730 elsif Ftyp /= Atyp
3731 and then Present (Atyp)
3732 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3733 and then Base_Type (Underlying_Type (Atyp)) =
3734 Base_Type (Underlying_Type (Ftyp))
3735 then
3736 return Unchecked_Convert_To (Ftyp, Arg);
3738 -- If the argument is already a conversion, as generated by
3739 -- Make_Init_Call, set the target type to the type of the formal
3740 -- directly, to avoid spurious typing problems.
3742 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3743 and then not Is_Class_Wide_Type (Atyp)
3744 then
3745 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3746 Set_Etype (Arg, Ftyp);
3747 return Arg;
3749 -- Otherwise, introduce a conversion when the designated object
3750 -- has a type derived from the formal of the controlled routine.
3752 elsif Is_Private_Type (Ftyp)
3753 and then Present (Atyp)
3754 and then Is_Derived_Type (Underlying_Type (Base_Type (Atyp)))
3755 then
3756 return Unchecked_Convert_To (Ftyp, Arg);
3758 else
3759 return Arg;
3760 end if;
3761 end Convert_View;
3763 ------------------------
3764 -- Enclosing_Function --
3765 ------------------------
3767 function Enclosing_Function (E : Entity_Id) return Entity_Id is
3768 Func_Id : Entity_Id;
3770 begin
3771 Func_Id := E;
3772 while Present (Func_Id) and then Func_Id /= Standard_Standard loop
3773 if Ekind (Func_Id) = E_Function then
3774 return Func_Id;
3775 end if;
3777 Func_Id := Scope (Func_Id);
3778 end loop;
3780 return Empty;
3781 end Enclosing_Function;
3783 -------------------------------
3784 -- Establish_Transient_Scope --
3785 -------------------------------
3787 -- This procedure is called each time a transient block has to be inserted
3788 -- that is to say for each call to a function with unconstrained or tagged
3789 -- result. It creates a new scope on the stack scope in order to enclose
3790 -- all transient variables generated.
3792 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3793 Loc : constant Source_Ptr := Sloc (N);
3794 Iter_Loop : Entity_Id;
3795 Wrap_Node : Node_Id;
3797 begin
3798 -- Do not create a transient scope if we are already inside one
3800 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3801 if Scope_Stack.Table (S).Is_Transient then
3802 if Sec_Stack then
3803 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3804 end if;
3806 return;
3808 -- If we encounter Standard there are no enclosing transient scopes
3810 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3811 exit;
3812 end if;
3813 end loop;
3815 Wrap_Node := Find_Node_To_Be_Wrapped (N);
3817 -- The context does not contain a node that requires a transient scope,
3818 -- nothing to do.
3820 if No (Wrap_Node) then
3821 null;
3823 -- If the node to wrap is an iteration_scheme, the expression is one of
3824 -- the bounds, and the expansion will make an explicit declaration for
3825 -- it (see Analyze_Iteration_Scheme, sem_ch5.adb), so do not apply any
3826 -- transformations here. Same for an Ada 2012 iterator specification,
3827 -- where a block is created for the expression that build the container.
3829 elsif Nkind_In (Wrap_Node, N_Iteration_Scheme,
3830 N_Iterator_Specification)
3831 then
3832 null;
3834 -- In formal verification mode, if the node to wrap is a pragma check,
3835 -- this node and enclosed expression are not expanded, so do not apply
3836 -- any transformations here.
3838 elsif GNATprove_Mode
3839 and then Nkind (Wrap_Node) = N_Pragma
3840 and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
3841 then
3842 null;
3844 -- Create a block entity to act as a transient scope. Note that when the
3845 -- node to be wrapped is an expression or a statement, a real physical
3846 -- block is constructed (see routines Wrap_Transient_Expression and
3847 -- Wrap_Transient_Statement) and inserted into the tree.
3849 else
3850 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3851 Set_Scope_Is_Transient;
3853 -- The transient scope must also take care of the secondary stack
3854 -- management.
3856 if Sec_Stack then
3857 Set_Uses_Sec_Stack (Current_Scope);
3858 Check_Restriction (No_Secondary_Stack, N);
3860 -- The expansion of iterator loops generates references to objects
3861 -- in order to extract elements from a container:
3863 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
3864 -- Obj : <object type> renames Ref.all.Element.all;
3866 -- These references are controlled and returned on the secondary
3867 -- stack. A new reference is created at each iteration of the loop
3868 -- and as a result it must be finalized and the space occupied by
3869 -- it on the secondary stack reclaimed at the end of the current
3870 -- iteration.
3872 -- When the context that requires a transient scope is a call to
3873 -- routine Reference, the node to be wrapped is the source object:
3875 -- for Obj of Container loop
3877 -- Routine Wrap_Transient_Declaration however does not generate a
3878 -- physical block as wrapping a declaration will kill it too ealy.
3879 -- To handle this peculiar case, mark the related iterator loop as
3880 -- requiring the secondary stack. This signals the finalization
3881 -- machinery to manage the secondary stack (see routine
3882 -- Process_Statements_For_Controlled_Objects).
3884 Iter_Loop := Find_Enclosing_Iterator_Loop (Current_Scope);
3886 if Present (Iter_Loop) then
3887 Set_Uses_Sec_Stack (Iter_Loop);
3888 end if;
3889 end if;
3891 Set_Etype (Current_Scope, Standard_Void_Type);
3892 Set_Node_To_Be_Wrapped (Wrap_Node);
3894 if Debug_Flag_W then
3895 Write_Str (" <Transient>");
3896 Write_Eol;
3897 end if;
3898 end if;
3899 end Establish_Transient_Scope;
3901 ----------------------------
3902 -- Expand_Cleanup_Actions --
3903 ----------------------------
3905 procedure Expand_Cleanup_Actions (N : Node_Id) is
3906 Scop : constant Entity_Id := Current_Scope;
3908 Is_Asynchronous_Call : constant Boolean :=
3909 Nkind (N) = N_Block_Statement
3910 and then Is_Asynchronous_Call_Block (N);
3911 Is_Master : constant Boolean :=
3912 Nkind (N) /= N_Entry_Body
3913 and then Is_Task_Master (N);
3914 Is_Protected_Body : constant Boolean :=
3915 Nkind (N) = N_Subprogram_Body
3916 and then Is_Protected_Subprogram_Body (N);
3917 Is_Task_Allocation : constant Boolean :=
3918 Nkind (N) = N_Block_Statement
3919 and then Is_Task_Allocation_Block (N);
3920 Is_Task_Body : constant Boolean :=
3921 Nkind (Original_Node (N)) = N_Task_Body;
3922 Needs_Sec_Stack_Mark : constant Boolean :=
3923 Uses_Sec_Stack (Scop)
3924 and then
3925 not Sec_Stack_Needed_For_Return (Scop)
3926 and then VM_Target = No_VM;
3927 Needs_Custom_Cleanup : constant Boolean :=
3928 Nkind (N) = N_Block_Statement
3929 and then Present (Cleanup_Actions (N));
3931 Actions_Required : constant Boolean :=
3932 Requires_Cleanup_Actions (N, True)
3933 or else Is_Asynchronous_Call
3934 or else Is_Master
3935 or else Is_Protected_Body
3936 or else Is_Task_Allocation
3937 or else Is_Task_Body
3938 or else Needs_Sec_Stack_Mark
3939 or else Needs_Custom_Cleanup;
3941 HSS : Node_Id := Handled_Statement_Sequence (N);
3942 Loc : Source_Ptr;
3943 Cln : List_Id;
3945 procedure Wrap_HSS_In_Block;
3946 -- Move HSS inside a new block along with the original exception
3947 -- handlers. Make the newly generated block the sole statement of HSS.
3949 -----------------------
3950 -- Wrap_HSS_In_Block --
3951 -----------------------
3953 procedure Wrap_HSS_In_Block is
3954 Block : Node_Id;
3955 End_Lab : Node_Id;
3957 begin
3958 -- Preserve end label to provide proper cross-reference information
3960 End_Lab := End_Label (HSS);
3961 Block :=
3962 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
3964 -- Signal the finalization machinery that this particular block
3965 -- contains the original context.
3967 Set_Is_Finalization_Wrapper (Block);
3969 Set_Handled_Statement_Sequence (N,
3970 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3971 HSS := Handled_Statement_Sequence (N);
3973 Set_First_Real_Statement (HSS, Block);
3974 Set_End_Label (HSS, End_Lab);
3976 -- Comment needed here, see RH for 1.306 ???
3978 if Nkind (N) = N_Subprogram_Body then
3979 Set_Has_Nested_Block_With_Handler (Scop);
3980 end if;
3981 end Wrap_HSS_In_Block;
3983 -- Start of processing for Expand_Cleanup_Actions
3985 begin
3986 -- The current construct does not need any form of servicing
3988 if not Actions_Required then
3989 return;
3991 -- If the current node is a rewritten task body and the descriptors have
3992 -- not been delayed (due to some nested instantiations), do not generate
3993 -- redundant cleanup actions.
3995 elsif Is_Task_Body
3996 and then Nkind (N) = N_Subprogram_Body
3997 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3998 then
3999 return;
4000 end if;
4002 if Needs_Custom_Cleanup then
4003 Cln := Cleanup_Actions (N);
4004 else
4005 Cln := No_List;
4006 end if;
4008 declare
4009 Decls : List_Id := Declarations (N);
4010 Fin_Id : Entity_Id;
4011 Mark : Entity_Id := Empty;
4012 New_Decls : List_Id;
4013 Old_Poll : Boolean;
4015 begin
4016 -- If we are generating expanded code for debugging purposes, use the
4017 -- Sloc of the point of insertion for the cleanup code. The Sloc will
4018 -- be updated subsequently to reference the proper line in .dg files.
4019 -- If we are not debugging generated code, use No_Location instead,
4020 -- so that no debug information is generated for the cleanup code.
4021 -- This makes the behavior of the NEXT command in GDB monotonic, and
4022 -- makes the placement of breakpoints more accurate.
4024 if Debug_Generated_Code then
4025 Loc := Sloc (Scop);
4026 else
4027 Loc := No_Location;
4028 end if;
4030 -- Set polling off. The finalization and cleanup code is executed
4031 -- with aborts deferred.
4033 Old_Poll := Polling_Required;
4034 Polling_Required := False;
4036 -- A task activation call has already been built for a task
4037 -- allocation block.
4039 if not Is_Task_Allocation then
4040 Build_Task_Activation_Call (N);
4041 end if;
4043 if Is_Master then
4044 Establish_Task_Master (N);
4045 end if;
4047 New_Decls := New_List;
4049 -- If secondary stack is in use, generate:
4051 -- Mnn : constant Mark_Id := SS_Mark;
4053 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
4054 -- secondary stack is never used on a VM.
4056 if Needs_Sec_Stack_Mark then
4057 Mark := Make_Temporary (Loc, 'M');
4059 Append_To (New_Decls, Build_SS_Mark_Call (Loc, Mark));
4060 Set_Uses_Sec_Stack (Scop, False);
4061 end if;
4063 -- If exception handlers are present, wrap the sequence of statements
4064 -- in a block since it is not possible to have exception handlers and
4065 -- an At_End handler in the same construct.
4067 if Present (Exception_Handlers (HSS)) then
4068 Wrap_HSS_In_Block;
4070 -- Ensure that the First_Real_Statement field is set
4072 elsif No (First_Real_Statement (HSS)) then
4073 Set_First_Real_Statement (HSS, First (Statements (HSS)));
4074 end if;
4076 -- Do not move the Activation_Chain declaration in the context of
4077 -- task allocation blocks. Task allocation blocks use _chain in their
4078 -- cleanup handlers and gigi complains if it is declared in the
4079 -- sequence of statements of the scope that declares the handler.
4081 if Is_Task_Allocation then
4082 declare
4083 Chain : constant Entity_Id := Activation_Chain_Entity (N);
4084 Decl : Node_Id;
4086 begin
4087 Decl := First (Decls);
4088 while Nkind (Decl) /= N_Object_Declaration
4089 or else Defining_Identifier (Decl) /= Chain
4090 loop
4091 Next (Decl);
4093 -- A task allocation block should always include a _chain
4094 -- declaration.
4096 pragma Assert (Present (Decl));
4097 end loop;
4099 Remove (Decl);
4100 Prepend_To (New_Decls, Decl);
4101 end;
4102 end if;
4104 -- Ensure the presence of a declaration list in order to successfully
4105 -- append all original statements to it.
4107 if No (Decls) then
4108 Set_Declarations (N, New_List);
4109 Decls := Declarations (N);
4110 end if;
4112 -- Move the declarations into the sequence of statements in order to
4113 -- have them protected by the At_End handler. It may seem weird to
4114 -- put declarations in the sequence of statement but in fact nothing
4115 -- forbids that at the tree level.
4117 Append_List_To (Decls, Statements (HSS));
4118 Set_Statements (HSS, Decls);
4120 -- Reset the Sloc of the handled statement sequence to properly
4121 -- reflect the new initial "statement" in the sequence.
4123 Set_Sloc (HSS, Sloc (First (Decls)));
4125 -- The declarations of finalizer spec and auxiliary variables replace
4126 -- the old declarations that have been moved inward.
4128 Set_Declarations (N, New_Decls);
4129 Analyze_Declarations (New_Decls);
4131 -- Generate finalization calls for all controlled objects appearing
4132 -- in the statements of N. Add context specific cleanup for various
4133 -- constructs.
4135 Build_Finalizer
4136 (N => N,
4137 Clean_Stmts => Build_Cleanup_Statements (N, Cln),
4138 Mark_Id => Mark,
4139 Top_Decls => New_Decls,
4140 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
4141 or else Is_Master,
4142 Fin_Id => Fin_Id);
4144 if Present (Fin_Id) then
4145 Build_Finalizer_Call (N, Fin_Id);
4146 end if;
4148 -- Restore saved polling mode
4150 Polling_Required := Old_Poll;
4151 end;
4152 end Expand_Cleanup_Actions;
4154 ---------------------------
4155 -- Expand_N_Package_Body --
4156 ---------------------------
4158 -- Add call to Activate_Tasks if body is an activator (actual processing
4159 -- is in chapter 9).
4161 -- Generate subprogram descriptor for elaboration routine
4163 -- Encode entity names in package body
4165 procedure Expand_N_Package_Body (N : Node_Id) is
4166 Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
4167 Fin_Id : Entity_Id;
4169 begin
4170 -- This is done only for non-generic packages
4172 if Ekind (Spec_Ent) = E_Package then
4173 Push_Scope (Corresponding_Spec (N));
4175 -- Build dispatch tables of library level tagged types
4177 if Tagged_Type_Expansion
4178 and then Is_Library_Level_Entity (Spec_Ent)
4179 then
4180 Build_Static_Dispatch_Tables (N);
4181 end if;
4183 Build_Task_Activation_Call (N);
4185 -- When the package is subject to pragma Initial_Condition, the
4186 -- assertion expression must be verified at the end of the body
4187 -- statements.
4189 if Present (Get_Pragma (Spec_Ent, Pragma_Initial_Condition)) then
4190 Expand_Pragma_Initial_Condition (N);
4191 end if;
4193 Pop_Scope;
4194 end if;
4196 Set_Elaboration_Flag (N, Corresponding_Spec (N));
4197 Set_In_Package_Body (Spec_Ent, False);
4199 -- Set to encode entity names in package body before gigi is called
4201 Qualify_Entity_Names (N);
4203 if Ekind (Spec_Ent) /= E_Generic_Package then
4204 Build_Finalizer
4205 (N => N,
4206 Clean_Stmts => No_List,
4207 Mark_Id => Empty,
4208 Top_Decls => No_List,
4209 Defer_Abort => False,
4210 Fin_Id => Fin_Id);
4212 if Present (Fin_Id) then
4213 declare
4214 Body_Ent : Node_Id := Defining_Unit_Name (N);
4216 begin
4217 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
4218 Body_Ent := Defining_Identifier (Body_Ent);
4219 end if;
4221 Set_Finalizer (Body_Ent, Fin_Id);
4222 end;
4223 end if;
4224 end if;
4225 end Expand_N_Package_Body;
4227 ----------------------------------
4228 -- Expand_N_Package_Declaration --
4229 ----------------------------------
4231 -- Add call to Activate_Tasks if there are tasks declared and the package
4232 -- has no body. Note that in Ada 83 this may result in premature activation
4233 -- of some tasks, given that we cannot tell whether a body will eventually
4234 -- appear.
4236 procedure Expand_N_Package_Declaration (N : Node_Id) is
4237 Id : constant Entity_Id := Defining_Entity (N);
4238 Spec : constant Node_Id := Specification (N);
4239 Decls : List_Id;
4240 Fin_Id : Entity_Id;
4242 No_Body : Boolean := False;
4243 -- True in the case of a package declaration that is a compilation
4244 -- unit and for which no associated body will be compiled in this
4245 -- compilation.
4247 begin
4248 -- Case of a package declaration other than a compilation unit
4250 if Nkind (Parent (N)) /= N_Compilation_Unit then
4251 null;
4253 -- Case of a compilation unit that does not require a body
4255 elsif not Body_Required (Parent (N))
4256 and then not Unit_Requires_Body (Id)
4257 then
4258 No_Body := True;
4260 -- Special case of generating calling stubs for a remote call interface
4261 -- package: even though the package declaration requires one, the body
4262 -- won't be processed in this compilation (so any stubs for RACWs
4263 -- declared in the package must be generated here, along with the spec).
4265 elsif Parent (N) = Cunit (Main_Unit)
4266 and then Is_Remote_Call_Interface (Id)
4267 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
4268 then
4269 No_Body := True;
4270 end if;
4272 -- For a nested instance, delay processing until freeze point
4274 if Has_Delayed_Freeze (Id)
4275 and then Nkind (Parent (N)) /= N_Compilation_Unit
4276 then
4277 return;
4278 end if;
4280 -- For a package declaration that implies no associated body, generate
4281 -- task activation call and RACW supporting bodies now (since we won't
4282 -- have a specific separate compilation unit for that).
4284 if No_Body then
4285 Push_Scope (Id);
4287 -- Generate RACW subprogram bodies
4289 if Has_RACW (Id) then
4290 Decls := Private_Declarations (Spec);
4292 if No (Decls) then
4293 Decls := Visible_Declarations (Spec);
4294 end if;
4296 if No (Decls) then
4297 Decls := New_List;
4298 Set_Visible_Declarations (Spec, Decls);
4299 end if;
4301 Append_RACW_Bodies (Decls, Id);
4302 Analyze_List (Decls);
4303 end if;
4305 -- Generate task activation call as last step of elaboration
4307 if Present (Activation_Chain_Entity (N)) then
4308 Build_Task_Activation_Call (N);
4309 end if;
4311 -- When the package is subject to pragma Initial_Condition and lacks
4312 -- a body, the assertion expression must be verified at the end of
4313 -- the visible declarations. Otherwise the check is performed at the
4314 -- end of the body statements (see Expand_N_Package_Body).
4316 if Present (Get_Pragma (Id, Pragma_Initial_Condition)) then
4317 Expand_Pragma_Initial_Condition (N);
4318 end if;
4320 Pop_Scope;
4321 end if;
4323 -- Build dispatch tables of library level tagged types
4325 if Tagged_Type_Expansion
4326 and then (Is_Compilation_Unit (Id)
4327 or else (Is_Generic_Instance (Id)
4328 and then Is_Library_Level_Entity (Id)))
4329 then
4330 Build_Static_Dispatch_Tables (N);
4331 end if;
4333 -- Note: it is not necessary to worry about generating a subprogram
4334 -- descriptor, since the only way to get exception handlers into a
4335 -- package spec is to include instantiations, and that would cause
4336 -- generation of subprogram descriptors to be delayed in any case.
4338 -- Set to encode entity names in package spec before gigi is called
4340 Qualify_Entity_Names (N);
4342 if Ekind (Id) /= E_Generic_Package then
4343 Build_Finalizer
4344 (N => N,
4345 Clean_Stmts => No_List,
4346 Mark_Id => Empty,
4347 Top_Decls => No_List,
4348 Defer_Abort => False,
4349 Fin_Id => Fin_Id);
4351 Set_Finalizer (Id, Fin_Id);
4352 end if;
4353 end Expand_N_Package_Declaration;
4355 -----------------------------
4356 -- Find_Node_To_Be_Wrapped --
4357 -----------------------------
4359 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
4360 P : Node_Id;
4361 The_Parent : Node_Id;
4363 begin
4364 The_Parent := N;
4365 P := Empty;
4366 loop
4367 case Nkind (The_Parent) is
4369 -- Simple statement can be wrapped
4371 when N_Pragma =>
4372 return The_Parent;
4374 -- Usually assignments are good candidate for wrapping except
4375 -- when they have been generated as part of a controlled aggregate
4376 -- where the wrapping should take place more globally. Note that
4377 -- No_Ctrl_Actions may be set also for non-controlled assignements
4378 -- in order to disable the use of dispatching _assign, so we need
4379 -- to test explicitly for a controlled type here.
4381 when N_Assignment_Statement =>
4382 if No_Ctrl_Actions (The_Parent)
4383 and then Needs_Finalization (Etype (Name (The_Parent)))
4384 then
4385 null;
4386 else
4387 return The_Parent;
4388 end if;
4390 -- An entry call statement is a special case if it occurs in the
4391 -- context of a Timed_Entry_Call. In this case we wrap the entire
4392 -- timed entry call.
4394 when N_Entry_Call_Statement |
4395 N_Procedure_Call_Statement =>
4396 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
4397 and then Nkind_In (Parent (Parent (The_Parent)),
4398 N_Timed_Entry_Call,
4399 N_Conditional_Entry_Call)
4400 then
4401 return Parent (Parent (The_Parent));
4402 else
4403 return The_Parent;
4404 end if;
4406 -- Object declarations are also a boundary for the transient scope
4407 -- even if they are not really wrapped. For further details, see
4408 -- Wrap_Transient_Declaration.
4410 when N_Object_Declaration |
4411 N_Object_Renaming_Declaration |
4412 N_Subtype_Declaration =>
4413 return The_Parent;
4415 -- The expression itself is to be wrapped if its parent is a
4416 -- compound statement or any other statement where the expression
4417 -- is known to be scalar.
4419 when N_Accept_Alternative |
4420 N_Attribute_Definition_Clause |
4421 N_Case_Statement |
4422 N_Code_Statement |
4423 N_Delay_Alternative |
4424 N_Delay_Until_Statement |
4425 N_Delay_Relative_Statement |
4426 N_Discriminant_Association |
4427 N_Elsif_Part |
4428 N_Entry_Body_Formal_Part |
4429 N_Exit_Statement |
4430 N_If_Statement |
4431 N_Iteration_Scheme |
4432 N_Terminate_Alternative =>
4433 pragma Assert (Present (P));
4434 return P;
4436 when N_Attribute_Reference =>
4438 if Is_Procedure_Attribute_Name
4439 (Attribute_Name (The_Parent))
4440 then
4441 return The_Parent;
4442 end if;
4444 -- A raise statement can be wrapped. This will arise when the
4445 -- expression in a raise_with_expression uses the secondary
4446 -- stack, for example.
4448 when N_Raise_Statement =>
4449 return The_Parent;
4451 -- If the expression is within the iteration scheme of a loop,
4452 -- we must create a declaration for it, followed by an assignment
4453 -- in order to have a usable statement to wrap.
4455 when N_Loop_Parameter_Specification =>
4456 return Parent (The_Parent);
4458 -- The following nodes contains "dummy calls" which don't need to
4459 -- be wrapped.
4461 when N_Parameter_Specification |
4462 N_Discriminant_Specification |
4463 N_Component_Declaration =>
4464 return Empty;
4466 -- The return statement is not to be wrapped when the function
4467 -- itself needs wrapping at the outer-level
4469 when N_Simple_Return_Statement =>
4470 declare
4471 Applies_To : constant Entity_Id :=
4472 Return_Applies_To
4473 (Return_Statement_Entity (The_Parent));
4474 Return_Type : constant Entity_Id := Etype (Applies_To);
4475 begin
4476 if Requires_Transient_Scope (Return_Type) then
4477 return Empty;
4478 else
4479 return The_Parent;
4480 end if;
4481 end;
4483 -- If we leave a scope without having been able to find a node to
4484 -- wrap, something is going wrong but this can happen in error
4485 -- situation that are not detected yet (such as a dynamic string
4486 -- in a pragma export)
4488 when N_Subprogram_Body |
4489 N_Package_Declaration |
4490 N_Package_Body |
4491 N_Block_Statement =>
4492 return Empty;
4494 -- Otherwise continue the search
4496 when others =>
4497 null;
4498 end case;
4500 P := The_Parent;
4501 The_Parent := Parent (P);
4502 end loop;
4503 end Find_Node_To_Be_Wrapped;
4505 ----------------------------------
4506 -- Has_New_Controlled_Component --
4507 ----------------------------------
4509 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4510 Comp : Entity_Id;
4512 begin
4513 if not Is_Tagged_Type (E) then
4514 return Has_Controlled_Component (E);
4515 elsif not Is_Derived_Type (E) then
4516 return Has_Controlled_Component (E);
4517 end if;
4519 Comp := First_Component (E);
4520 while Present (Comp) loop
4521 if Chars (Comp) = Name_uParent then
4522 null;
4524 elsif Scope (Original_Record_Component (Comp)) = E
4525 and then Needs_Finalization (Etype (Comp))
4526 then
4527 return True;
4528 end if;
4530 Next_Component (Comp);
4531 end loop;
4533 return False;
4534 end Has_New_Controlled_Component;
4536 ---------------------------------
4537 -- Has_Simple_Protected_Object --
4538 ---------------------------------
4540 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4541 begin
4542 if Has_Task (T) then
4543 return False;
4545 elsif Is_Simple_Protected_Type (T) then
4546 return True;
4548 elsif Is_Array_Type (T) then
4549 return Has_Simple_Protected_Object (Component_Type (T));
4551 elsif Is_Record_Type (T) then
4552 declare
4553 Comp : Entity_Id;
4555 begin
4556 Comp := First_Component (T);
4557 while Present (Comp) loop
4558 if Has_Simple_Protected_Object (Etype (Comp)) then
4559 return True;
4560 end if;
4562 Next_Component (Comp);
4563 end loop;
4565 return False;
4566 end;
4568 else
4569 return False;
4570 end if;
4571 end Has_Simple_Protected_Object;
4573 ------------------------------------
4574 -- Insert_Actions_In_Scope_Around --
4575 ------------------------------------
4577 procedure Insert_Actions_In_Scope_Around
4578 (N : Node_Id;
4579 Clean : Boolean;
4580 Manage_SS : Boolean)
4582 Act_Before : constant List_Id :=
4583 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Before);
4584 Act_After : constant List_Id :=
4585 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (After);
4586 Act_Cleanup : constant List_Id :=
4587 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup);
4588 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
4589 -- Last), but this was incorrect as Process_Transient_Object may
4590 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
4592 procedure Process_Transient_Objects
4593 (First_Object : Node_Id;
4594 Last_Object : Node_Id;
4595 Related_Node : Node_Id);
4596 -- First_Object and Last_Object define a list which contains potential
4597 -- controlled transient objects. Finalization flags are inserted before
4598 -- First_Object and finalization calls are inserted after Last_Object.
4599 -- Related_Node is the node for which transient objects have been
4600 -- created.
4602 -------------------------------
4603 -- Process_Transient_Objects --
4604 -------------------------------
4606 procedure Process_Transient_Objects
4607 (First_Object : Node_Id;
4608 Last_Object : Node_Id;
4609 Related_Node : Node_Id)
4611 Must_Hook : Boolean := False;
4612 -- Flag denoting whether the context requires transient variable
4613 -- export to the outer finalizer.
4615 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result;
4616 -- Determine whether an arbitrary node denotes a subprogram call
4618 procedure Detect_Subprogram_Call is
4619 new Traverse_Proc (Is_Subprogram_Call);
4621 ------------------------
4622 -- Is_Subprogram_Call --
4623 ------------------------
4625 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result is
4626 begin
4627 -- Complex constructs are factored out by the expander and their
4628 -- occurrences are replaced with references to temporaries or
4629 -- object renamings. Due to this expansion activity, inspect the
4630 -- original tree to detect subprogram calls.
4632 if Nkind_In (N, N_Identifier,
4633 N_Object_Renaming_Declaration)
4634 and then Original_Node (N) /= N
4635 then
4636 Detect_Subprogram_Call (Original_Node (N));
4638 -- The original construct contains a subprogram call, there is
4639 -- no point in continuing the tree traversal.
4641 if Must_Hook then
4642 return Abandon;
4643 else
4644 return OK;
4645 end if;
4647 -- The original construct contains a subprogram call, there is no
4648 -- point in continuing the tree traversal.
4650 elsif Nkind (N) = N_Object_Declaration
4651 and then Present (Expression (N))
4652 and then Nkind (Original_Node (Expression (N))) = N_Function_Call
4653 then
4654 Must_Hook := True;
4655 return Abandon;
4657 -- A regular procedure or function call
4659 elsif Nkind (N) in N_Subprogram_Call then
4660 Must_Hook := True;
4661 return Abandon;
4663 -- Keep searching
4665 else
4666 return OK;
4667 end if;
4668 end Is_Subprogram_Call;
4670 -- Local variables
4672 Built : Boolean := False;
4673 Desig_Typ : Entity_Id;
4674 Expr : Node_Id;
4675 Fin_Block : Node_Id;
4676 Fin_Data : Finalization_Exception_Data;
4677 Fin_Decls : List_Id;
4678 Fin_Insrt : Node_Id;
4679 Last_Fin : Node_Id := Empty;
4680 Loc : Source_Ptr;
4681 Obj_Id : Entity_Id;
4682 Obj_Ref : Node_Id;
4683 Obj_Typ : Entity_Id;
4684 Prev_Fin : Node_Id := Empty;
4685 Ptr_Id : Entity_Id;
4686 Stmt : Node_Id;
4687 Stmts : List_Id;
4688 Temp_Id : Entity_Id;
4689 Temp_Ins : Node_Id;
4691 -- Start of processing for Process_Transient_Objects
4693 begin
4694 -- Recognize a scenario where the transient context is an object
4695 -- declaration initialized by a build-in-place function call:
4697 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
4699 -- The rough expansion of the above is:
4701 -- Temp : ... := Ctrl_Func_Call;
4702 -- Obj : ...;
4703 -- Res : ... := BIP_Func_Call (..., Obj, ...);
4705 -- The finalization of any controlled transient must happen after
4706 -- the build-in-place function call is executed.
4708 if Nkind (N) = N_Object_Declaration
4709 and then Present (BIP_Initialization_Call (Defining_Identifier (N)))
4710 then
4711 Must_Hook := True;
4712 Fin_Insrt := BIP_Initialization_Call (Defining_Identifier (N));
4714 -- Search the context for at least one subprogram call. If found, the
4715 -- machinery exports all transient objects to the enclosing finalizer
4716 -- due to the possibility of abnormal call termination.
4718 else
4719 Detect_Subprogram_Call (N);
4720 Fin_Insrt := Last_Object;
4721 end if;
4723 -- Examine all objects in the list First_Object .. Last_Object
4725 Stmt := First_Object;
4726 while Present (Stmt) loop
4727 if Nkind (Stmt) = N_Object_Declaration
4728 and then Analyzed (Stmt)
4729 and then Is_Finalizable_Transient (Stmt, N)
4731 -- Do not process the node to be wrapped since it will be
4732 -- handled by the enclosing finalizer.
4734 and then Stmt /= Related_Node
4735 then
4736 Loc := Sloc (Stmt);
4737 Obj_Id := Defining_Identifier (Stmt);
4738 Obj_Typ := Base_Type (Etype (Obj_Id));
4739 Desig_Typ := Obj_Typ;
4741 Set_Is_Processed_Transient (Obj_Id);
4743 -- Handle access types
4745 if Is_Access_Type (Desig_Typ) then
4746 Desig_Typ := Available_View (Designated_Type (Desig_Typ));
4747 end if;
4749 -- Create the necessary entities and declarations the first
4750 -- time around.
4752 if not Built then
4753 Built := True;
4754 Fin_Decls := New_List;
4756 Build_Object_Declarations (Fin_Data, Fin_Decls, Loc);
4757 end if;
4759 -- Transient variables associated with subprogram calls need
4760 -- extra processing. These variables are usually created right
4761 -- before the call and finalized immediately after the call.
4762 -- If an exception occurs during the call, the clean up code
4763 -- is skipped due to the sudden change in control and the
4764 -- transient is never finalized.
4766 -- To handle this case, such variables are "exported" to the
4767 -- enclosing sequence of statements where their corresponding
4768 -- "hooks" are picked up by the finalization machinery.
4770 if Must_Hook then
4772 -- Step 1: Create an access type which provides a reference
4773 -- to the transient object. Generate:
4775 -- Ann : access [all] <Desig_Typ>;
4777 Ptr_Id := Make_Temporary (Loc, 'A');
4779 Insert_Action (Stmt,
4780 Make_Full_Type_Declaration (Loc,
4781 Defining_Identifier => Ptr_Id,
4782 Type_Definition =>
4783 Make_Access_To_Object_Definition (Loc,
4784 All_Present =>
4785 Ekind (Obj_Typ) = E_General_Access_Type,
4786 Subtype_Indication =>
4787 New_Occurrence_Of (Desig_Typ, Loc))));
4789 -- Step 2: Create a temporary which acts as a hook to the
4790 -- transient object. Generate:
4792 -- Temp : Ptr_Id := null;
4794 Temp_Id := Make_Temporary (Loc, 'T');
4796 Insert_Action (Stmt,
4797 Make_Object_Declaration (Loc,
4798 Defining_Identifier => Temp_Id,
4799 Object_Definition =>
4800 New_Occurrence_Of (Ptr_Id, Loc)));
4802 -- Mark the temporary as a transient hook. This signals the
4803 -- machinery in Build_Finalizer to recognize this special
4804 -- case.
4806 Set_Status_Flag_Or_Transient_Decl (Temp_Id, Stmt);
4808 -- Step 3: Hook the transient object to the temporary
4810 if Is_Access_Type (Obj_Typ) then
4811 Expr :=
4812 Convert_To (Ptr_Id, New_Occurrence_Of (Obj_Id, Loc));
4813 else
4814 Expr :=
4815 Make_Attribute_Reference (Loc,
4816 Prefix => New_Occurrence_Of (Obj_Id, Loc),
4817 Attribute_Name => Name_Unrestricted_Access);
4818 end if;
4820 -- Generate:
4821 -- Temp := Ptr_Id (Obj_Id);
4822 -- <or>
4823 -- Temp := Obj_Id'Unrestricted_Access;
4825 -- When the transient object is initialized by an aggregate,
4826 -- the hook must capture the object after the last component
4827 -- assignment takes place. Only then is the object fully
4828 -- initialized.
4830 if Ekind (Obj_Id) = E_Variable
4831 and then Present (Last_Aggregate_Assignment (Obj_Id))
4832 then
4833 Temp_Ins := Last_Aggregate_Assignment (Obj_Id);
4835 -- Otherwise the hook seizes the related object immediately
4837 else
4838 Temp_Ins := Stmt;
4839 end if;
4841 Insert_After_And_Analyze (Temp_Ins,
4842 Make_Assignment_Statement (Loc,
4843 Name => New_Occurrence_Of (Temp_Id, Loc),
4844 Expression => Expr));
4845 end if;
4847 Stmts := New_List;
4849 -- The transient object is about to be finalized by the clean
4850 -- up code following the subprogram call. In order to avoid
4851 -- double finalization, clear the hook.
4853 -- Generate:
4854 -- Temp := null;
4856 if Must_Hook then
4857 Append_To (Stmts,
4858 Make_Assignment_Statement (Loc,
4859 Name => New_Occurrence_Of (Temp_Id, Loc),
4860 Expression => Make_Null (Loc)));
4861 end if;
4863 -- Generate:
4864 -- [Deep_]Finalize (Obj_Ref);
4866 -- Set type of dereference, so that proper conversion are
4867 -- generated when operation is inherited.
4869 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
4871 if Is_Access_Type (Obj_Typ) then
4872 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4873 Set_Etype (Obj_Ref, Directly_Designated_Type (Obj_Typ));
4874 end if;
4876 Append_To (Stmts,
4877 Make_Final_Call (Obj_Ref => Obj_Ref, Typ => Desig_Typ));
4879 -- Generate:
4880 -- [Temp := null;]
4881 -- begin
4882 -- [Deep_]Finalize (Obj_Ref);
4884 -- exception
4885 -- when others =>
4886 -- if not Raised then
4887 -- Raised := True;
4888 -- Save_Occurrence
4889 -- (Enn, Get_Current_Excep.all.all);
4890 -- end if;
4891 -- end;
4893 Fin_Block :=
4894 Make_Block_Statement (Loc,
4895 Handled_Statement_Sequence =>
4896 Make_Handled_Sequence_Of_Statements (Loc,
4897 Statements => Stmts,
4898 Exception_Handlers => New_List (
4899 Build_Exception_Handler (Fin_Data))));
4901 -- The single raise statement must be inserted after all the
4902 -- finalization blocks, and we put everything into a wrapper
4903 -- block to clearly expose the construct to the back-end.
4905 if Present (Prev_Fin) then
4906 Insert_Before_And_Analyze (Prev_Fin, Fin_Block);
4907 else
4908 Insert_After_And_Analyze (Fin_Insrt,
4909 Make_Block_Statement (Loc,
4910 Declarations => Fin_Decls,
4911 Handled_Statement_Sequence =>
4912 Make_Handled_Sequence_Of_Statements (Loc,
4913 Statements => New_List (Fin_Block))));
4915 Last_Fin := Fin_Block;
4916 end if;
4918 Prev_Fin := Fin_Block;
4919 end if;
4921 -- Terminate the scan after the last object has been processed to
4922 -- avoid touching unrelated code.
4924 if Stmt = Last_Object then
4925 exit;
4926 end if;
4928 Next (Stmt);
4929 end loop;
4931 if Clean then
4932 if Present (Prev_Fin) then
4933 Insert_List_Before_And_Analyze (Prev_Fin, Act_Cleanup);
4934 else
4935 Insert_List_After_And_Analyze (Fin_Insrt, Act_Cleanup);
4936 end if;
4937 end if;
4939 -- Generate:
4940 -- if Raised and then not Abort then
4941 -- Raise_From_Controlled_Operation (E);
4942 -- end if;
4944 if Built and then Present (Last_Fin) then
4945 Insert_After_And_Analyze (Last_Fin,
4946 Build_Raise_Statement (Fin_Data));
4947 end if;
4948 end Process_Transient_Objects;
4950 -- Local variables
4952 Loc : constant Source_Ptr := Sloc (N);
4953 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
4954 First_Obj : Node_Id;
4955 Last_Obj : Node_Id;
4956 Mark_Id : Entity_Id;
4957 Target : Node_Id;
4959 -- Start of processing for Insert_Actions_In_Scope_Around
4961 begin
4962 if No (Act_Before) and then No (Act_After) and then No (Act_Cleanup) then
4963 return;
4964 end if;
4966 -- If the node to be wrapped is the trigger of an asynchronous select,
4967 -- it is not part of a statement list. The actions must be inserted
4968 -- before the select itself, which is part of some list of statements.
4969 -- Note that the triggering alternative includes the triggering
4970 -- statement and an optional statement list. If the node to be
4971 -- wrapped is part of that list, the normal insertion applies.
4973 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4974 and then not Is_List_Member (Node_To_Wrap)
4975 then
4976 Target := Parent (Parent (Node_To_Wrap));
4977 else
4978 Target := N;
4979 end if;
4981 First_Obj := Target;
4982 Last_Obj := Target;
4984 -- Add all actions associated with a transient scope into the main tree.
4985 -- There are several scenarios here:
4987 -- +--- Before ----+ +----- After ---+
4988 -- 1) First_Obj ....... Target ........ Last_Obj
4990 -- 2) First_Obj ....... Target
4992 -- 3) Target ........ Last_Obj
4994 -- Flag declarations are inserted before the first object
4996 if Present (Act_Before) then
4997 First_Obj := First (Act_Before);
4998 Insert_List_Before (Target, Act_Before);
4999 end if;
5001 -- Finalization calls are inserted after the last object
5003 if Present (Act_After) then
5004 Last_Obj := Last (Act_After);
5005 Insert_List_After (Target, Act_After);
5006 end if;
5008 -- Mark and release the secondary stack when the context warrants it
5010 if Manage_SS then
5011 Mark_Id := Make_Temporary (Loc, 'M');
5013 -- Generate:
5014 -- Mnn : constant Mark_Id := SS_Mark;
5016 Insert_Before_And_Analyze
5017 (First_Obj, Build_SS_Mark_Call (Loc, Mark_Id));
5019 -- Generate:
5020 -- SS_Release (Mnn);
5022 Insert_After_And_Analyze
5023 (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
5024 end if;
5026 -- Check for transient controlled objects associated with Target and
5027 -- generate the appropriate finalization actions for them.
5029 Process_Transient_Objects
5030 (First_Object => First_Obj,
5031 Last_Object => Last_Obj,
5032 Related_Node => Target);
5034 -- Reset the action lists
5036 Scope_Stack.Table
5037 (Scope_Stack.Last).Actions_To_Be_Wrapped (Before) := No_List;
5038 Scope_Stack.Table
5039 (Scope_Stack.Last).Actions_To_Be_Wrapped (After) := No_List;
5041 if Clean then
5042 Scope_Stack.Table
5043 (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup) := No_List;
5044 end if;
5045 end Insert_Actions_In_Scope_Around;
5047 ------------------------------
5048 -- Is_Simple_Protected_Type --
5049 ------------------------------
5051 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
5052 begin
5053 return
5054 Is_Protected_Type (T)
5055 and then not Uses_Lock_Free (T)
5056 and then not Has_Entries (T)
5057 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
5058 end Is_Simple_Protected_Type;
5060 -----------------------
5061 -- Make_Adjust_Call --
5062 -----------------------
5064 function Make_Adjust_Call
5065 (Obj_Ref : Node_Id;
5066 Typ : Entity_Id;
5067 Skip_Self : Boolean := False) return Node_Id
5069 Loc : constant Source_Ptr := Sloc (Obj_Ref);
5070 Adj_Id : Entity_Id := Empty;
5071 Ref : Node_Id := Obj_Ref;
5072 Utyp : Entity_Id;
5074 begin
5075 -- Recover the proper type which contains Deep_Adjust
5077 if Is_Class_Wide_Type (Typ) then
5078 Utyp := Root_Type (Typ);
5079 else
5080 Utyp := Typ;
5081 end if;
5083 Utyp := Underlying_Type (Base_Type (Utyp));
5084 Set_Assignment_OK (Ref);
5086 -- Deal with untagged derivation of private views
5088 if Is_Untagged_Derivation (Typ) then
5089 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
5090 Ref := Unchecked_Convert_To (Utyp, Ref);
5091 Set_Assignment_OK (Ref);
5092 end if;
5094 -- When dealing with the completion of a private type, use the base
5095 -- type instead.
5097 if Utyp /= Base_Type (Utyp) then
5098 pragma Assert (Is_Private_Type (Typ));
5100 Utyp := Base_Type (Utyp);
5101 Ref := Unchecked_Convert_To (Utyp, Ref);
5102 end if;
5104 if Skip_Self then
5105 if Has_Controlled_Component (Utyp) then
5106 if Is_Tagged_Type (Utyp) then
5107 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
5108 else
5109 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
5110 end if;
5111 end if;
5113 -- Class-wide types, interfaces and types with controlled components
5115 elsif Is_Class_Wide_Type (Typ)
5116 or else Is_Interface (Typ)
5117 or else Has_Controlled_Component (Utyp)
5118 then
5119 if Is_Tagged_Type (Utyp) then
5120 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
5121 else
5122 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
5123 end if;
5125 -- Derivations from [Limited_]Controlled
5127 elsif Is_Controlled (Utyp) then
5128 if Has_Controlled_Component (Utyp) then
5129 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
5130 else
5131 Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
5132 end if;
5134 -- Tagged types
5136 elsif Is_Tagged_Type (Utyp) then
5137 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
5139 else
5140 raise Program_Error;
5141 end if;
5143 if Present (Adj_Id) then
5145 -- If the object is unanalyzed, set its expected type for use in
5146 -- Convert_View in case an additional conversion is needed.
5148 if No (Etype (Ref))
5149 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
5150 then
5151 Set_Etype (Ref, Typ);
5152 end if;
5154 -- The object reference may need another conversion depending on the
5155 -- type of the formal and that of the actual.
5157 if not Is_Class_Wide_Type (Typ) then
5158 Ref := Convert_View (Adj_Id, Ref);
5159 end if;
5161 return
5162 Make_Call (Loc,
5163 Proc_Id => Adj_Id,
5164 Param => New_Copy_Tree (Ref),
5165 Skip_Self => Skip_Self);
5166 else
5167 return Empty;
5168 end if;
5169 end Make_Adjust_Call;
5171 ----------------------
5172 -- Make_Attach_Call --
5173 ----------------------
5175 function Make_Attach_Call
5176 (Obj_Ref : Node_Id;
5177 Ptr_Typ : Entity_Id) return Node_Id
5179 pragma Assert (VM_Target /= No_VM);
5181 Loc : constant Source_Ptr := Sloc (Obj_Ref);
5182 begin
5183 return
5184 Make_Procedure_Call_Statement (Loc,
5185 Name =>
5186 New_Occurrence_Of (RTE (RE_Attach), Loc),
5187 Parameter_Associations => New_List (
5188 New_Occurrence_Of (Finalization_Master (Ptr_Typ), Loc),
5189 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
5190 end Make_Attach_Call;
5192 ----------------------
5193 -- Make_Detach_Call --
5194 ----------------------
5196 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
5197 Loc : constant Source_Ptr := Sloc (Obj_Ref);
5199 begin
5200 return
5201 Make_Procedure_Call_Statement (Loc,
5202 Name =>
5203 New_Occurrence_Of (RTE (RE_Detach), Loc),
5204 Parameter_Associations => New_List (
5205 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
5206 end Make_Detach_Call;
5208 ---------------
5209 -- Make_Call --
5210 ---------------
5212 function Make_Call
5213 (Loc : Source_Ptr;
5214 Proc_Id : Entity_Id;
5215 Param : Node_Id;
5216 Skip_Self : Boolean := False) return Node_Id
5218 Params : constant List_Id := New_List (Param);
5220 begin
5221 -- Do not apply the controlled action to the object itself by signaling
5222 -- the related routine to avoid self.
5224 if Skip_Self then
5225 Append_To (Params, New_Occurrence_Of (Standard_False, Loc));
5226 end if;
5228 return
5229 Make_Procedure_Call_Statement (Loc,
5230 Name => New_Occurrence_Of (Proc_Id, Loc),
5231 Parameter_Associations => Params);
5232 end Make_Call;
5234 --------------------------
5235 -- Make_Deep_Array_Body --
5236 --------------------------
5238 function Make_Deep_Array_Body
5239 (Prim : Final_Primitives;
5240 Typ : Entity_Id) return List_Id
5242 function Build_Adjust_Or_Finalize_Statements
5243 (Typ : Entity_Id) return List_Id;
5244 -- Create the statements necessary to adjust or finalize an array of
5245 -- controlled elements. Generate:
5247 -- declare
5248 -- Abort : constant Boolean := Triggered_By_Abort;
5249 -- <or>
5250 -- Abort : constant Boolean := False; -- no abort
5252 -- E : Exception_Occurrence;
5253 -- Raised : Boolean := False;
5255 -- begin
5256 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
5257 -- ^-- in the finalization case
5258 -- ...
5259 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
5260 -- begin
5261 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
5263 -- exception
5264 -- when others =>
5265 -- if not Raised then
5266 -- Raised := True;
5267 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5268 -- end if;
5269 -- end;
5270 -- end loop;
5271 -- ...
5272 -- end loop;
5274 -- if Raised and then not Abort then
5275 -- Raise_From_Controlled_Operation (E);
5276 -- end if;
5277 -- end;
5279 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
5280 -- Create the statements necessary to initialize an array of controlled
5281 -- elements. Include a mechanism to carry out partial finalization if an
5282 -- exception occurs. Generate:
5284 -- declare
5285 -- Counter : Integer := 0;
5287 -- begin
5288 -- for J1 in V'Range (1) loop
5289 -- ...
5290 -- for JN in V'Range (N) loop
5291 -- begin
5292 -- [Deep_]Initialize (V (J1, ..., JN));
5294 -- Counter := Counter + 1;
5296 -- exception
5297 -- when others =>
5298 -- declare
5299 -- Abort : constant Boolean := Triggered_By_Abort;
5300 -- <or>
5301 -- Abort : constant Boolean := False; -- no abort
5302 -- E : Exception_Occurence;
5303 -- Raised : Boolean := False;
5305 -- begin
5306 -- Counter :=
5307 -- V'Length (1) *
5308 -- V'Length (2) *
5309 -- ...
5310 -- V'Length (N) - Counter;
5312 -- for F1 in reverse V'Range (1) loop
5313 -- ...
5314 -- for FN in reverse V'Range (N) loop
5315 -- if Counter > 0 then
5316 -- Counter := Counter - 1;
5317 -- else
5318 -- begin
5319 -- [Deep_]Finalize (V (F1, ..., FN));
5321 -- exception
5322 -- when others =>
5323 -- if not Raised then
5324 -- Raised := True;
5325 -- Save_Occurrence (E,
5326 -- Get_Current_Excep.all.all);
5327 -- end if;
5328 -- end;
5329 -- end if;
5330 -- end loop;
5331 -- ...
5332 -- end loop;
5333 -- end;
5335 -- if Raised and then not Abort then
5336 -- Raise_From_Controlled_Operation (E);
5337 -- end if;
5339 -- raise;
5340 -- end;
5341 -- end loop;
5342 -- end loop;
5343 -- end;
5345 function New_References_To
5346 (L : List_Id;
5347 Loc : Source_Ptr) return List_Id;
5348 -- Given a list of defining identifiers, return a list of references to
5349 -- the original identifiers, in the same order as they appear.
5351 -----------------------------------------
5352 -- Build_Adjust_Or_Finalize_Statements --
5353 -----------------------------------------
5355 function Build_Adjust_Or_Finalize_Statements
5356 (Typ : Entity_Id) return List_Id
5358 Comp_Typ : constant Entity_Id := Component_Type (Typ);
5359 Index_List : constant List_Id := New_List;
5360 Loc : constant Source_Ptr := Sloc (Typ);
5361 Num_Dims : constant Int := Number_Dimensions (Typ);
5362 Finalizer_Decls : List_Id := No_List;
5363 Finalizer_Data : Finalization_Exception_Data;
5364 Call : Node_Id;
5365 Comp_Ref : Node_Id;
5366 Core_Loop : Node_Id;
5367 Dim : Int;
5368 J : Entity_Id;
5369 Loop_Id : Entity_Id;
5370 Stmts : List_Id;
5372 Exceptions_OK : constant Boolean :=
5373 not Restriction_Active (No_Exception_Propagation);
5375 procedure Build_Indexes;
5376 -- Generate the indexes used in the dimension loops
5378 -------------------
5379 -- Build_Indexes --
5380 -------------------
5382 procedure Build_Indexes is
5383 begin
5384 -- Generate the following identifiers:
5385 -- Jnn - for initialization
5387 for Dim in 1 .. Num_Dims loop
5388 Append_To (Index_List,
5389 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5390 end loop;
5391 end Build_Indexes;
5393 -- Start of processing for Build_Adjust_Or_Finalize_Statements
5395 begin
5396 Finalizer_Decls := New_List;
5398 Build_Indexes;
5399 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
5401 Comp_Ref :=
5402 Make_Indexed_Component (Loc,
5403 Prefix => Make_Identifier (Loc, Name_V),
5404 Expressions => New_References_To (Index_List, Loc));
5405 Set_Etype (Comp_Ref, Comp_Typ);
5407 -- Generate:
5408 -- [Deep_]Adjust (V (J1, ..., JN))
5410 if Prim = Adjust_Case then
5411 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5413 -- Generate:
5414 -- [Deep_]Finalize (V (J1, ..., JN))
5416 else pragma Assert (Prim = Finalize_Case);
5417 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5418 end if;
5420 -- Generate the block which houses the adjust or finalize call:
5422 -- <adjust or finalize call>; -- No_Exception_Propagation
5424 -- begin -- Exception handlers allowed
5425 -- <adjust or finalize call>
5427 -- exception
5428 -- when others =>
5429 -- if not Raised then
5430 -- Raised := True;
5431 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5432 -- end if;
5433 -- end;
5435 if Exceptions_OK then
5436 Core_Loop :=
5437 Make_Block_Statement (Loc,
5438 Handled_Statement_Sequence =>
5439 Make_Handled_Sequence_Of_Statements (Loc,
5440 Statements => New_List (Call),
5441 Exception_Handlers => New_List (
5442 Build_Exception_Handler (Finalizer_Data))));
5443 else
5444 Core_Loop := Call;
5445 end if;
5447 -- Generate the dimension loops starting from the innermost one
5449 -- for Jnn in [reverse] V'Range (Dim) loop
5450 -- <core loop>
5451 -- end loop;
5453 J := Last (Index_List);
5454 Dim := Num_Dims;
5455 while Present (J) and then Dim > 0 loop
5456 Loop_Id := J;
5457 Prev (J);
5458 Remove (Loop_Id);
5460 Core_Loop :=
5461 Make_Loop_Statement (Loc,
5462 Iteration_Scheme =>
5463 Make_Iteration_Scheme (Loc,
5464 Loop_Parameter_Specification =>
5465 Make_Loop_Parameter_Specification (Loc,
5466 Defining_Identifier => Loop_Id,
5467 Discrete_Subtype_Definition =>
5468 Make_Attribute_Reference (Loc,
5469 Prefix => Make_Identifier (Loc, Name_V),
5470 Attribute_Name => Name_Range,
5471 Expressions => New_List (
5472 Make_Integer_Literal (Loc, Dim))),
5474 Reverse_Present => Prim = Finalize_Case)),
5476 Statements => New_List (Core_Loop),
5477 End_Label => Empty);
5479 Dim := Dim - 1;
5480 end loop;
5482 -- Generate the block which contains the core loop, the declarations
5483 -- of the abort flag, the exception occurrence, the raised flag and
5484 -- the conditional raise:
5486 -- declare
5487 -- Abort : constant Boolean := Triggered_By_Abort;
5488 -- <or>
5489 -- Abort : constant Boolean := False; -- no abort
5491 -- E : Exception_Occurrence;
5492 -- Raised : Boolean := False;
5494 -- begin
5495 -- <core loop>
5497 -- if Raised and then not Abort then -- Expection handlers OK
5498 -- Raise_From_Controlled_Operation (E);
5499 -- end if;
5500 -- end;
5502 Stmts := New_List (Core_Loop);
5504 if Exceptions_OK then
5505 Append_To (Stmts,
5506 Build_Raise_Statement (Finalizer_Data));
5507 end if;
5509 return
5510 New_List (
5511 Make_Block_Statement (Loc,
5512 Declarations =>
5513 Finalizer_Decls,
5514 Handled_Statement_Sequence =>
5515 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5516 end Build_Adjust_Or_Finalize_Statements;
5518 ---------------------------------
5519 -- Build_Initialize_Statements --
5520 ---------------------------------
5522 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
5523 Comp_Typ : constant Entity_Id := Component_Type (Typ);
5524 Final_List : constant List_Id := New_List;
5525 Index_List : constant List_Id := New_List;
5526 Loc : constant Source_Ptr := Sloc (Typ);
5527 Num_Dims : constant Int := Number_Dimensions (Typ);
5528 Counter_Id : Entity_Id;
5529 Dim : Int;
5530 F : Node_Id;
5531 Fin_Stmt : Node_Id;
5532 Final_Block : Node_Id;
5533 Final_Loop : Node_Id;
5534 Finalizer_Data : Finalization_Exception_Data;
5535 Finalizer_Decls : List_Id := No_List;
5536 Init_Loop : Node_Id;
5537 J : Node_Id;
5538 Loop_Id : Node_Id;
5539 Stmts : List_Id;
5541 Exceptions_OK : constant Boolean :=
5542 not Restriction_Active (No_Exception_Propagation);
5544 function Build_Counter_Assignment return Node_Id;
5545 -- Generate the following assignment:
5546 -- Counter := V'Length (1) *
5547 -- ...
5548 -- V'Length (N) - Counter;
5550 function Build_Finalization_Call return Node_Id;
5551 -- Generate a deep finalization call for an array element
5553 procedure Build_Indexes;
5554 -- Generate the initialization and finalization indexes used in the
5555 -- dimension loops.
5557 function Build_Initialization_Call return Node_Id;
5558 -- Generate a deep initialization call for an array element
5560 ------------------------------
5561 -- Build_Counter_Assignment --
5562 ------------------------------
5564 function Build_Counter_Assignment return Node_Id is
5565 Dim : Int;
5566 Expr : Node_Id;
5568 begin
5569 -- Start from the first dimension and generate:
5570 -- V'Length (1)
5572 Dim := 1;
5573 Expr :=
5574 Make_Attribute_Reference (Loc,
5575 Prefix => Make_Identifier (Loc, Name_V),
5576 Attribute_Name => Name_Length,
5577 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
5579 -- Process the rest of the dimensions, generate:
5580 -- Expr * V'Length (N)
5582 Dim := Dim + 1;
5583 while Dim <= Num_Dims loop
5584 Expr :=
5585 Make_Op_Multiply (Loc,
5586 Left_Opnd => Expr,
5587 Right_Opnd =>
5588 Make_Attribute_Reference (Loc,
5589 Prefix => Make_Identifier (Loc, Name_V),
5590 Attribute_Name => Name_Length,
5591 Expressions => New_List (
5592 Make_Integer_Literal (Loc, Dim))));
5594 Dim := Dim + 1;
5595 end loop;
5597 -- Generate:
5598 -- Counter := Expr - Counter;
5600 return
5601 Make_Assignment_Statement (Loc,
5602 Name => New_Occurrence_Of (Counter_Id, Loc),
5603 Expression =>
5604 Make_Op_Subtract (Loc,
5605 Left_Opnd => Expr,
5606 Right_Opnd => New_Occurrence_Of (Counter_Id, Loc)));
5607 end Build_Counter_Assignment;
5609 -----------------------------
5610 -- Build_Finalization_Call --
5611 -----------------------------
5613 function Build_Finalization_Call return Node_Id is
5614 Comp_Ref : constant Node_Id :=
5615 Make_Indexed_Component (Loc,
5616 Prefix => Make_Identifier (Loc, Name_V),
5617 Expressions => New_References_To (Final_List, Loc));
5619 begin
5620 Set_Etype (Comp_Ref, Comp_Typ);
5622 -- Generate:
5623 -- [Deep_]Finalize (V);
5625 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5626 end Build_Finalization_Call;
5628 -------------------
5629 -- Build_Indexes --
5630 -------------------
5632 procedure Build_Indexes is
5633 begin
5634 -- Generate the following identifiers:
5635 -- Jnn - for initialization
5636 -- Fnn - for finalization
5638 for Dim in 1 .. Num_Dims loop
5639 Append_To (Index_List,
5640 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5642 Append_To (Final_List,
5643 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5644 end loop;
5645 end Build_Indexes;
5647 -------------------------------
5648 -- Build_Initialization_Call --
5649 -------------------------------
5651 function Build_Initialization_Call return Node_Id is
5652 Comp_Ref : constant Node_Id :=
5653 Make_Indexed_Component (Loc,
5654 Prefix => Make_Identifier (Loc, Name_V),
5655 Expressions => New_References_To (Index_List, Loc));
5657 begin
5658 Set_Etype (Comp_Ref, Comp_Typ);
5660 -- Generate:
5661 -- [Deep_]Initialize (V (J1, ..., JN));
5663 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5664 end Build_Initialization_Call;
5666 -- Start of processing for Build_Initialize_Statements
5668 begin
5669 Counter_Id := Make_Temporary (Loc, 'C');
5670 Finalizer_Decls := New_List;
5672 Build_Indexes;
5673 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
5675 -- Generate the block which houses the finalization call, the index
5676 -- guard and the handler which triggers Program_Error later on.
5678 -- if Counter > 0 then
5679 -- Counter := Counter - 1;
5680 -- else
5681 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5683 -- begin -- Exceptions allowed
5684 -- [Deep_]Finalize (V (F1, ..., FN));
5685 -- exception
5686 -- when others =>
5687 -- if not Raised then
5688 -- Raised := True;
5689 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5690 -- end if;
5691 -- end;
5692 -- end if;
5694 if Exceptions_OK then
5695 Fin_Stmt :=
5696 Make_Block_Statement (Loc,
5697 Handled_Statement_Sequence =>
5698 Make_Handled_Sequence_Of_Statements (Loc,
5699 Statements => New_List (Build_Finalization_Call),
5700 Exception_Handlers => New_List (
5701 Build_Exception_Handler (Finalizer_Data))));
5702 else
5703 Fin_Stmt := Build_Finalization_Call;
5704 end if;
5706 -- This is the core of the loop, the dimension iterators are added
5707 -- one by one in reverse.
5709 Final_Loop :=
5710 Make_If_Statement (Loc,
5711 Condition =>
5712 Make_Op_Gt (Loc,
5713 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
5714 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5716 Then_Statements => New_List (
5717 Make_Assignment_Statement (Loc,
5718 Name => New_Occurrence_Of (Counter_Id, Loc),
5719 Expression =>
5720 Make_Op_Subtract (Loc,
5721 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
5722 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5724 Else_Statements => New_List (Fin_Stmt));
5726 -- Generate all finalization loops starting from the innermost
5727 -- dimension.
5729 -- for Fnn in reverse V'Range (Dim) loop
5730 -- <final loop>
5731 -- end loop;
5733 F := Last (Final_List);
5734 Dim := Num_Dims;
5735 while Present (F) and then Dim > 0 loop
5736 Loop_Id := F;
5737 Prev (F);
5738 Remove (Loop_Id);
5740 Final_Loop :=
5741 Make_Loop_Statement (Loc,
5742 Iteration_Scheme =>
5743 Make_Iteration_Scheme (Loc,
5744 Loop_Parameter_Specification =>
5745 Make_Loop_Parameter_Specification (Loc,
5746 Defining_Identifier => Loop_Id,
5747 Discrete_Subtype_Definition =>
5748 Make_Attribute_Reference (Loc,
5749 Prefix => Make_Identifier (Loc, Name_V),
5750 Attribute_Name => Name_Range,
5751 Expressions => New_List (
5752 Make_Integer_Literal (Loc, Dim))),
5754 Reverse_Present => True)),
5756 Statements => New_List (Final_Loop),
5757 End_Label => Empty);
5759 Dim := Dim - 1;
5760 end loop;
5762 -- Generate the block which contains the finalization loops, the
5763 -- declarations of the abort flag, the exception occurrence, the
5764 -- raised flag and the conditional raise.
5766 -- declare
5767 -- Abort : constant Boolean := Triggered_By_Abort;
5768 -- <or>
5769 -- Abort : constant Boolean := False; -- no abort
5771 -- E : Exception_Occurrence;
5772 -- Raised : Boolean := False;
5774 -- begin
5775 -- Counter :=
5776 -- V'Length (1) *
5777 -- ...
5778 -- V'Length (N) - Counter;
5780 -- <final loop>
5782 -- if Raised and then not Abort then -- Exception handlers OK
5783 -- Raise_From_Controlled_Operation (E);
5784 -- end if;
5786 -- raise; -- Exception handlers OK
5787 -- end;
5789 Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5791 if Exceptions_OK then
5792 Append_To (Stmts,
5793 Build_Raise_Statement (Finalizer_Data));
5794 Append_To (Stmts, Make_Raise_Statement (Loc));
5795 end if;
5797 Final_Block :=
5798 Make_Block_Statement (Loc,
5799 Declarations =>
5800 Finalizer_Decls,
5801 Handled_Statement_Sequence =>
5802 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5804 -- Generate the block which contains the initialization call and
5805 -- the partial finalization code.
5807 -- begin
5808 -- [Deep_]Initialize (V (J1, ..., JN));
5810 -- Counter := Counter + 1;
5812 -- exception
5813 -- when others =>
5814 -- <finalization code>
5815 -- end;
5817 Init_Loop :=
5818 Make_Block_Statement (Loc,
5819 Handled_Statement_Sequence =>
5820 Make_Handled_Sequence_Of_Statements (Loc,
5821 Statements => New_List (Build_Initialization_Call),
5822 Exception_Handlers => New_List (
5823 Make_Exception_Handler (Loc,
5824 Exception_Choices => New_List (Make_Others_Choice (Loc)),
5825 Statements => New_List (Final_Block)))));
5827 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5828 Make_Assignment_Statement (Loc,
5829 Name => New_Occurrence_Of (Counter_Id, Loc),
5830 Expression =>
5831 Make_Op_Add (Loc,
5832 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
5833 Right_Opnd => Make_Integer_Literal (Loc, 1))));
5835 -- Generate all initialization loops starting from the innermost
5836 -- dimension.
5838 -- for Jnn in V'Range (Dim) loop
5839 -- <init loop>
5840 -- end loop;
5842 J := Last (Index_List);
5843 Dim := Num_Dims;
5844 while Present (J) and then Dim > 0 loop
5845 Loop_Id := J;
5846 Prev (J);
5847 Remove (Loop_Id);
5849 Init_Loop :=
5850 Make_Loop_Statement (Loc,
5851 Iteration_Scheme =>
5852 Make_Iteration_Scheme (Loc,
5853 Loop_Parameter_Specification =>
5854 Make_Loop_Parameter_Specification (Loc,
5855 Defining_Identifier => Loop_Id,
5856 Discrete_Subtype_Definition =>
5857 Make_Attribute_Reference (Loc,
5858 Prefix => Make_Identifier (Loc, Name_V),
5859 Attribute_Name => Name_Range,
5860 Expressions => New_List (
5861 Make_Integer_Literal (Loc, Dim))))),
5863 Statements => New_List (Init_Loop),
5864 End_Label => Empty);
5866 Dim := Dim - 1;
5867 end loop;
5869 -- Generate the block which contains the counter variable and the
5870 -- initialization loops.
5872 -- declare
5873 -- Counter : Integer := 0;
5874 -- begin
5875 -- <init loop>
5876 -- end;
5878 return
5879 New_List (
5880 Make_Block_Statement (Loc,
5881 Declarations => New_List (
5882 Make_Object_Declaration (Loc,
5883 Defining_Identifier => Counter_Id,
5884 Object_Definition =>
5885 New_Occurrence_Of (Standard_Integer, Loc),
5886 Expression => Make_Integer_Literal (Loc, 0))),
5888 Handled_Statement_Sequence =>
5889 Make_Handled_Sequence_Of_Statements (Loc,
5890 Statements => New_List (Init_Loop))));
5891 end Build_Initialize_Statements;
5893 -----------------------
5894 -- New_References_To --
5895 -----------------------
5897 function New_References_To
5898 (L : List_Id;
5899 Loc : Source_Ptr) return List_Id
5901 Refs : constant List_Id := New_List;
5902 Id : Node_Id;
5904 begin
5905 Id := First (L);
5906 while Present (Id) loop
5907 Append_To (Refs, New_Occurrence_Of (Id, Loc));
5908 Next (Id);
5909 end loop;
5911 return Refs;
5912 end New_References_To;
5914 -- Start of processing for Make_Deep_Array_Body
5916 begin
5917 case Prim is
5918 when Address_Case =>
5919 return Make_Finalize_Address_Stmts (Typ);
5921 when Adjust_Case |
5922 Finalize_Case =>
5923 return Build_Adjust_Or_Finalize_Statements (Typ);
5925 when Initialize_Case =>
5926 return Build_Initialize_Statements (Typ);
5927 end case;
5928 end Make_Deep_Array_Body;
5930 --------------------
5931 -- Make_Deep_Proc --
5932 --------------------
5934 function Make_Deep_Proc
5935 (Prim : Final_Primitives;
5936 Typ : Entity_Id;
5937 Stmts : List_Id) return Entity_Id
5939 Loc : constant Source_Ptr := Sloc (Typ);
5940 Formals : List_Id;
5941 Proc_Id : Entity_Id;
5943 begin
5944 -- Create the object formal, generate:
5945 -- V : System.Address
5947 if Prim = Address_Case then
5948 Formals := New_List (
5949 Make_Parameter_Specification (Loc,
5950 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5951 Parameter_Type =>
5952 New_Occurrence_Of (RTE (RE_Address), Loc)));
5954 -- Default case
5956 else
5957 -- V : in out Typ
5959 Formals := New_List (
5960 Make_Parameter_Specification (Loc,
5961 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5962 In_Present => True,
5963 Out_Present => True,
5964 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
5966 -- F : Boolean := True
5968 if Prim = Adjust_Case
5969 or else Prim = Finalize_Case
5970 then
5971 Append_To (Formals,
5972 Make_Parameter_Specification (Loc,
5973 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5974 Parameter_Type =>
5975 New_Occurrence_Of (Standard_Boolean, Loc),
5976 Expression =>
5977 New_Occurrence_Of (Standard_True, Loc)));
5978 end if;
5979 end if;
5981 Proc_Id :=
5982 Make_Defining_Identifier (Loc,
5983 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5985 -- Generate:
5986 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5987 -- begin
5988 -- <stmts>
5989 -- exception -- Finalize and Adjust cases only
5990 -- raise Program_Error;
5991 -- end Deep_Initialize / Adjust / Finalize;
5993 -- or
5995 -- procedure Finalize_Address (V : System.Address) is
5996 -- begin
5997 -- <stmts>
5998 -- end Finalize_Address;
6000 Discard_Node (
6001 Make_Subprogram_Body (Loc,
6002 Specification =>
6003 Make_Procedure_Specification (Loc,
6004 Defining_Unit_Name => Proc_Id,
6005 Parameter_Specifications => Formals),
6007 Declarations => Empty_List,
6009 Handled_Statement_Sequence =>
6010 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
6012 return Proc_Id;
6013 end Make_Deep_Proc;
6015 ---------------------------
6016 -- Make_Deep_Record_Body --
6017 ---------------------------
6019 function Make_Deep_Record_Body
6020 (Prim : Final_Primitives;
6021 Typ : Entity_Id;
6022 Is_Local : Boolean := False) return List_Id
6024 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
6025 -- Build the statements necessary to adjust a record type. The type may
6026 -- have discriminants and contain variant parts. Generate:
6028 -- begin
6029 -- begin
6030 -- [Deep_]Adjust (V.Comp_1);
6031 -- exception
6032 -- when Id : others =>
6033 -- if not Raised then
6034 -- Raised := True;
6035 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6036 -- end if;
6037 -- end;
6038 -- . . .
6039 -- begin
6040 -- [Deep_]Adjust (V.Comp_N);
6041 -- exception
6042 -- when Id : others =>
6043 -- if not Raised then
6044 -- Raised := True;
6045 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6046 -- end if;
6047 -- end;
6049 -- begin
6050 -- Deep_Adjust (V._parent, False); -- If applicable
6051 -- exception
6052 -- when Id : others =>
6053 -- if not Raised then
6054 -- Raised := True;
6055 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6056 -- end if;
6057 -- end;
6059 -- if F then
6060 -- begin
6061 -- Adjust (V); -- If applicable
6062 -- exception
6063 -- when others =>
6064 -- if not Raised then
6065 -- Raised := True;
6066 -- Save_Occurence (E, Get_Current_Excep.all.all);
6067 -- end if;
6068 -- end;
6069 -- end if;
6071 -- if Raised and then not Abort then
6072 -- Raise_From_Controlled_Operation (E);
6073 -- end if;
6074 -- end;
6076 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
6077 -- Build the statements necessary to finalize a record type. The type
6078 -- may have discriminants and contain variant parts. Generate:
6080 -- declare
6081 -- Abort : constant Boolean := Triggered_By_Abort;
6082 -- <or>
6083 -- Abort : constant Boolean := False; -- no abort
6084 -- E : Exception_Occurence;
6085 -- Raised : Boolean := False;
6087 -- begin
6088 -- if F then
6089 -- begin
6090 -- Finalize (V); -- If applicable
6091 -- exception
6092 -- when others =>
6093 -- if not Raised then
6094 -- Raised := True;
6095 -- Save_Occurence (E, Get_Current_Excep.all.all);
6096 -- end if;
6097 -- end;
6098 -- end if;
6100 -- case Variant_1 is
6101 -- when Value_1 =>
6102 -- case State_Counter_N => -- If Is_Local is enabled
6103 -- when N => .
6104 -- goto LN; .
6105 -- ... .
6106 -- when 1 => .
6107 -- goto L1; .
6108 -- when others => .
6109 -- goto L0; .
6110 -- end case; .
6112 -- <<LN>> -- If Is_Local is enabled
6113 -- begin
6114 -- [Deep_]Finalize (V.Comp_N);
6115 -- exception
6116 -- when others =>
6117 -- if not Raised then
6118 -- Raised := True;
6119 -- Save_Occurence (E, Get_Current_Excep.all.all);
6120 -- end if;
6121 -- end;
6122 -- . . .
6123 -- <<L1>>
6124 -- begin
6125 -- [Deep_]Finalize (V.Comp_1);
6126 -- exception
6127 -- when others =>
6128 -- if not Raised then
6129 -- Raised := True;
6130 -- Save_Occurence (E, Get_Current_Excep.all.all);
6131 -- end if;
6132 -- end;
6133 -- <<L0>>
6134 -- end case;
6136 -- case State_Counter_1 => -- If Is_Local is enabled
6137 -- when M => .
6138 -- goto LM; .
6139 -- ...
6141 -- begin
6142 -- Deep_Finalize (V._parent, False); -- If applicable
6143 -- exception
6144 -- when Id : others =>
6145 -- if not Raised then
6146 -- Raised := True;
6147 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6148 -- end if;
6149 -- end;
6151 -- if Raised and then not Abort then
6152 -- Raise_From_Controlled_Operation (E);
6153 -- end if;
6154 -- end;
6156 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
6157 -- Given a derived tagged type Typ, traverse all components, find field
6158 -- _parent and return its type.
6160 procedure Preprocess_Components
6161 (Comps : Node_Id;
6162 Num_Comps : out Int;
6163 Has_POC : out Boolean);
6164 -- Examine all components in component list Comps, count all controlled
6165 -- components and determine whether at least one of them is per-object
6166 -- constrained. Component _parent is always skipped.
6168 -----------------------------
6169 -- Build_Adjust_Statements --
6170 -----------------------------
6172 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
6173 Loc : constant Source_Ptr := Sloc (Typ);
6174 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6175 Bod_Stmts : List_Id;
6176 Finalizer_Data : Finalization_Exception_Data;
6177 Finalizer_Decls : List_Id := No_List;
6178 Rec_Def : Node_Id;
6179 Var_Case : Node_Id;
6181 Exceptions_OK : constant Boolean :=
6182 not Restriction_Active (No_Exception_Propagation);
6184 function Process_Component_List_For_Adjust
6185 (Comps : Node_Id) return List_Id;
6186 -- Build all necessary adjust statements for a single component list
6188 ---------------------------------------
6189 -- Process_Component_List_For_Adjust --
6190 ---------------------------------------
6192 function Process_Component_List_For_Adjust
6193 (Comps : Node_Id) return List_Id
6195 Stmts : constant List_Id := New_List;
6196 Decl : Node_Id;
6197 Decl_Id : Entity_Id;
6198 Decl_Typ : Entity_Id;
6199 Has_POC : Boolean;
6200 Num_Comps : Int;
6202 procedure Process_Component_For_Adjust (Decl : Node_Id);
6203 -- Process the declaration of a single controlled component
6205 ----------------------------------
6206 -- Process_Component_For_Adjust --
6207 ----------------------------------
6209 procedure Process_Component_For_Adjust (Decl : Node_Id) is
6210 Id : constant Entity_Id := Defining_Identifier (Decl);
6211 Typ : constant Entity_Id := Etype (Id);
6212 Adj_Stmt : Node_Id;
6214 begin
6215 -- Generate:
6216 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
6218 -- begin -- Exception handlers allowed
6219 -- [Deep_]Adjust (V.Id);
6220 -- exception
6221 -- when others =>
6222 -- if not Raised then
6223 -- Raised := True;
6224 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6225 -- end if;
6226 -- end;
6228 Adj_Stmt :=
6229 Make_Adjust_Call (
6230 Obj_Ref =>
6231 Make_Selected_Component (Loc,
6232 Prefix => Make_Identifier (Loc, Name_V),
6233 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6234 Typ => Typ);
6236 if Exceptions_OK then
6237 Adj_Stmt :=
6238 Make_Block_Statement (Loc,
6239 Handled_Statement_Sequence =>
6240 Make_Handled_Sequence_Of_Statements (Loc,
6241 Statements => New_List (Adj_Stmt),
6242 Exception_Handlers => New_List (
6243 Build_Exception_Handler (Finalizer_Data))));
6244 end if;
6246 Append_To (Stmts, Adj_Stmt);
6247 end Process_Component_For_Adjust;
6249 -- Start of processing for Process_Component_List_For_Adjust
6251 begin
6252 -- Perform an initial check, determine the number of controlled
6253 -- components in the current list and whether at least one of them
6254 -- is per-object constrained.
6256 Preprocess_Components (Comps, Num_Comps, Has_POC);
6258 -- The processing in this routine is done in the following order:
6259 -- 1) Regular components
6260 -- 2) Per-object constrained components
6261 -- 3) Variant parts
6263 if Num_Comps > 0 then
6265 -- Process all regular components in order of declarations
6267 Decl := First_Non_Pragma (Component_Items (Comps));
6268 while Present (Decl) loop
6269 Decl_Id := Defining_Identifier (Decl);
6270 Decl_Typ := Etype (Decl_Id);
6272 -- Skip _parent as well as per-object constrained components
6274 if Chars (Decl_Id) /= Name_uParent
6275 and then Needs_Finalization (Decl_Typ)
6276 then
6277 if Has_Access_Constraint (Decl_Id)
6278 and then No (Expression (Decl))
6279 then
6280 null;
6281 else
6282 Process_Component_For_Adjust (Decl);
6283 end if;
6284 end if;
6286 Next_Non_Pragma (Decl);
6287 end loop;
6289 -- Process all per-object constrained components in order of
6290 -- declarations.
6292 if Has_POC then
6293 Decl := First_Non_Pragma (Component_Items (Comps));
6294 while Present (Decl) loop
6295 Decl_Id := Defining_Identifier (Decl);
6296 Decl_Typ := Etype (Decl_Id);
6298 -- Skip _parent
6300 if Chars (Decl_Id) /= Name_uParent
6301 and then Needs_Finalization (Decl_Typ)
6302 and then Has_Access_Constraint (Decl_Id)
6303 and then No (Expression (Decl))
6304 then
6305 Process_Component_For_Adjust (Decl);
6306 end if;
6308 Next_Non_Pragma (Decl);
6309 end loop;
6310 end if;
6311 end if;
6313 -- Process all variants, if any
6315 Var_Case := Empty;
6316 if Present (Variant_Part (Comps)) then
6317 declare
6318 Var_Alts : constant List_Id := New_List;
6319 Var : Node_Id;
6321 begin
6322 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6323 while Present (Var) loop
6325 -- Generate:
6326 -- when <discrete choices> =>
6327 -- <adjust statements>
6329 Append_To (Var_Alts,
6330 Make_Case_Statement_Alternative (Loc,
6331 Discrete_Choices =>
6332 New_Copy_List (Discrete_Choices (Var)),
6333 Statements =>
6334 Process_Component_List_For_Adjust (
6335 Component_List (Var))));
6337 Next_Non_Pragma (Var);
6338 end loop;
6340 -- Generate:
6341 -- case V.<discriminant> is
6342 -- when <discrete choices 1> =>
6343 -- <adjust statements 1>
6344 -- ...
6345 -- when <discrete choices N> =>
6346 -- <adjust statements N>
6347 -- end case;
6349 Var_Case :=
6350 Make_Case_Statement (Loc,
6351 Expression =>
6352 Make_Selected_Component (Loc,
6353 Prefix => Make_Identifier (Loc, Name_V),
6354 Selector_Name =>
6355 Make_Identifier (Loc,
6356 Chars => Chars (Name (Variant_Part (Comps))))),
6357 Alternatives => Var_Alts);
6358 end;
6359 end if;
6361 -- Add the variant case statement to the list of statements
6363 if Present (Var_Case) then
6364 Append_To (Stmts, Var_Case);
6365 end if;
6367 -- If the component list did not have any controlled components
6368 -- nor variants, return null.
6370 if Is_Empty_List (Stmts) then
6371 Append_To (Stmts, Make_Null_Statement (Loc));
6372 end if;
6374 return Stmts;
6375 end Process_Component_List_For_Adjust;
6377 -- Start of processing for Build_Adjust_Statements
6379 begin
6380 Finalizer_Decls := New_List;
6381 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
6383 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6384 Rec_Def := Record_Extension_Part (Typ_Def);
6385 else
6386 Rec_Def := Typ_Def;
6387 end if;
6389 -- Create an adjust sequence for all record components
6391 if Present (Component_List (Rec_Def)) then
6392 Bod_Stmts :=
6393 Process_Component_List_For_Adjust (Component_List (Rec_Def));
6394 end if;
6396 -- A derived record type must adjust all inherited components. This
6397 -- action poses the following problem:
6399 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
6400 -- begin
6401 -- Adjust (Obj);
6402 -- ...
6404 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
6405 -- begin
6406 -- Deep_Adjust (Obj._parent);
6407 -- ...
6408 -- Adjust (Obj);
6409 -- ...
6411 -- Adjusting the derived type will invoke Adjust of the parent and
6412 -- then that of the derived type. This is undesirable because both
6413 -- routines may modify shared components. Only the Adjust of the
6414 -- derived type should be invoked.
6416 -- To prevent this double adjustment of shared components,
6417 -- Deep_Adjust uses a flag to control the invocation of Adjust:
6419 -- procedure Deep_Adjust
6420 -- (Obj : in out Some_Type;
6421 -- Flag : Boolean := True)
6422 -- is
6423 -- begin
6424 -- if Flag then
6425 -- Adjust (Obj);
6426 -- end if;
6427 -- ...
6429 -- When Deep_Adjust is invokes for field _parent, a value of False is
6430 -- provided for the flag:
6432 -- Deep_Adjust (Obj._parent, False);
6434 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
6435 declare
6436 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6437 Adj_Stmt : Node_Id;
6438 Call : Node_Id;
6440 begin
6441 if Needs_Finalization (Par_Typ) then
6442 Call :=
6443 Make_Adjust_Call
6444 (Obj_Ref =>
6445 Make_Selected_Component (Loc,
6446 Prefix => Make_Identifier (Loc, Name_V),
6447 Selector_Name =>
6448 Make_Identifier (Loc, Name_uParent)),
6449 Typ => Par_Typ,
6450 Skip_Self => True);
6452 -- Generate:
6453 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
6455 -- begin -- Exceptions OK
6456 -- Deep_Adjust (V._parent, False);
6457 -- exception
6458 -- when Id : others =>
6459 -- if not Raised then
6460 -- Raised := True;
6461 -- Save_Occurrence (E,
6462 -- Get_Current_Excep.all.all);
6463 -- end if;
6464 -- end;
6466 if Present (Call) then
6467 Adj_Stmt := Call;
6469 if Exceptions_OK then
6470 Adj_Stmt :=
6471 Make_Block_Statement (Loc,
6472 Handled_Statement_Sequence =>
6473 Make_Handled_Sequence_Of_Statements (Loc,
6474 Statements => New_List (Adj_Stmt),
6475 Exception_Handlers => New_List (
6476 Build_Exception_Handler (Finalizer_Data))));
6477 end if;
6479 Prepend_To (Bod_Stmts, Adj_Stmt);
6480 end if;
6481 end if;
6482 end;
6483 end if;
6485 -- Adjust the object. This action must be performed last after all
6486 -- components have been adjusted.
6488 if Is_Controlled (Typ) then
6489 declare
6490 Adj_Stmt : Node_Id;
6491 Proc : Entity_Id;
6493 begin
6494 Proc := Find_Prim_Op (Typ, Name_Adjust);
6496 -- Generate:
6497 -- if F then
6498 -- Adjust (V); -- No_Exception_Propagation
6500 -- begin -- Exception handlers allowed
6501 -- Adjust (V);
6502 -- exception
6503 -- when others =>
6504 -- if not Raised then
6505 -- Raised := True;
6506 -- Save_Occurrence (E,
6507 -- Get_Current_Excep.all.all);
6508 -- end if;
6509 -- end;
6510 -- end if;
6512 if Present (Proc) then
6513 Adj_Stmt :=
6514 Make_Procedure_Call_Statement (Loc,
6515 Name => New_Occurrence_Of (Proc, Loc),
6516 Parameter_Associations => New_List (
6517 Make_Identifier (Loc, Name_V)));
6519 if Exceptions_OK then
6520 Adj_Stmt :=
6521 Make_Block_Statement (Loc,
6522 Handled_Statement_Sequence =>
6523 Make_Handled_Sequence_Of_Statements (Loc,
6524 Statements => New_List (Adj_Stmt),
6525 Exception_Handlers => New_List (
6526 Build_Exception_Handler
6527 (Finalizer_Data))));
6528 end if;
6530 Append_To (Bod_Stmts,
6531 Make_If_Statement (Loc,
6532 Condition => Make_Identifier (Loc, Name_F),
6533 Then_Statements => New_List (Adj_Stmt)));
6534 end if;
6535 end;
6536 end if;
6538 -- At this point either all adjustment statements have been generated
6539 -- or the type is not controlled.
6541 if Is_Empty_List (Bod_Stmts) then
6542 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6544 return Bod_Stmts;
6546 -- Generate:
6547 -- declare
6548 -- Abort : constant Boolean := Triggered_By_Abort;
6549 -- <or>
6550 -- Abort : constant Boolean := False; -- no abort
6552 -- E : Exception_Occurence;
6553 -- Raised : Boolean := False;
6555 -- begin
6556 -- <adjust statements>
6558 -- if Raised and then not Abort then
6559 -- Raise_From_Controlled_Operation (E);
6560 -- end if;
6561 -- end;
6563 else
6564 if Exceptions_OK then
6565 Append_To (Bod_Stmts,
6566 Build_Raise_Statement (Finalizer_Data));
6567 end if;
6569 return
6570 New_List (
6571 Make_Block_Statement (Loc,
6572 Declarations =>
6573 Finalizer_Decls,
6574 Handled_Statement_Sequence =>
6575 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6576 end if;
6577 end Build_Adjust_Statements;
6579 -------------------------------
6580 -- Build_Finalize_Statements --
6581 -------------------------------
6583 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6584 Loc : constant Source_Ptr := Sloc (Typ);
6585 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6586 Bod_Stmts : List_Id;
6587 Counter : Int := 0;
6588 Finalizer_Data : Finalization_Exception_Data;
6589 Finalizer_Decls : List_Id := No_List;
6590 Rec_Def : Node_Id;
6591 Var_Case : Node_Id;
6593 Exceptions_OK : constant Boolean :=
6594 not Restriction_Active (No_Exception_Propagation);
6596 function Process_Component_List_For_Finalize
6597 (Comps : Node_Id) return List_Id;
6598 -- Build all necessary finalization statements for a single component
6599 -- list. The statements may include a jump circuitry if flag Is_Local
6600 -- is enabled.
6602 -----------------------------------------
6603 -- Process_Component_List_For_Finalize --
6604 -----------------------------------------
6606 function Process_Component_List_For_Finalize
6607 (Comps : Node_Id) return List_Id
6609 Alts : List_Id;
6610 Counter_Id : Entity_Id;
6611 Decl : Node_Id;
6612 Decl_Id : Entity_Id;
6613 Decl_Typ : Entity_Id;
6614 Decls : List_Id;
6615 Has_POC : Boolean;
6616 Jump_Block : Node_Id;
6617 Label : Node_Id;
6618 Label_Id : Entity_Id;
6619 Num_Comps : Int;
6620 Stmts : List_Id;
6622 procedure Process_Component_For_Finalize
6623 (Decl : Node_Id;
6624 Alts : List_Id;
6625 Decls : List_Id;
6626 Stmts : List_Id);
6627 -- Process the declaration of a single controlled component. If
6628 -- flag Is_Local is enabled, create the corresponding label and
6629 -- jump circuitry. Alts is the list of case alternatives, Decls
6630 -- is the top level declaration list where labels are declared
6631 -- and Stmts is the list of finalization actions.
6633 ------------------------------------
6634 -- Process_Component_For_Finalize --
6635 ------------------------------------
6637 procedure Process_Component_For_Finalize
6638 (Decl : Node_Id;
6639 Alts : List_Id;
6640 Decls : List_Id;
6641 Stmts : List_Id)
6643 Id : constant Entity_Id := Defining_Identifier (Decl);
6644 Typ : constant Entity_Id := Etype (Id);
6645 Fin_Stmt : Node_Id;
6647 begin
6648 if Is_Local then
6649 declare
6650 Label : Node_Id;
6651 Label_Id : Entity_Id;
6653 begin
6654 -- Generate:
6655 -- LN : label;
6657 Label_Id :=
6658 Make_Identifier (Loc,
6659 Chars => New_External_Name ('L', Num_Comps));
6660 Set_Entity (Label_Id,
6661 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6662 Label := Make_Label (Loc, Label_Id);
6664 Append_To (Decls,
6665 Make_Implicit_Label_Declaration (Loc,
6666 Defining_Identifier => Entity (Label_Id),
6667 Label_Construct => Label));
6669 -- Generate:
6670 -- when N =>
6671 -- goto LN;
6673 Append_To (Alts,
6674 Make_Case_Statement_Alternative (Loc,
6675 Discrete_Choices => New_List (
6676 Make_Integer_Literal (Loc, Num_Comps)),
6678 Statements => New_List (
6679 Make_Goto_Statement (Loc,
6680 Name =>
6681 New_Occurrence_Of (Entity (Label_Id), Loc)))));
6683 -- Generate:
6684 -- <<LN>>
6686 Append_To (Stmts, Label);
6688 -- Decrease the number of components to be processed.
6689 -- This action yields a new Label_Id in future calls.
6691 Num_Comps := Num_Comps - 1;
6692 end;
6693 end if;
6695 -- Generate:
6696 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6698 -- begin -- Exception handlers allowed
6699 -- [Deep_]Finalize (V.Id);
6700 -- exception
6701 -- when others =>
6702 -- if not Raised then
6703 -- Raised := True;
6704 -- Save_Occurrence (E,
6705 -- Get_Current_Excep.all.all);
6706 -- end if;
6707 -- end;
6709 Fin_Stmt :=
6710 Make_Final_Call
6711 (Obj_Ref =>
6712 Make_Selected_Component (Loc,
6713 Prefix => Make_Identifier (Loc, Name_V),
6714 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6715 Typ => Typ);
6717 if not Restriction_Active (No_Exception_Propagation) then
6718 Fin_Stmt :=
6719 Make_Block_Statement (Loc,
6720 Handled_Statement_Sequence =>
6721 Make_Handled_Sequence_Of_Statements (Loc,
6722 Statements => New_List (Fin_Stmt),
6723 Exception_Handlers => New_List (
6724 Build_Exception_Handler (Finalizer_Data))));
6725 end if;
6727 Append_To (Stmts, Fin_Stmt);
6728 end Process_Component_For_Finalize;
6730 -- Start of processing for Process_Component_List_For_Finalize
6732 begin
6733 -- Perform an initial check, look for controlled and per-object
6734 -- constrained components.
6736 Preprocess_Components (Comps, Num_Comps, Has_POC);
6738 -- Create a state counter to service the current component list.
6739 -- This step is performed before the variants are inspected in
6740 -- order to generate the same state counter names as those from
6741 -- Build_Initialize_Statements.
6743 if Num_Comps > 0 and then Is_Local then
6744 Counter := Counter + 1;
6746 Counter_Id :=
6747 Make_Defining_Identifier (Loc,
6748 Chars => New_External_Name ('C', Counter));
6749 end if;
6751 -- Process the component in the following order:
6752 -- 1) Variants
6753 -- 2) Per-object constrained components
6754 -- 3) Regular components
6756 -- Start with the variant parts
6758 Var_Case := Empty;
6759 if Present (Variant_Part (Comps)) then
6760 declare
6761 Var_Alts : constant List_Id := New_List;
6762 Var : Node_Id;
6764 begin
6765 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6766 while Present (Var) loop
6768 -- Generate:
6769 -- when <discrete choices> =>
6770 -- <finalize statements>
6772 Append_To (Var_Alts,
6773 Make_Case_Statement_Alternative (Loc,
6774 Discrete_Choices =>
6775 New_Copy_List (Discrete_Choices (Var)),
6776 Statements =>
6777 Process_Component_List_For_Finalize (
6778 Component_List (Var))));
6780 Next_Non_Pragma (Var);
6781 end loop;
6783 -- Generate:
6784 -- case V.<discriminant> is
6785 -- when <discrete choices 1> =>
6786 -- <finalize statements 1>
6787 -- ...
6788 -- when <discrete choices N> =>
6789 -- <finalize statements N>
6790 -- end case;
6792 Var_Case :=
6793 Make_Case_Statement (Loc,
6794 Expression =>
6795 Make_Selected_Component (Loc,
6796 Prefix => Make_Identifier (Loc, Name_V),
6797 Selector_Name =>
6798 Make_Identifier (Loc,
6799 Chars => Chars (Name (Variant_Part (Comps))))),
6800 Alternatives => Var_Alts);
6801 end;
6802 end if;
6804 -- The current component list does not have a single controlled
6805 -- component, however it may contain variants. Return the case
6806 -- statement for the variants or nothing.
6808 if Num_Comps = 0 then
6809 if Present (Var_Case) then
6810 return New_List (Var_Case);
6811 else
6812 return New_List (Make_Null_Statement (Loc));
6813 end if;
6814 end if;
6816 -- Prepare all lists
6818 Alts := New_List;
6819 Decls := New_List;
6820 Stmts := New_List;
6822 -- Process all per-object constrained components in reverse order
6824 if Has_POC then
6825 Decl := Last_Non_Pragma (Component_Items (Comps));
6826 while Present (Decl) loop
6827 Decl_Id := Defining_Identifier (Decl);
6828 Decl_Typ := Etype (Decl_Id);
6830 -- Skip _parent
6832 if Chars (Decl_Id) /= Name_uParent
6833 and then Needs_Finalization (Decl_Typ)
6834 and then Has_Access_Constraint (Decl_Id)
6835 and then No (Expression (Decl))
6836 then
6837 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6838 end if;
6840 Prev_Non_Pragma (Decl);
6841 end loop;
6842 end if;
6844 -- Process the rest of the components in reverse order
6846 Decl := Last_Non_Pragma (Component_Items (Comps));
6847 while Present (Decl) loop
6848 Decl_Id := Defining_Identifier (Decl);
6849 Decl_Typ := Etype (Decl_Id);
6851 -- Skip _parent
6853 if Chars (Decl_Id) /= Name_uParent
6854 and then Needs_Finalization (Decl_Typ)
6855 then
6856 -- Skip per-object constrained components since they were
6857 -- handled in the above step.
6859 if Has_Access_Constraint (Decl_Id)
6860 and then No (Expression (Decl))
6861 then
6862 null;
6863 else
6864 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6865 end if;
6866 end if;
6868 Prev_Non_Pragma (Decl);
6869 end loop;
6871 -- Generate:
6872 -- declare
6873 -- LN : label; -- If Is_Local is enabled
6874 -- ... .
6875 -- L0 : label; .
6877 -- begin .
6878 -- case CounterX is .
6879 -- when N => .
6880 -- goto LN; .
6881 -- ... .
6882 -- when 1 => .
6883 -- goto L1; .
6884 -- when others => .
6885 -- goto L0; .
6886 -- end case; .
6888 -- <<LN>> -- If Is_Local is enabled
6889 -- begin
6890 -- [Deep_]Finalize (V.CompY);
6891 -- exception
6892 -- when Id : others =>
6893 -- if not Raised then
6894 -- Raised := True;
6895 -- Save_Occurrence (E,
6896 -- Get_Current_Excep.all.all);
6897 -- end if;
6898 -- end;
6899 -- ...
6900 -- <<L0>> -- If Is_Local is enabled
6901 -- end;
6903 if Is_Local then
6905 -- Add the declaration of default jump location L0, its
6906 -- corresponding alternative and its place in the statements.
6908 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6909 Set_Entity (Label_Id,
6910 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6911 Label := Make_Label (Loc, Label_Id);
6913 Append_To (Decls, -- declaration
6914 Make_Implicit_Label_Declaration (Loc,
6915 Defining_Identifier => Entity (Label_Id),
6916 Label_Construct => Label));
6918 Append_To (Alts, -- alternative
6919 Make_Case_Statement_Alternative (Loc,
6920 Discrete_Choices => New_List (
6921 Make_Others_Choice (Loc)),
6923 Statements => New_List (
6924 Make_Goto_Statement (Loc,
6925 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
6927 Append_To (Stmts, Label); -- statement
6929 -- Create the jump block
6931 Prepend_To (Stmts,
6932 Make_Case_Statement (Loc,
6933 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
6934 Alternatives => Alts));
6935 end if;
6937 Jump_Block :=
6938 Make_Block_Statement (Loc,
6939 Declarations => Decls,
6940 Handled_Statement_Sequence =>
6941 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6943 if Present (Var_Case) then
6944 return New_List (Var_Case, Jump_Block);
6945 else
6946 return New_List (Jump_Block);
6947 end if;
6948 end Process_Component_List_For_Finalize;
6950 -- Start of processing for Build_Finalize_Statements
6952 begin
6953 Finalizer_Decls := New_List;
6954 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
6956 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6957 Rec_Def := Record_Extension_Part (Typ_Def);
6958 else
6959 Rec_Def := Typ_Def;
6960 end if;
6962 -- Create a finalization sequence for all record components
6964 if Present (Component_List (Rec_Def)) then
6965 Bod_Stmts :=
6966 Process_Component_List_For_Finalize (Component_List (Rec_Def));
6967 end if;
6969 -- A derived record type must finalize all inherited components. This
6970 -- action poses the following problem:
6972 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6973 -- begin
6974 -- Finalize (Obj);
6975 -- ...
6977 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6978 -- begin
6979 -- Deep_Finalize (Obj._parent);
6980 -- ...
6981 -- Finalize (Obj);
6982 -- ...
6984 -- Finalizing the derived type will invoke Finalize of the parent and
6985 -- then that of the derived type. This is undesirable because both
6986 -- routines may modify shared components. Only the Finalize of the
6987 -- derived type should be invoked.
6989 -- To prevent this double adjustment of shared components,
6990 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6992 -- procedure Deep_Finalize
6993 -- (Obj : in out Some_Type;
6994 -- Flag : Boolean := True)
6995 -- is
6996 -- begin
6997 -- if Flag then
6998 -- Finalize (Obj);
6999 -- end if;
7000 -- ...
7002 -- When Deep_Finalize is invokes for field _parent, a value of False
7003 -- is provided for the flag:
7005 -- Deep_Finalize (Obj._parent, False);
7007 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
7008 declare
7009 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
7010 Call : Node_Id;
7011 Fin_Stmt : Node_Id;
7013 begin
7014 if Needs_Finalization (Par_Typ) then
7015 Call :=
7016 Make_Final_Call
7017 (Obj_Ref =>
7018 Make_Selected_Component (Loc,
7019 Prefix => Make_Identifier (Loc, Name_V),
7020 Selector_Name =>
7021 Make_Identifier (Loc, Name_uParent)),
7022 Typ => Par_Typ,
7023 Skip_Self => True);
7025 -- Generate:
7026 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
7028 -- begin -- Exceptions OK
7029 -- Deep_Finalize (V._parent, False);
7030 -- exception
7031 -- when Id : others =>
7032 -- if not Raised then
7033 -- Raised := True;
7034 -- Save_Occurrence (E,
7035 -- Get_Current_Excep.all.all);
7036 -- end if;
7037 -- end;
7039 if Present (Call) then
7040 Fin_Stmt := Call;
7042 if Exceptions_OK then
7043 Fin_Stmt :=
7044 Make_Block_Statement (Loc,
7045 Handled_Statement_Sequence =>
7046 Make_Handled_Sequence_Of_Statements (Loc,
7047 Statements => New_List (Fin_Stmt),
7048 Exception_Handlers => New_List (
7049 Build_Exception_Handler
7050 (Finalizer_Data))));
7051 end if;
7053 Append_To (Bod_Stmts, Fin_Stmt);
7054 end if;
7055 end if;
7056 end;
7057 end if;
7059 -- Finalize the object. This action must be performed first before
7060 -- all components have been finalized.
7062 if Is_Controlled (Typ) and then not Is_Local then
7063 declare
7064 Fin_Stmt : Node_Id;
7065 Proc : Entity_Id;
7067 begin
7068 Proc := Find_Prim_Op (Typ, Name_Finalize);
7070 -- Generate:
7071 -- if F then
7072 -- Finalize (V); -- No_Exception_Propagation
7074 -- begin
7075 -- Finalize (V);
7076 -- exception
7077 -- when others =>
7078 -- if not Raised then
7079 -- Raised := True;
7080 -- Save_Occurrence (E,
7081 -- Get_Current_Excep.all.all);
7082 -- end if;
7083 -- end;
7084 -- end if;
7086 if Present (Proc) then
7087 Fin_Stmt :=
7088 Make_Procedure_Call_Statement (Loc,
7089 Name => New_Occurrence_Of (Proc, Loc),
7090 Parameter_Associations => New_List (
7091 Make_Identifier (Loc, Name_V)));
7093 if Exceptions_OK then
7094 Fin_Stmt :=
7095 Make_Block_Statement (Loc,
7096 Handled_Statement_Sequence =>
7097 Make_Handled_Sequence_Of_Statements (Loc,
7098 Statements => New_List (Fin_Stmt),
7099 Exception_Handlers => New_List (
7100 Build_Exception_Handler
7101 (Finalizer_Data))));
7102 end if;
7104 Prepend_To (Bod_Stmts,
7105 Make_If_Statement (Loc,
7106 Condition => Make_Identifier (Loc, Name_F),
7107 Then_Statements => New_List (Fin_Stmt)));
7108 end if;
7109 end;
7110 end if;
7112 -- At this point either all finalization statements have been
7113 -- generated or the type is not controlled.
7115 if No (Bod_Stmts) then
7116 return New_List (Make_Null_Statement (Loc));
7118 -- Generate:
7119 -- declare
7120 -- Abort : constant Boolean := Triggered_By_Abort;
7121 -- <or>
7122 -- Abort : constant Boolean := False; -- no abort
7124 -- E : Exception_Occurence;
7125 -- Raised : Boolean := False;
7127 -- begin
7128 -- <finalize statements>
7130 -- if Raised and then not Abort then
7131 -- Raise_From_Controlled_Operation (E);
7132 -- end if;
7133 -- end;
7135 else
7136 if Exceptions_OK then
7137 Append_To (Bod_Stmts,
7138 Build_Raise_Statement (Finalizer_Data));
7139 end if;
7141 return
7142 New_List (
7143 Make_Block_Statement (Loc,
7144 Declarations =>
7145 Finalizer_Decls,
7146 Handled_Statement_Sequence =>
7147 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
7148 end if;
7149 end Build_Finalize_Statements;
7151 -----------------------
7152 -- Parent_Field_Type --
7153 -----------------------
7155 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
7156 Field : Entity_Id;
7158 begin
7159 Field := First_Entity (Typ);
7160 while Present (Field) loop
7161 if Chars (Field) = Name_uParent then
7162 return Etype (Field);
7163 end if;
7165 Next_Entity (Field);
7166 end loop;
7168 -- A derived tagged type should always have a parent field
7170 raise Program_Error;
7171 end Parent_Field_Type;
7173 ---------------------------
7174 -- Preprocess_Components --
7175 ---------------------------
7177 procedure Preprocess_Components
7178 (Comps : Node_Id;
7179 Num_Comps : out Int;
7180 Has_POC : out Boolean)
7182 Decl : Node_Id;
7183 Id : Entity_Id;
7184 Typ : Entity_Id;
7186 begin
7187 Num_Comps := 0;
7188 Has_POC := False;
7190 Decl := First_Non_Pragma (Component_Items (Comps));
7191 while Present (Decl) loop
7192 Id := Defining_Identifier (Decl);
7193 Typ := Etype (Id);
7195 -- Skip field _parent
7197 if Chars (Id) /= Name_uParent
7198 and then Needs_Finalization (Typ)
7199 then
7200 Num_Comps := Num_Comps + 1;
7202 if Has_Access_Constraint (Id)
7203 and then No (Expression (Decl))
7204 then
7205 Has_POC := True;
7206 end if;
7207 end if;
7209 Next_Non_Pragma (Decl);
7210 end loop;
7211 end Preprocess_Components;
7213 -- Start of processing for Make_Deep_Record_Body
7215 begin
7216 case Prim is
7217 when Address_Case =>
7218 return Make_Finalize_Address_Stmts (Typ);
7220 when Adjust_Case =>
7221 return Build_Adjust_Statements (Typ);
7223 when Finalize_Case =>
7224 return Build_Finalize_Statements (Typ);
7226 when Initialize_Case =>
7227 declare
7228 Loc : constant Source_Ptr := Sloc (Typ);
7230 begin
7231 if Is_Controlled (Typ) then
7232 return New_List (
7233 Make_Procedure_Call_Statement (Loc,
7234 Name =>
7235 New_Occurrence_Of
7236 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
7237 Parameter_Associations => New_List (
7238 Make_Identifier (Loc, Name_V))));
7239 else
7240 return Empty_List;
7241 end if;
7242 end;
7243 end case;
7244 end Make_Deep_Record_Body;
7246 ----------------------
7247 -- Make_Final_Call --
7248 ----------------------
7250 function Make_Final_Call
7251 (Obj_Ref : Node_Id;
7252 Typ : Entity_Id;
7253 Skip_Self : Boolean := False) return Node_Id
7255 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7256 Atyp : Entity_Id;
7257 Fin_Id : Entity_Id := Empty;
7258 Ref : Node_Id;
7259 Utyp : Entity_Id;
7261 begin
7262 -- Recover the proper type which contains [Deep_]Finalize
7264 if Is_Class_Wide_Type (Typ) then
7265 Utyp := Root_Type (Typ);
7266 Atyp := Utyp;
7267 Ref := Obj_Ref;
7269 elsif Is_Concurrent_Type (Typ) then
7270 Utyp := Corresponding_Record_Type (Typ);
7271 Atyp := Empty;
7272 Ref := Convert_Concurrent (Obj_Ref, Typ);
7274 elsif Is_Private_Type (Typ)
7275 and then Present (Full_View (Typ))
7276 and then Is_Concurrent_Type (Full_View (Typ))
7277 then
7278 Utyp := Corresponding_Record_Type (Full_View (Typ));
7279 Atyp := Typ;
7280 Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ));
7282 else
7283 Utyp := Typ;
7284 Atyp := Typ;
7285 Ref := Obj_Ref;
7286 end if;
7288 Utyp := Underlying_Type (Base_Type (Utyp));
7289 Set_Assignment_OK (Ref);
7291 -- Deal with untagged derivation of private views. If the parent type
7292 -- is a protected type, Deep_Finalize is found on the corresponding
7293 -- record of the ancestor.
7295 if Is_Untagged_Derivation (Typ) then
7296 if Is_Protected_Type (Typ) then
7297 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7298 else
7299 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7301 if Is_Protected_Type (Utyp) then
7302 Utyp := Corresponding_Record_Type (Utyp);
7303 end if;
7304 end if;
7306 Ref := Unchecked_Convert_To (Utyp, Ref);
7307 Set_Assignment_OK (Ref);
7308 end if;
7310 -- Deal with derived private types which do not inherit primitives from
7311 -- their parents. In this case, [Deep_]Finalize can be found in the full
7312 -- view of the parent type.
7314 if Is_Tagged_Type (Utyp)
7315 and then Is_Derived_Type (Utyp)
7316 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
7317 and then Is_Private_Type (Etype (Utyp))
7318 and then Present (Full_View (Etype (Utyp)))
7319 then
7320 Utyp := Full_View (Etype (Utyp));
7321 Ref := Unchecked_Convert_To (Utyp, Ref);
7322 Set_Assignment_OK (Ref);
7323 end if;
7325 -- When dealing with the completion of a private type, use the base type
7326 -- instead.
7328 if Utyp /= Base_Type (Utyp) then
7329 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
7331 Utyp := Base_Type (Utyp);
7332 Ref := Unchecked_Convert_To (Utyp, Ref);
7333 Set_Assignment_OK (Ref);
7334 end if;
7336 if Skip_Self then
7337 if Has_Controlled_Component (Utyp) then
7338 if Is_Tagged_Type (Utyp) then
7339 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
7340 else
7341 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
7342 end if;
7343 end if;
7345 -- Class-wide types, interfaces and types with controlled components
7347 elsif Is_Class_Wide_Type (Typ)
7348 or else Is_Interface (Typ)
7349 or else Has_Controlled_Component (Utyp)
7350 then
7351 if Is_Tagged_Type (Utyp) then
7352 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
7353 else
7354 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
7355 end if;
7357 -- Derivations from [Limited_]Controlled
7359 elsif Is_Controlled (Utyp) then
7360 if Has_Controlled_Component (Utyp) then
7361 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
7362 else
7363 Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
7364 end if;
7366 -- Tagged types
7368 elsif Is_Tagged_Type (Utyp) then
7369 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
7371 else
7372 raise Program_Error;
7373 end if;
7375 if Present (Fin_Id) then
7377 -- When finalizing a class-wide object, do not convert to the root
7378 -- type in order to produce a dispatching call.
7380 if Is_Class_Wide_Type (Typ) then
7381 null;
7383 -- Ensure that a finalization routine is at least decorated in order
7384 -- to inspect the object parameter.
7386 elsif Analyzed (Fin_Id)
7387 or else Ekind (Fin_Id) = E_Procedure
7388 then
7389 -- In certain cases, such as the creation of Stream_Read, the
7390 -- visible entity of the type is its full view. Since Stream_Read
7391 -- will have to create an object of type Typ, the local object
7392 -- will be finalzed by the scope finalizer generated later on. The
7393 -- object parameter of Deep_Finalize will always use the private
7394 -- view of the type. To avoid such a clash between a private and a
7395 -- full view, perform an unchecked conversion of the object
7396 -- reference to the private view.
7398 declare
7399 Formal_Typ : constant Entity_Id :=
7400 Etype (First_Formal (Fin_Id));
7401 begin
7402 if Is_Private_Type (Formal_Typ)
7403 and then Present (Full_View (Formal_Typ))
7404 and then Full_View (Formal_Typ) = Utyp
7405 then
7406 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
7407 end if;
7408 end;
7410 Ref := Convert_View (Fin_Id, Ref);
7411 end if;
7413 return
7414 Make_Call (Loc,
7415 Proc_Id => Fin_Id,
7416 Param => New_Copy_Tree (Ref),
7417 Skip_Self => Skip_Self);
7418 else
7419 return Empty;
7420 end if;
7421 end Make_Final_Call;
7423 --------------------------------
7424 -- Make_Finalize_Address_Body --
7425 --------------------------------
7427 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
7428 Is_Task : constant Boolean :=
7429 Ekind (Typ) = E_Record_Type
7430 and then Is_Concurrent_Record_Type (Typ)
7431 and then Ekind (Corresponding_Concurrent_Type (Typ)) =
7432 E_Task_Type;
7433 Loc : constant Source_Ptr := Sloc (Typ);
7434 Proc_Id : Entity_Id;
7435 Stmts : List_Id;
7437 begin
7438 -- The corresponding records of task types are not controlled by design.
7439 -- For the sake of completeness, create an empty Finalize_Address to be
7440 -- used in task class-wide allocations.
7442 if Is_Task then
7443 null;
7445 -- Nothing to do if the type is not controlled or it already has a
7446 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
7447 -- come from source. These are usually generated for completeness and
7448 -- do not need the Finalize_Address primitive.
7450 elsif not Needs_Finalization (Typ)
7451 or else Present (TSS (Typ, TSS_Finalize_Address))
7452 or else
7453 (Is_Class_Wide_Type (Typ)
7454 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
7455 and then not Comes_From_Source (Root_Type (Typ)))
7456 then
7457 return;
7458 end if;
7460 Proc_Id :=
7461 Make_Defining_Identifier (Loc,
7462 Make_TSS_Name (Typ, TSS_Finalize_Address));
7464 -- Generate:
7466 -- procedure <Typ>FD (V : System.Address) is
7467 -- begin
7468 -- null; -- for tasks
7470 -- declare -- for all other types
7471 -- type Pnn is access all Typ;
7472 -- for Pnn'Storage_Size use 0;
7473 -- begin
7474 -- [Deep_]Finalize (Pnn (V).all);
7475 -- end;
7476 -- end TypFD;
7478 if Is_Task then
7479 Stmts := New_List (Make_Null_Statement (Loc));
7480 else
7481 Stmts := Make_Finalize_Address_Stmts (Typ);
7482 end if;
7484 Discard_Node (
7485 Make_Subprogram_Body (Loc,
7486 Specification =>
7487 Make_Procedure_Specification (Loc,
7488 Defining_Unit_Name => Proc_Id,
7490 Parameter_Specifications => New_List (
7491 Make_Parameter_Specification (Loc,
7492 Defining_Identifier =>
7493 Make_Defining_Identifier (Loc, Name_V),
7494 Parameter_Type =>
7495 New_Occurrence_Of (RTE (RE_Address), Loc)))),
7497 Declarations => No_List,
7499 Handled_Statement_Sequence =>
7500 Make_Handled_Sequence_Of_Statements (Loc,
7501 Statements => Stmts)));
7503 Set_TSS (Typ, Proc_Id);
7504 end Make_Finalize_Address_Body;
7506 ---------------------------------
7507 -- Make_Finalize_Address_Stmts --
7508 ---------------------------------
7510 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
7511 Loc : constant Source_Ptr := Sloc (Typ);
7512 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
7513 Decls : List_Id;
7514 Desg_Typ : Entity_Id;
7515 Obj_Expr : Node_Id;
7517 begin
7518 if Is_Array_Type (Typ) then
7519 if Is_Constrained (First_Subtype (Typ)) then
7520 Desg_Typ := First_Subtype (Typ);
7521 else
7522 Desg_Typ := Base_Type (Typ);
7523 end if;
7525 -- Class-wide types of constrained root types
7527 elsif Is_Class_Wide_Type (Typ)
7528 and then Has_Discriminants (Root_Type (Typ))
7529 and then not
7530 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7531 then
7532 declare
7533 Parent_Typ : Entity_Id;
7535 begin
7536 -- Climb the parent type chain looking for a non-constrained type
7538 Parent_Typ := Root_Type (Typ);
7539 while Parent_Typ /= Etype (Parent_Typ)
7540 and then Has_Discriminants (Parent_Typ)
7541 and then not
7542 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7543 loop
7544 Parent_Typ := Etype (Parent_Typ);
7545 end loop;
7547 -- Handle views created for tagged types with unknown
7548 -- discriminants.
7550 if Is_Underlying_Record_View (Parent_Typ) then
7551 Parent_Typ := Underlying_Record_View (Parent_Typ);
7552 end if;
7554 Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
7555 end;
7557 -- General case
7559 else
7560 Desg_Typ := Typ;
7561 end if;
7563 -- Generate:
7564 -- type Ptr_Typ is access all Typ;
7565 -- for Ptr_Typ'Storage_Size use 0;
7567 Decls := New_List (
7568 Make_Full_Type_Declaration (Loc,
7569 Defining_Identifier => Ptr_Typ,
7570 Type_Definition =>
7571 Make_Access_To_Object_Definition (Loc,
7572 All_Present => True,
7573 Subtype_Indication => New_Occurrence_Of (Desg_Typ, Loc))),
7575 Make_Attribute_Definition_Clause (Loc,
7576 Name => New_Occurrence_Of (Ptr_Typ, Loc),
7577 Chars => Name_Storage_Size,
7578 Expression => Make_Integer_Literal (Loc, 0)));
7580 Obj_Expr := Make_Identifier (Loc, Name_V);
7582 -- Unconstrained arrays require special processing in order to retrieve
7583 -- the elements. To achieve this, we have to skip the dope vector which
7584 -- lays in front of the elements and then use a thin pointer to perform
7585 -- the address-to-access conversion.
7587 if Is_Array_Type (Typ)
7588 and then not Is_Constrained (First_Subtype (Typ))
7589 then
7590 declare
7591 Dope_Id : Entity_Id;
7593 begin
7594 -- Ensure that Ptr_Typ a thin pointer, generate:
7595 -- for Ptr_Typ'Size use System.Address'Size;
7597 Append_To (Decls,
7598 Make_Attribute_Definition_Clause (Loc,
7599 Name => New_Occurrence_Of (Ptr_Typ, Loc),
7600 Chars => Name_Size,
7601 Expression =>
7602 Make_Integer_Literal (Loc, System_Address_Size)));
7604 -- Generate:
7605 -- Dnn : constant Storage_Offset :=
7606 -- Desg_Typ'Descriptor_Size / Storage_Unit;
7608 Dope_Id := Make_Temporary (Loc, 'D');
7610 Append_To (Decls,
7611 Make_Object_Declaration (Loc,
7612 Defining_Identifier => Dope_Id,
7613 Constant_Present => True,
7614 Object_Definition =>
7615 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc),
7616 Expression =>
7617 Make_Op_Divide (Loc,
7618 Left_Opnd =>
7619 Make_Attribute_Reference (Loc,
7620 Prefix => New_Occurrence_Of (Desg_Typ, Loc),
7621 Attribute_Name => Name_Descriptor_Size),
7622 Right_Opnd =>
7623 Make_Integer_Literal (Loc, System_Storage_Unit))));
7625 -- Shift the address from the start of the dope vector to the
7626 -- start of the elements:
7628 -- V + Dnn
7630 -- Note that this is done through a wrapper routine since RTSfind
7631 -- cannot retrieve operations with string names of the form "+".
7633 Obj_Expr :=
7634 Make_Function_Call (Loc,
7635 Name =>
7636 New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
7637 Parameter_Associations => New_List (
7638 Obj_Expr,
7639 New_Occurrence_Of (Dope_Id, Loc)));
7640 end;
7641 end if;
7643 -- Create the block and the finalization call
7645 return New_List (
7646 Make_Block_Statement (Loc,
7647 Declarations => Decls,
7649 Handled_Statement_Sequence =>
7650 Make_Handled_Sequence_Of_Statements (Loc,
7651 Statements => New_List (
7652 Make_Final_Call (
7653 Obj_Ref =>
7654 Make_Explicit_Dereference (Loc,
7655 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7656 Typ => Desg_Typ)))));
7657 end Make_Finalize_Address_Stmts;
7659 -------------------------------------
7660 -- Make_Handler_For_Ctrl_Operation --
7661 -------------------------------------
7663 -- Generate:
7665 -- when E : others =>
7666 -- Raise_From_Controlled_Operation (E);
7668 -- or:
7670 -- when others =>
7671 -- raise Program_Error [finalize raised exception];
7673 -- depending on whether Raise_From_Controlled_Operation is available
7675 function Make_Handler_For_Ctrl_Operation
7676 (Loc : Source_Ptr) return Node_Id
7678 E_Occ : Entity_Id;
7679 -- Choice parameter (for the first case above)
7681 Raise_Node : Node_Id;
7682 -- Procedure call or raise statement
7684 begin
7685 -- Standard run-time, .NET/JVM targets: add choice parameter E and pass
7686 -- it to Raise_From_Controlled_Operation so that the original exception
7687 -- name and message can be recorded in the exception message for
7688 -- Program_Error.
7690 if RTE_Available (RE_Raise_From_Controlled_Operation) then
7691 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7692 Raise_Node :=
7693 Make_Procedure_Call_Statement (Loc,
7694 Name =>
7695 New_Occurrence_Of
7696 (RTE (RE_Raise_From_Controlled_Operation), Loc),
7697 Parameter_Associations => New_List (
7698 New_Occurrence_Of (E_Occ, Loc)));
7700 -- Restricted run-time: exception messages are not supported
7702 else
7703 E_Occ := Empty;
7704 Raise_Node :=
7705 Make_Raise_Program_Error (Loc,
7706 Reason => PE_Finalize_Raised_Exception);
7707 end if;
7709 return
7710 Make_Implicit_Exception_Handler (Loc,
7711 Exception_Choices => New_List (Make_Others_Choice (Loc)),
7712 Choice_Parameter => E_Occ,
7713 Statements => New_List (Raise_Node));
7714 end Make_Handler_For_Ctrl_Operation;
7716 --------------------
7717 -- Make_Init_Call --
7718 --------------------
7720 function Make_Init_Call
7721 (Obj_Ref : Node_Id;
7722 Typ : Entity_Id) return Node_Id
7724 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7725 Is_Conc : Boolean;
7726 Proc : Entity_Id;
7727 Ref : Node_Id;
7728 Utyp : Entity_Id;
7730 begin
7731 -- Deal with the type and object reference. Depending on the context, an
7732 -- object reference may need several conversions.
7734 if Is_Concurrent_Type (Typ) then
7735 Is_Conc := True;
7736 Utyp := Corresponding_Record_Type (Typ);
7737 Ref := Convert_Concurrent (Obj_Ref, Typ);
7739 elsif Is_Private_Type (Typ)
7740 and then Present (Full_View (Typ))
7741 and then Is_Concurrent_Type (Underlying_Type (Typ))
7742 then
7743 Is_Conc := True;
7744 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7745 Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7747 else
7748 Is_Conc := False;
7749 Utyp := Typ;
7750 Ref := Obj_Ref;
7751 end if;
7753 Set_Assignment_OK (Ref);
7755 Utyp := Underlying_Type (Base_Type (Utyp));
7757 -- Deal with untagged derivation of private views
7759 if Is_Untagged_Derivation (Typ) and then not Is_Conc then
7760 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7761 Ref := Unchecked_Convert_To (Utyp, Ref);
7763 -- The following is to prevent problems with UC see 1.156 RH ???
7765 Set_Assignment_OK (Ref);
7766 end if;
7768 -- If the underlying_type is a subtype, then we are dealing with the
7769 -- completion of a private type. We need to access the base type and
7770 -- generate a conversion to it.
7772 if Utyp /= Base_Type (Utyp) then
7773 pragma Assert (Is_Private_Type (Typ));
7774 Utyp := Base_Type (Utyp);
7775 Ref := Unchecked_Convert_To (Utyp, Ref);
7776 end if;
7778 -- Select the appropriate version of initialize
7780 if Has_Controlled_Component (Utyp) then
7781 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7782 else
7783 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7784 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7785 end if;
7787 -- The object reference may need another conversion depending on the
7788 -- type of the formal and that of the actual.
7790 Ref := Convert_View (Proc, Ref);
7792 -- Generate:
7793 -- [Deep_]Initialize (Ref);
7795 return
7796 Make_Procedure_Call_Statement (Loc,
7797 Name =>
7798 New_Occurrence_Of (Proc, Loc),
7799 Parameter_Associations => New_List (Ref));
7800 end Make_Init_Call;
7802 ------------------------------
7803 -- Make_Local_Deep_Finalize --
7804 ------------------------------
7806 function Make_Local_Deep_Finalize
7807 (Typ : Entity_Id;
7808 Nam : Entity_Id) return Node_Id
7810 Loc : constant Source_Ptr := Sloc (Typ);
7811 Formals : List_Id;
7813 begin
7814 Formals := New_List (
7816 -- V : in out Typ
7818 Make_Parameter_Specification (Loc,
7819 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7820 In_Present => True,
7821 Out_Present => True,
7822 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
7824 -- F : Boolean := True
7826 Make_Parameter_Specification (Loc,
7827 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7828 Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc),
7829 Expression => New_Occurrence_Of (Standard_True, Loc)));
7831 -- Add the necessary number of counters to represent the initialization
7832 -- state of an object.
7834 return
7835 Make_Subprogram_Body (Loc,
7836 Specification =>
7837 Make_Procedure_Specification (Loc,
7838 Defining_Unit_Name => Nam,
7839 Parameter_Specifications => Formals),
7841 Declarations => No_List,
7843 Handled_Statement_Sequence =>
7844 Make_Handled_Sequence_Of_Statements (Loc,
7845 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7846 end Make_Local_Deep_Finalize;
7848 ------------------------------------
7849 -- Make_Set_Finalize_Address_Call --
7850 ------------------------------------
7852 function Make_Set_Finalize_Address_Call
7853 (Loc : Source_Ptr;
7854 Ptr_Typ : Entity_Id) return Node_Id
7856 -- It is possible for Ptr_Typ to be a partial view, if the access type
7857 -- is a full view declared in the private part of a nested package, and
7858 -- the finalization actions take place when completing analysis of the
7859 -- enclosing unit. For this reason use Underlying_Type twice below.
7861 Desig_Typ : constant Entity_Id :=
7862 Available_View
7863 (Designated_Type (Underlying_Type (Ptr_Typ)));
7864 Fin_Addr : constant Entity_Id := Finalize_Address (Desig_Typ);
7865 Fin_Mas : constant Entity_Id :=
7866 Finalization_Master (Underlying_Type (Ptr_Typ));
7868 begin
7869 -- Both the finalization master and primitive Finalize_Address must be
7870 -- available.
7872 pragma Assert (Present (Fin_Addr) and Present (Fin_Mas));
7874 -- Generate:
7875 -- Set_Finalize_Address
7876 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
7878 return
7879 Make_Procedure_Call_Statement (Loc,
7880 Name =>
7881 New_Occurrence_Of (RTE (RE_Set_Finalize_Address), Loc),
7882 Parameter_Associations => New_List (
7883 New_Occurrence_Of (Fin_Mas, Loc),
7885 Make_Attribute_Reference (Loc,
7886 Prefix => New_Occurrence_Of (Fin_Addr, Loc),
7887 Attribute_Name => Name_Unrestricted_Access)));
7888 end Make_Set_Finalize_Address_Call;
7890 --------------------------
7891 -- Make_Transient_Block --
7892 --------------------------
7894 function Make_Transient_Block
7895 (Loc : Source_Ptr;
7896 Action : Node_Id;
7897 Par : Node_Id) return Node_Id
7899 Decls : constant List_Id := New_List;
7900 Instrs : constant List_Id := New_List (Action);
7901 Block : Node_Id;
7902 Insert : Node_Id;
7904 begin
7905 -- Case where only secondary stack use is involved
7907 if VM_Target = No_VM
7908 and then Uses_Sec_Stack (Current_Scope)
7909 and then Nkind (Action) /= N_Simple_Return_Statement
7910 and then Nkind (Par) /= N_Exception_Handler
7911 then
7912 declare
7913 S : Entity_Id;
7915 begin
7916 S := Scope (Current_Scope);
7917 loop
7918 -- At the outer level, no need to release the sec stack
7920 if S = Standard_Standard then
7921 Set_Uses_Sec_Stack (Current_Scope, False);
7922 exit;
7924 -- In a function, only release the sec stack if the function
7925 -- does not return on the sec stack otherwise the result may
7926 -- be lost. The caller is responsible for releasing.
7928 elsif Ekind (S) = E_Function then
7929 Set_Uses_Sec_Stack (Current_Scope, False);
7931 if not Requires_Transient_Scope (Etype (S)) then
7932 Set_Uses_Sec_Stack (S, True);
7933 Check_Restriction (No_Secondary_Stack, Action);
7934 end if;
7936 exit;
7938 -- In a loop or entry we should install a block encompassing
7939 -- all the construct. For now just release right away.
7941 elsif Ekind_In (S, E_Entry, E_Loop) then
7942 exit;
7944 -- In a procedure or a block, we release on exit of the
7945 -- procedure or block. ??? memory leak can be created by
7946 -- recursive calls.
7948 elsif Ekind_In (S, E_Block, E_Procedure) then
7949 Set_Uses_Sec_Stack (S, True);
7950 Check_Restriction (No_Secondary_Stack, Action);
7951 Set_Uses_Sec_Stack (Current_Scope, False);
7952 exit;
7954 else
7955 S := Scope (S);
7956 end if;
7957 end loop;
7958 end;
7959 end if;
7961 -- Create the transient block. Set the parent now since the block itself
7962 -- is not part of the tree. The current scope is the E_Block entity
7963 -- that has been pushed by Establish_Transient_Scope.
7965 pragma Assert (Ekind (Current_Scope) = E_Block);
7966 Block :=
7967 Make_Block_Statement (Loc,
7968 Identifier => New_Occurrence_Of (Current_Scope, Loc),
7969 Declarations => Decls,
7970 Handled_Statement_Sequence =>
7971 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7972 Has_Created_Identifier => True);
7973 Set_Parent (Block, Par);
7975 -- Insert actions stuck in the transient scopes as well as all freezing
7976 -- nodes needed by those actions. Do not insert cleanup actions here,
7977 -- they will be transferred to the newly created block.
7979 Insert_Actions_In_Scope_Around
7980 (Action, Clean => False, Manage_SS => False);
7982 Insert := Prev (Action);
7983 if Present (Insert) then
7984 Freeze_All (First_Entity (Current_Scope), Insert);
7985 end if;
7987 -- Transfer cleanup actions to the newly created block
7989 declare
7990 Cleanup_Actions : List_Id
7991 renames Scope_Stack.Table (Scope_Stack.Last).
7992 Actions_To_Be_Wrapped (Cleanup);
7993 begin
7994 Set_Cleanup_Actions (Block, Cleanup_Actions);
7995 Cleanup_Actions := No_List;
7996 end;
7998 -- When the transient scope was established, we pushed the entry for the
7999 -- transient scope onto the scope stack, so that the scope was active
8000 -- for the installation of finalizable entities etc. Now we must remove
8001 -- this entry, since we have constructed a proper block.
8003 Pop_Scope;
8005 return Block;
8006 end Make_Transient_Block;
8008 ------------------------
8009 -- Node_To_Be_Wrapped --
8010 ------------------------
8012 function Node_To_Be_Wrapped return Node_Id is
8013 begin
8014 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
8015 end Node_To_Be_Wrapped;
8017 ----------------------------
8018 -- Set_Node_To_Be_Wrapped --
8019 ----------------------------
8021 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
8022 begin
8023 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
8024 end Set_Node_To_Be_Wrapped;
8026 ----------------------------
8027 -- Store_Actions_In_Scope --
8028 ----------------------------
8030 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id) is
8031 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
8032 Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK);
8034 begin
8035 if No (Actions) then
8036 Actions := L;
8038 if Is_List_Member (SE.Node_To_Be_Wrapped) then
8039 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
8040 else
8041 Set_Parent (L, SE.Node_To_Be_Wrapped);
8042 end if;
8044 Analyze_List (L);
8046 elsif AK = Before then
8047 Insert_List_After_And_Analyze (Last (Actions), L);
8049 else
8050 Insert_List_Before_And_Analyze (First (Actions), L);
8051 end if;
8052 end Store_Actions_In_Scope;
8054 ----------------------------------
8055 -- Store_After_Actions_In_Scope --
8056 ----------------------------------
8058 procedure Store_After_Actions_In_Scope (L : List_Id) is
8059 begin
8060 Store_Actions_In_Scope (After, L);
8061 end Store_After_Actions_In_Scope;
8063 -----------------------------------
8064 -- Store_Before_Actions_In_Scope --
8065 -----------------------------------
8067 procedure Store_Before_Actions_In_Scope (L : List_Id) is
8068 begin
8069 Store_Actions_In_Scope (Before, L);
8070 end Store_Before_Actions_In_Scope;
8072 -----------------------------------
8073 -- Store_Cleanup_Actions_In_Scope --
8074 -----------------------------------
8076 procedure Store_Cleanup_Actions_In_Scope (L : List_Id) is
8077 begin
8078 Store_Actions_In_Scope (Cleanup, L);
8079 end Store_Cleanup_Actions_In_Scope;
8081 --------------------------------
8082 -- Wrap_Transient_Declaration --
8083 --------------------------------
8085 -- If a transient scope has been established during the processing of the
8086 -- Expression of an Object_Declaration, it is not possible to wrap the
8087 -- declaration into a transient block as usual case, otherwise the object
8088 -- would be itself declared in the wrong scope. Therefore, all entities (if
8089 -- any) defined in the transient block are moved to the proper enclosing
8090 -- scope. Furthermore, if they are controlled variables they are finalized
8091 -- right after the declaration. The finalization list of the transient
8092 -- scope is defined as a renaming of the enclosing one so during their
8093 -- initialization they will be attached to the proper finalization list.
8094 -- For instance, the following declaration :
8096 -- X : Typ := F (G (A), G (B));
8098 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
8099 -- is expanded into :
8101 -- X : Typ := [ complex Expression-Action ];
8102 -- [Deep_]Finalize (_v1);
8103 -- [Deep_]Finalize (_v2);
8105 procedure Wrap_Transient_Declaration (N : Node_Id) is
8106 Curr_S : Entity_Id;
8107 Encl_S : Entity_Id;
8109 begin
8110 Curr_S := Current_Scope;
8111 Encl_S := Scope (Curr_S);
8113 -- Insert all actions inluding cleanup generated while analyzing or
8114 -- expanding the transient context back into the tree. Manage the
8115 -- secondary stack when the object declaration appears in a library
8116 -- level package [body]. This is not needed for .NET/JVM as those do
8117 -- not support the secondary stack.
8119 Insert_Actions_In_Scope_Around
8120 (N => N,
8121 Clean => True,
8122 Manage_SS =>
8123 VM_Target = No_VM
8124 and then Uses_Sec_Stack (Curr_S)
8125 and then Nkind (N) = N_Object_Declaration
8126 and then Ekind_In (Encl_S, E_Package, E_Package_Body)
8127 and then Is_Library_Level_Entity (Encl_S));
8128 Pop_Scope;
8130 -- Relocate local entities declared within the transient scope to the
8131 -- enclosing scope. This action sets their Is_Public flag accordingly.
8133 Transfer_Entities (Curr_S, Encl_S);
8135 -- Mark the enclosing dynamic scope to ensure that the secondary stack
8136 -- is properly released upon exiting the said scope. This is not needed
8137 -- for .NET/JVM as those do not support the secondary stack.
8139 if VM_Target = No_VM and then Uses_Sec_Stack (Curr_S) then
8140 Curr_S := Enclosing_Dynamic_Scope (Curr_S);
8142 -- Do not mark a function that returns on the secondary stack as the
8143 -- reclamation is done by the caller.
8145 if Ekind (Curr_S) = E_Function
8146 and then Requires_Transient_Scope (Etype (Curr_S))
8147 then
8148 null;
8150 -- Otherwise mark the enclosing dynamic scope
8152 else
8153 Set_Uses_Sec_Stack (Curr_S);
8154 Check_Restriction (No_Secondary_Stack, N);
8155 end if;
8156 end if;
8157 end Wrap_Transient_Declaration;
8159 -------------------------------
8160 -- Wrap_Transient_Expression --
8161 -------------------------------
8163 procedure Wrap_Transient_Expression (N : Node_Id) is
8164 Loc : constant Source_Ptr := Sloc (N);
8165 Expr : Node_Id := Relocate_Node (N);
8166 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
8167 Typ : constant Entity_Id := Etype (N);
8169 begin
8170 -- Generate:
8172 -- Temp : Typ;
8173 -- declare
8174 -- M : constant Mark_Id := SS_Mark;
8175 -- procedure Finalizer is ... (See Build_Finalizer)
8177 -- begin
8178 -- Temp := <Expr>; -- general case
8179 -- Temp := (if <Expr> then True else False); -- boolean case
8181 -- at end
8182 -- Finalizer;
8183 -- end;
8185 -- A special case is made for Boolean expressions so that the back-end
8186 -- knows to generate a conditional branch instruction, if running with
8187 -- -fpreserve-control-flow. This ensures that a control flow change
8188 -- signalling the decision outcome occurs before the cleanup actions.
8190 if Opt.Suppress_Control_Flow_Optimizations
8191 and then Is_Boolean_Type (Typ)
8192 then
8193 Expr :=
8194 Make_If_Expression (Loc,
8195 Expressions => New_List (
8196 Expr,
8197 New_Occurrence_Of (Standard_True, Loc),
8198 New_Occurrence_Of (Standard_False, Loc)));
8199 end if;
8201 Insert_Actions (N, New_List (
8202 Make_Object_Declaration (Loc,
8203 Defining_Identifier => Temp,
8204 Object_Definition => New_Occurrence_Of (Typ, Loc)),
8206 Make_Transient_Block (Loc,
8207 Action =>
8208 Make_Assignment_Statement (Loc,
8209 Name => New_Occurrence_Of (Temp, Loc),
8210 Expression => Expr),
8211 Par => Parent (N))));
8213 Rewrite (N, New_Occurrence_Of (Temp, Loc));
8214 Analyze_And_Resolve (N, Typ);
8215 end Wrap_Transient_Expression;
8217 ------------------------------
8218 -- Wrap_Transient_Statement --
8219 ------------------------------
8221 procedure Wrap_Transient_Statement (N : Node_Id) is
8222 Loc : constant Source_Ptr := Sloc (N);
8223 New_Stmt : constant Node_Id := Relocate_Node (N);
8225 begin
8226 -- Generate:
8227 -- declare
8228 -- M : constant Mark_Id := SS_Mark;
8229 -- procedure Finalizer is ... (See Build_Finalizer)
8231 -- begin
8232 -- <New_Stmt>;
8234 -- at end
8235 -- Finalizer;
8236 -- end;
8238 Rewrite (N,
8239 Make_Transient_Block (Loc,
8240 Action => New_Stmt,
8241 Par => Parent (N)));
8243 -- With the scope stack back to normal, we can call analyze on the
8244 -- resulting block. At this point, the transient scope is being
8245 -- treated like a perfectly normal scope, so there is nothing
8246 -- special about it.
8248 -- Note: Wrap_Transient_Statement is called with the node already
8249 -- analyzed (i.e. Analyzed (N) is True). This is important, since
8250 -- otherwise we would get a recursive processing of the node when
8251 -- we do this Analyze call.
8253 Analyze (N);
8254 end Wrap_Transient_Statement;
8256 end Exp_Ch7;