1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2011, Free Software Foundation, Inc. --
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. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 -- This package contains virtually all expansion mechanisms related to
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_Tss; use Exp_Tss;
42 with Exp_Util; use Exp_Util;
43 with Freeze; use Freeze;
45 with Nlists; use Nlists;
46 with Nmake; use Nmake;
48 with Output; use Output;
49 with Restrict; use Restrict;
50 with Rident; use Rident;
51 with Rtsfind; use Rtsfind;
52 with Sinfo; use Sinfo;
54 with Sem_Aux; use Sem_Aux;
55 with Sem_Ch3; use Sem_Ch3;
56 with Sem_Ch7; use Sem_Ch7;
57 with Sem_Ch8; use Sem_Ch8;
58 with Sem_Res; use Sem_Res;
59 with Sem_Util; use Sem_Util;
60 with Snames; use Snames;
61 with Stand; use Stand;
62 with Targparm; use Targparm;
63 with Tbuild; use Tbuild;
64 with Ttypes; use Ttypes;
65 with Uintp; use Uintp;
67 package body Exp_Ch7 is
69 --------------------------------
70 -- Transient Scope Management --
71 --------------------------------
73 -- A transient scope is created when temporary objects are created by the
74 -- compiler. These temporary objects are allocated on the secondary stack
75 -- and the transient scope is responsible for finalizing the object when
76 -- appropriate and reclaiming the memory at the right time. The temporary
77 -- objects are generally the objects allocated to store the result of a
78 -- function returning an unconstrained or a tagged value. Expressions
79 -- needing to be wrapped in a transient scope (functions calls returning
80 -- unconstrained or tagged values) may appear in 3 different contexts which
81 -- lead to 3 different kinds of transient scope expansion:
83 -- 1. In a simple statement (procedure call, assignment, ...). In
84 -- this case the instruction is wrapped into a transient block.
85 -- (See Wrap_Transient_Statement for details)
87 -- 2. In an expression of a control structure (test in a IF statement,
88 -- expression in a CASE statement, ...).
89 -- (See Wrap_Transient_Expression for details)
91 -- 3. In a expression of an object_declaration. No wrapping is possible
92 -- here, so the finalization actions, if any, are done right after the
93 -- declaration and the secondary stack deallocation is done in the
94 -- proper enclosing scope (see Wrap_Transient_Declaration for details)
96 -- Note about functions returning tagged types: it has been decided to
97 -- always allocate their result in the secondary stack, even though is not
98 -- absolutely mandatory when the tagged type is constrained because the
99 -- caller knows the size of the returned object and thus could allocate the
100 -- result in the primary stack. An exception to this is when the function
101 -- builds its result in place, as is done for functions with inherently
102 -- limited result types for Ada 2005. In that case, certain callers may
103 -- pass the address of a constrained object as the target object for the
106 -- By allocating tagged results in the secondary stack a number of
107 -- implementation difficulties are avoided:
109 -- - If it is a dispatching function call, the computation of the size of
110 -- the result is possible but complex from the outside.
112 -- - If the returned type is controlled, the assignment of the returned
113 -- value to the anonymous object involves an Adjust, and we have no
114 -- easy way to access the anonymous object created by the back end.
116 -- - If the returned type is class-wide, this is an unconstrained type
119 -- Furthermore, the small loss in efficiency which is the result of this
120 -- decision is not such a big deal because functions returning tagged types
121 -- are not as common in practice compared to functions returning access to
124 --------------------------------------------------
125 -- Transient Blocks and Finalization Management --
126 --------------------------------------------------
128 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id;
129 -- N is a node which may generate a transient scope. Loop over the parent
130 -- pointers of N until it find the appropriate node to wrap. If it returns
131 -- Empty, it means that no transient scope is needed in this context.
133 procedure Insert_Actions_In_Scope_Around (N : Node_Id);
134 -- Insert the before-actions kept in the scope stack before N, and the
135 -- after-actions after N, which must be a member of a list.
137 function Make_Transient_Block
140 Par : Node_Id) return Node_Id;
141 -- Action is a single statement or object declaration. Par is the proper
142 -- parent of the generated block. Create a transient block whose name is
143 -- the current scope and the only handled statement is Action. If Action
144 -- involves controlled objects or secondary stack usage, the corresponding
145 -- cleanup actions are performed at the end of the block.
147 procedure Set_Node_To_Be_Wrapped (N : Node_Id);
148 -- Set the field Node_To_Be_Wrapped of the current scope
150 -- ??? The entire comment needs to be rewritten
152 -----------------------------
153 -- Finalization Management --
154 -----------------------------
156 -- This part describe how Initialization/Adjustment/Finalization procedures
157 -- are generated and called. Two cases must be considered, types that are
158 -- Controlled (Is_Controlled flag set) and composite types that contain
159 -- controlled components (Has_Controlled_Component flag set). In the first
160 -- case the procedures to call are the user-defined primitive operations
161 -- Initialize/Adjust/Finalize. In the second case, GNAT generates
162 -- Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
163 -- of calling the former procedures on the controlled components.
165 -- For records with Has_Controlled_Component set, a hidden "controller"
166 -- component is inserted. This controller component contains its own
167 -- finalization list on which all controlled components are attached
168 -- creating an indirection on the upper-level Finalization list. This
169 -- technique facilitates the management of objects whose number of
170 -- controlled components changes during execution. This controller
171 -- component is itself controlled and is attached to the upper-level
172 -- finalization chain. Its adjust primitive is in charge of calling adjust
173 -- on the components and adjusting the finalization pointer to match their
174 -- new location (see a-finali.adb).
176 -- It is not possible to use a similar technique for arrays that have
177 -- Has_Controlled_Component set. In this case, deep procedures are
178 -- generated that call initialize/adjust/finalize + attachment or
179 -- detachment on the finalization list for all component.
181 -- Initialize calls: they are generated for declarations or dynamic
182 -- allocations of Controlled objects with no initial value. They are always
183 -- followed by an attachment to the current Finalization Chain. For the
184 -- dynamic allocation case this the chain attached to the scope of the
185 -- access type definition otherwise, this is the chain of the current
188 -- Adjust Calls: They are generated on 2 occasions: (1) for
189 -- declarations or dynamic allocations of Controlled objects with an
190 -- initial value. (2) after an assignment. In the first case they are
191 -- followed by an attachment to the final chain, in the second case
194 -- Finalization Calls: They are generated on (1) scope exit, (2)
195 -- assignments, (3) unchecked deallocations. In case (3) they have to
196 -- be detached from the final chain, in case (2) they must not and in
197 -- case (1) this is not important since we are exiting the scope anyway.
201 -- Type extensions will have a new record controller at each derivation
202 -- level containing controlled components. The record controller for
203 -- the parent/ancestor is attached to the finalization list of the
204 -- extension's record controller (i.e. the parent is like a component
205 -- of the extension).
207 -- For types that are both Is_Controlled and Has_Controlled_Components,
208 -- the record controller and the object itself are handled separately.
209 -- It could seem simpler to attach the object at the end of its record
210 -- controller but this would not tackle view conversions properly.
212 -- A classwide type can always potentially have controlled components
213 -- but the record controller of the corresponding actual type may not
214 -- be known at compile time so the dispatch table contains a special
215 -- field that allows to compute the offset of the record controller
216 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
218 -- Here is a simple example of the expansion of a controlled block :
222 -- Y : Controlled := Init;
228 -- Z : R := (C => X);
237 -- _L : System.FI.Finalizable_Ptr;
239 -- procedure _Clean is
242 -- System.FI.Finalize_List (_L);
250 -- Attach_To_Final_List (_L, Finalizable (X), 1);
251 -- at end: Abort_Undefer;
252 -- Y : Controlled := Init;
254 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
262 -- Deep_Initialize (W, _L, 1);
263 -- at end: Abort_Under;
264 -- Z : R := (C => X);
265 -- Deep_Adjust (Z, _L, 1);
269 -- Deep_Finalize (W, False);
270 -- <save W's final pointers>
272 -- <restore W's final pointers>
273 -- Deep_Adjust (W, _L, 0);
278 type Final_Primitives is
279 (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
280 -- This enumeration type is defined in order to ease sharing code for
281 -- building finalization procedures for composite types.
283 Name_Of : constant array (Final_Primitives) of Name_Id :=
284 (Initialize_Case => Name_Initialize,
285 Adjust_Case => Name_Adjust,
286 Finalize_Case => Name_Finalize,
287 Address_Case => Name_Finalize_Address);
288 Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
289 (Initialize_Case => TSS_Deep_Initialize,
290 Adjust_Case => TSS_Deep_Adjust,
291 Finalize_Case => TSS_Deep_Finalize,
292 Address_Case => TSS_Finalize_Address);
294 procedure Build_Array_Deep_Procs (Typ : Entity_Id);
295 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
296 -- Has_Controlled_Component set and store them using the TSS mechanism.
298 function Build_Cleanup_Statements (N : Node_Id) return List_Id;
299 -- Create the clean up calls for an asynchronous call block, task master,
300 -- protected subprogram body, task allocation block or task body. If N is
301 -- neither of these constructs, the routine returns a new list.
303 function Build_Exception_Handler
306 Raised_Id : Entity_Id;
307 For_Library : Boolean := False) return Node_Id;
308 -- Subsidiary to Build_Finalizer, Make_Deep_Array_Body and Make_Deep_Record
309 -- _Body. Create an exception handler of the following form:
312 -- if not Raised_Id then
313 -- Raised_Id := True;
314 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
317 -- If flag For_Library is set (and not in restricted profile):
320 -- if not Raised_Id then
321 -- Raised_Id := True;
322 -- Save_Library_Occurrence (Get_Current_Excep.all.all);
325 -- E_Id denotes the defining identifier of a local exception occurrence.
326 -- Raised_Id is the entity of a local boolean flag. Flag For_Library is
327 -- used when operating at the library level, when enabled the current
328 -- exception will be saved to a global location.
330 procedure Build_Finalizer
332 Clean_Stmts : List_Id;
335 Defer_Abort : Boolean;
336 Fin_Id : out Entity_Id);
337 -- N may denote an accept statement, block, entry body, package body,
338 -- package spec, protected body, subprogram body, and a task body. Create
339 -- a procedure which contains finalization calls for all controlled objects
340 -- declared in the declarative or statement region of N. The calls are
341 -- built in reverse order relative to the original declarations. In the
342 -- case of a tack body, the routine delays the creation of the finalizer
343 -- until all statements have been moved to the task body procedure.
344 -- Clean_Stmts may contain additional context-dependent code used to abort
345 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
346 -- Mark_Id is the secondary stack used in the current context or Empty if
347 -- missing. Top_Decls is the list on which the declaration of the finalizer
348 -- is attached in the non-package case. Defer_Abort indicates that the
349 -- statements passed in perform actions that require abort to be deferred,
350 -- such as for task termination. Fin_Id is the finalizer declaration
353 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
354 -- N is a construct which contains a handled sequence of statements, Fin_Id
355 -- is the entity of a finalizer. Create an At_End handler which covers the
356 -- statements of N and calls Fin_Id. If the handled statement sequence has
357 -- an exception handler, the statements will be wrapped in a block to avoid
358 -- unwanted interaction with the new At_End handler.
360 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
361 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
362 -- Has_Component_Component set and store them using the TSS mechanism.
364 procedure Check_Visibly_Controlled
365 (Prim : Final_Primitives;
367 E : in out Entity_Id;
368 Cref : in out Node_Id);
369 -- The controlled operation declared for a derived type may not be
370 -- overriding, if the controlled operations of the parent type are hidden,
371 -- for example when the parent is a private type whose full view is
372 -- controlled. For other primitive operations we modify the name of the
373 -- operation to indicate that it is not overriding, but this is not
374 -- possible for Initialize, etc. because they have to be retrievable by
375 -- name. Before generating the proper call to one of these operations we
376 -- check whether Typ is known to be controlled at the point of definition.
377 -- If it is not then we must retrieve the hidden operation of the parent
378 -- and use it instead. This is one case that might be solved more cleanly
379 -- once Overriding pragmas or declarations are in place.
381 function Convert_View
384 Ind : Pos := 1) return Node_Id;
385 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
386 -- argument being passed to it. Ind indicates which formal of procedure
387 -- Proc we are trying to match. This function will, if necessary, generate
388 -- a conversion between the partial and full view of Arg to match the type
389 -- of the formal of Proc, or force a conversion to the class-wide type in
390 -- the case where the operation is abstract.
392 function Enclosing_Function (E : Entity_Id) return Entity_Id;
393 -- Given an arbitrary entity, traverse the scope chain looking for the
394 -- first enclosing function. Return Empty if no function was found.
400 For_Parent : Boolean := False) return Node_Id;
401 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
402 -- routine [Deep_]Adjust / Finalize and an object parameter, create an
403 -- adjust / finalization call. Flag For_Parent should be set when field
404 -- _parent is being processed.
406 function Make_Deep_Proc
407 (Prim : Final_Primitives;
409 Stmts : List_Id) return Node_Id;
410 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
411 -- Deep_Finalize procedures according to the first parameter, these
412 -- procedures operate on the type Typ. The Stmts parameter gives the body
415 function Make_Deep_Array_Body
416 (Prim : Final_Primitives;
417 Typ : Entity_Id) return List_Id;
418 -- This function generates the list of statements for implementing
419 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
420 -- the first parameter, these procedures operate on the array type Typ.
422 function Make_Deep_Record_Body
423 (Prim : Final_Primitives;
425 Is_Local : Boolean := False) return List_Id;
426 -- This function generates the list of statements for implementing
427 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
428 -- the first parameter, these procedures operate on the record type Typ.
429 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
430 -- whether the inner logic should be dictated by state counters.
432 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
433 -- Subsidiary to Make_Finalize_Address_Body and Make_Deep_Array_Body.
434 -- Generate the following statements:
437 -- type Acc_Typ is access all Typ;
438 -- for Acc_Typ'Storage_Size use 0;
440 -- [Deep_]Finalize (Acc_Typ (V).all);
443 ----------------------------
444 -- Build_Array_Deep_Procs --
445 ----------------------------
447 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
451 (Prim => Initialize_Case,
453 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
455 if not Is_Immutably_Limited_Type (Typ) then
458 (Prim => Adjust_Case,
460 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
465 (Prim => Finalize_Case,
467 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
469 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
470 -- .NET do not support address arithmetic and unchecked conversions.
472 if VM_Target = No_VM then
475 (Prim => Address_Case,
477 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
479 end Build_Array_Deep_Procs;
481 ------------------------------
482 -- Build_Cleanup_Statements --
483 ------------------------------
485 function Build_Cleanup_Statements (N : Node_Id) return List_Id is
486 Is_Asynchronous_Call : constant Boolean :=
487 Nkind (N) = N_Block_Statement
488 and then Is_Asynchronous_Call_Block (N);
489 Is_Master : constant Boolean :=
490 Nkind (N) /= N_Entry_Body
491 and then Is_Task_Master (N);
492 Is_Protected_Body : constant Boolean :=
493 Nkind (N) = N_Subprogram_Body
494 and then Is_Protected_Subprogram_Body (N);
495 Is_Task_Allocation : constant Boolean :=
496 Nkind (N) = N_Block_Statement
497 and then Is_Task_Allocation_Block (N);
498 Is_Task_Body : constant Boolean :=
499 Nkind (Original_Node (N)) = N_Task_Body;
501 Loc : constant Source_Ptr := Sloc (N);
502 Stmts : constant List_Id := New_List;
506 if Restricted_Profile then
508 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
510 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
514 if Restriction_Active (No_Task_Hierarchy) = False then
515 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
518 -- Add statements to unlock the protected object parameter and to
519 -- undefer abort. If the context is a protected procedure and the object
520 -- has entries, call the entry service routine.
522 -- NOTE: The generated code references _object, a parameter to the
525 elsif Is_Protected_Body then
527 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
528 Conc_Typ : Entity_Id;
531 Param_Typ : Entity_Id;
534 -- Find the _object parameter representing the protected object
536 Param := First (Parameter_Specifications (Spec));
538 Param_Typ := Etype (Parameter_Type (Param));
540 if Ekind (Param_Typ) = E_Record_Type then
541 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
544 exit when No (Param) or else Present (Conc_Typ);
548 pragma Assert (Present (Param));
550 -- If the associated protected object has entries, a protected
551 -- procedure has to service entry queues. In this case generate:
553 -- Service_Entries (_object._object'Access);
555 if Nkind (Specification (N)) = N_Procedure_Specification
556 and then Has_Entries (Conc_Typ)
558 case Corresponding_Runtime_Package (Conc_Typ) is
559 when System_Tasking_Protected_Objects_Entries =>
560 Nam := New_Reference_To (RTE (RE_Service_Entries), Loc);
562 when System_Tasking_Protected_Objects_Single_Entry =>
563 Nam := New_Reference_To (RTE (RE_Service_Entry), Loc);
570 Make_Procedure_Call_Statement (Loc,
572 Parameter_Associations => New_List (
573 Make_Attribute_Reference (Loc,
575 Make_Selected_Component (Loc,
576 Prefix => New_Reference_To (
577 Defining_Identifier (Param), Loc),
579 Make_Identifier (Loc, Name_uObject)),
580 Attribute_Name => Name_Unchecked_Access))));
584 -- Unlock (_object._object'Access);
586 case Corresponding_Runtime_Package (Conc_Typ) is
587 when System_Tasking_Protected_Objects_Entries =>
588 Nam := New_Reference_To (RTE (RE_Unlock_Entries), Loc);
590 when System_Tasking_Protected_Objects_Single_Entry =>
591 Nam := New_Reference_To (RTE (RE_Unlock_Entry), Loc);
593 when System_Tasking_Protected_Objects =>
594 Nam := New_Reference_To (RTE (RE_Unlock), Loc);
601 Make_Procedure_Call_Statement (Loc,
603 Parameter_Associations => New_List (
604 Make_Attribute_Reference (Loc,
606 Make_Selected_Component (Loc,
609 (Defining_Identifier (Param), Loc),
611 Make_Identifier (Loc, Name_uObject)),
612 Attribute_Name => Name_Unchecked_Access))));
618 if Abort_Allowed then
620 Make_Procedure_Call_Statement (Loc,
622 New_Reference_To (RTE (RE_Abort_Undefer), Loc),
623 Parameter_Associations => Empty_List));
627 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
628 -- tasks. Other unactivated tasks are completed by Complete_Task or
631 -- NOTE: The generated code references _chain, a local object
633 elsif Is_Task_Allocation then
636 -- Expunge_Unactivated_Tasks (_chain);
638 -- where _chain is the list of tasks created by the allocator but not
639 -- yet activated. This list will be empty unless the block completes
643 Make_Procedure_Call_Statement (Loc,
646 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
647 Parameter_Associations => New_List (
648 New_Reference_To (Activation_Chain_Entity (N), Loc))));
650 -- Attempt to cancel an asynchronous entry call whenever the block which
651 -- contains the abortable part is exited.
653 -- NOTE: The generated code references Cnn, a local object
655 elsif Is_Asynchronous_Call then
657 Cancel_Param : constant Entity_Id :=
658 Entry_Cancel_Parameter (Entity (Identifier (N)));
661 -- If it is of type Communication_Block, this must be a protected
662 -- entry call. Generate:
664 -- if Enqueued (Cancel_Param) then
665 -- Cancel_Protected_Entry_Call (Cancel_Param);
668 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
670 Make_If_Statement (Loc,
672 Make_Function_Call (Loc,
674 New_Reference_To (RTE (RE_Enqueued), Loc),
675 Parameter_Associations => New_List (
676 New_Reference_To (Cancel_Param, Loc))),
678 Then_Statements => New_List (
679 Make_Procedure_Call_Statement (Loc,
682 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
683 Parameter_Associations => New_List (
684 New_Reference_To (Cancel_Param, Loc))))));
686 -- Asynchronous delay, generate:
687 -- Cancel_Async_Delay (Cancel_Param);
689 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
691 Make_Procedure_Call_Statement (Loc,
693 New_Reference_To (RTE (RE_Cancel_Async_Delay), Loc),
694 Parameter_Associations => New_List (
695 Make_Attribute_Reference (Loc,
697 New_Reference_To (Cancel_Param, Loc),
698 Attribute_Name => Name_Unchecked_Access))));
700 -- Task entry call, generate:
701 -- Cancel_Task_Entry_Call (Cancel_Param);
705 Make_Procedure_Call_Statement (Loc,
707 New_Reference_To (RTE (RE_Cancel_Task_Entry_Call), Loc),
708 Parameter_Associations => New_List (
709 New_Reference_To (Cancel_Param, Loc))));
715 end Build_Cleanup_Statements;
717 -----------------------------
718 -- Build_Controlling_Procs --
719 -----------------------------
721 procedure Build_Controlling_Procs (Typ : Entity_Id) is
723 if Is_Array_Type (Typ) then
724 Build_Array_Deep_Procs (Typ);
725 else pragma Assert (Is_Record_Type (Typ));
726 Build_Record_Deep_Procs (Typ);
728 end Build_Controlling_Procs;
730 -----------------------------
731 -- Build_Exception_Handler --
732 -----------------------------
734 function Build_Exception_Handler
737 Raised_Id : Entity_Id;
738 For_Library : Boolean := False) return Node_Id
741 Proc_To_Call : Entity_Id;
744 pragma Assert (Present (E_Id));
745 pragma Assert (Present (Raised_Id));
748 -- Get_Current_Excep.all.all
750 Actuals := New_List (
751 Make_Explicit_Dereference (Loc,
753 Make_Function_Call (Loc,
755 Make_Explicit_Dereference (Loc,
757 New_Reference_To (RTE (RE_Get_Current_Excep), Loc)))));
759 if For_Library and then not Restricted_Profile then
760 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
763 Proc_To_Call := RTE (RE_Save_Occurrence);
764 Prepend_To (Actuals, New_Reference_To (E_Id, Loc));
769 -- if not Raised_Id then
770 -- Raised_Id := True;
772 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
774 -- Save_Library_Occurrence (Get_Current_Excep.all.all);
778 Make_Exception_Handler (Loc,
779 Exception_Choices => New_List (
780 Make_Others_Choice (Loc)),
782 Statements => New_List (
783 Make_If_Statement (Loc,
786 Right_Opnd => New_Reference_To (Raised_Id, Loc)),
788 Then_Statements => New_List (
789 Make_Assignment_Statement (Loc,
790 Name => New_Reference_To (Raised_Id, Loc),
791 Expression => New_Reference_To (Standard_True, Loc)),
793 Make_Procedure_Call_Statement (Loc,
795 New_Reference_To (Proc_To_Call, Loc),
796 Parameter_Associations => Actuals)))));
797 end Build_Exception_Handler;
799 -----------------------------------
800 -- Build_Finalization_Collection --
801 -----------------------------------
803 procedure Build_Finalization_Collection
805 Ins_Node : Node_Id := Empty;
806 Encl_Scope : Entity_Id := Empty)
808 Desig_Typ : constant Entity_Id := Directly_Designated_Type (Typ);
810 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
811 -- Determine whether entity E is inside a wrapper package created for
812 -- an instance of Ada.Unchecked_Deallocation.
814 ------------------------------
815 -- In_Deallocation_Instance --
816 ------------------------------
818 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
819 Pkg : constant Entity_Id := Scope (E);
820 Par : Node_Id := Empty;
823 if Ekind (Pkg) = E_Package
824 and then Present (Related_Instance (Pkg))
825 and then Ekind (Related_Instance (Pkg)) = E_Procedure
827 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
831 and then Chars (Par) = Name_Unchecked_Deallocation
832 and then Chars (Scope (Par)) = Name_Ada
833 and then Scope (Scope (Par)) = Standard_Standard;
837 end In_Deallocation_Instance;
839 -- Start of processing for Build_Finalization_Collection
842 -- Certain run-time configurations and targets do not provide support
843 -- for controlled types.
845 if Restriction_Active (No_Finalization) then
848 -- Various machinery such as freezing may have already created a
851 elsif Present (Associated_Collection (Typ)) then
854 -- Do not process types that return on the secondary stack
856 -- ??? The need for a secondary stack should be revisited and perhaps
859 elsif Present (Associated_Storage_Pool (Typ))
860 and then Is_RTE (Associated_Storage_Pool (Typ), RE_SS_Pool)
864 -- Do not process types which may never allocate an object
866 elsif No_Pool_Assigned (Typ) then
869 -- Do not process access types coming from Ada.Unchecked_Deallocation
870 -- instances. Even though the designated type may be controlled, the
871 -- access type will never participate in allocation.
873 elsif In_Deallocation_Instance (Typ) then
876 -- Ignore the general use of anonymous access types unless the context
877 -- requires a collection.
879 elsif Ekind (Typ) = E_Anonymous_Access_Type
880 and then No (Ins_Node)
884 -- Do not process non-library access types when restriction No_Nested_
885 -- Finalization is in effect since collections are controlled objects.
887 elsif Restriction_Active (No_Nested_Finalization)
888 and then not Is_Library_Level_Entity (Typ)
892 -- For .NET/JVM targets, allow the processing of access-to-controlled
893 -- types where the designated type is explicitly derived from [Limited_]
896 elsif VM_Target /= No_VM
897 and then not Is_Controlled (Desig_Typ)
903 Loc : constant Source_Ptr := Sloc (Typ);
904 Actions : constant List_Id := New_List;
910 -- Fnn : Finalization_Collection;
912 -- Source access types use fixed names for their collections since
913 -- the collection is inserted only once in the same source unit and
914 -- there is no possible name overlap. Internally-generated access
915 -- types on the other hand use temporaries as collection names due
916 -- to possible name collisions.
918 if Comes_From_Source (Typ) then
920 Make_Defining_Identifier (Loc,
921 Chars => New_External_Name (Chars (Typ), "FC"));
923 Coll_Id := Make_Temporary (Loc, 'F');
927 Make_Object_Declaration (Loc,
928 Defining_Identifier => Coll_Id,
930 New_Reference_To (RTE (RE_Finalization_Collection), Loc)));
932 -- Storage pool selection and attribute decoration of the generated
933 -- collection. Since .NET/JVM compilers do not support pools, this
936 if VM_Target = No_VM then
938 -- If the access type has a user-defined pool, use it as the base
939 -- storage medium for the finalization pool.
941 if Present (Associated_Storage_Pool (Typ)) then
942 Pool_Id := Associated_Storage_Pool (Typ);
944 -- Access subtypes must use the storage pool of their base type
946 elsif Ekind (Typ) = E_Access_Subtype then
948 Base_Typ : constant Entity_Id := Base_Type (Typ);
951 if No (Associated_Storage_Pool (Base_Typ)) then
952 Pool_Id := RTE (RE_Global_Pool_Object);
953 Set_Associated_Storage_Pool (Base_Typ, Pool_Id);
955 Pool_Id := Associated_Storage_Pool (Base_Typ);
959 -- The default choice is the global pool
962 Pool_Id := RTE (RE_Global_Pool_Object);
963 Set_Associated_Storage_Pool (Typ, Pool_Id);
967 -- Set_Storage_Pool_Ptr (Fnn, Pool_Id'Unchecked_Access);
970 Make_Procedure_Call_Statement (Loc,
972 New_Reference_To (RTE (RE_Set_Storage_Pool_Ptr), Loc),
973 Parameter_Associations => New_List (
974 New_Reference_To (Coll_Id, Loc),
975 Make_Attribute_Reference (Loc,
976 Prefix => New_Reference_To (Pool_Id, Loc),
977 Attribute_Name => Name_Unrestricted_Access))));
980 Set_Associated_Collection (Typ, Coll_Id);
982 -- A finalization collection created for an anonymous access type
983 -- must be inserted before a context-dependent node.
985 if Present (Ins_Node) then
986 Push_Scope (Encl_Scope);
988 -- Treat use clauses as declarations and insert directly in front
991 if Nkind_In (Ins_Node, N_Use_Package_Clause,
994 Insert_List_Before_And_Analyze (Ins_Node, Actions);
996 Insert_Actions (Ins_Node, Actions);
1001 elsif Ekind (Typ) = E_Access_Subtype
1002 or else (Ekind (Desig_Typ) = E_Incomplete_Type
1003 and then Has_Completion_In_Body (Desig_Typ))
1005 Insert_Actions (Parent (Typ), Actions);
1007 -- If the designated type is not yet frozen, then append the actions
1008 -- to that type's freeze actions. The actions need to be appended to
1009 -- whichever type is frozen later, similarly to what Freeze_Type does
1010 -- for appending the storage pool declaration for an access type.
1011 -- Otherwise, the call to Set_Storage_Pool_Ptr might reference the
1012 -- pool object before it's declared. However, it's not clear that
1013 -- this is exactly the right test to accomplish that here. ???
1015 elsif Present (Freeze_Node (Desig_Typ))
1016 and then not Analyzed (Freeze_Node (Desig_Typ))
1018 Append_Freeze_Actions (Desig_Typ, Actions);
1020 elsif Present (Freeze_Node (Typ))
1021 and then not Analyzed (Freeze_Node (Typ))
1023 Append_Freeze_Actions (Typ, Actions);
1025 -- If there's a pool created locally for the access type, then we
1026 -- need to ensure that the collection gets created after the pool
1027 -- object, because otherwise we can have a forward reference, so
1028 -- we force the collection actions to be inserted and analyzed after
1029 -- the pool entity. Note that both the access type and its designated
1030 -- type may have already been frozen and had their freezing actions
1031 -- analyzed at this point. (This seems a little unclean.???)
1033 elsif VM_Target = No_VM
1034 and then Scope (Pool_Id) = Scope (Typ)
1036 Insert_List_After_And_Analyze (Parent (Pool_Id), Actions);
1039 Insert_Actions (Parent (Typ), Actions);
1042 end Build_Finalization_Collection;
1044 ---------------------
1045 -- Build_Finalizer --
1046 ---------------------
1048 procedure Build_Finalizer
1050 Clean_Stmts : List_Id;
1051 Mark_Id : Entity_Id;
1052 Top_Decls : List_Id;
1053 Defer_Abort : Boolean;
1054 Fin_Id : out Entity_Id)
1056 Acts_As_Clean : constant Boolean :=
1059 (Present (Clean_Stmts)
1060 and then Is_Non_Empty_List (Clean_Stmts));
1061 Exceptions_OK : constant Boolean :=
1062 not Restriction_Active (No_Exception_Propagation);
1063 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1064 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1065 For_Package : constant Boolean :=
1066 For_Package_Body or else For_Package_Spec;
1067 Loc : constant Source_Ptr := Sloc (N);
1069 -- NOTE: Local variable declarations are conservative and do not create
1070 -- structures right from the start. Entities and lists are created once
1071 -- it has been established that N has at least one controlled object.
1073 Abort_Id : Entity_Id := Empty;
1074 -- Entity of local flag. The flag is set when finalization is triggered
1077 Components_Built : Boolean := False;
1078 -- A flag used to avoid double initialization of entities and lists. If
1079 -- the flag is set then the following variables have been initialized:
1089 Counter_Id : Entity_Id := Empty;
1090 Counter_Val : Int := 0;
1091 -- Name and value of the state counter
1093 Decls : List_Id := No_List;
1094 -- Declarative region of N (if available). If N is a package declaration
1095 -- Decls denotes the visible declarations.
1097 E_Id : Entity_Id := Empty;
1098 -- Entity of the local exception occurence. The first exception which
1099 -- occurred during finalization is stored in E_Id and later reraised.
1101 Finalizer_Decls : List_Id := No_List;
1102 -- Local variable declarations. This list holds the label declarations
1103 -- of all jump block alternatives as well as the declaration of the
1104 -- local exception occurence and the raised flag.
1106 -- E : Exception_Occurrence;
1107 -- Raised : Boolean := False;
1108 -- L<counter value> : label;
1110 Finalizer_Insert_Nod : Node_Id := Empty;
1111 -- Insertion point for the finalizer body. Depending on the context
1112 -- (Nkind of N) and the individual grouping of controlled objects, this
1113 -- node may denote a package declaration or body, package instantiation,
1114 -- block statement or a counter update statement.
1116 Finalizer_Stmts : List_Id := No_List;
1117 -- The statement list of the finalizer body. It contains the following:
1119 -- Abort_Defer; -- Added if abort is allowed
1120 -- <call to Prev_At_End> -- Added if exists
1121 -- <cleanup statements> -- Added if Acts_As_Clean
1122 -- <jump block> -- Added if Has_Ctrl_Objs
1123 -- <finalization statements> -- Added if Has_Ctrl_Objs
1124 -- <stack release> -- Added if Mark_Id exists
1125 -- Abort_Undefer; -- Added if abort is allowed
1127 Has_Ctrl_Objs : Boolean := False;
1128 -- A general flag which denotes whether N has at least one controlled
1131 HSS : Node_Id := Empty;
1132 -- The sequence of statements of N (if available)
1134 Jump_Alts : List_Id := No_List;
1135 -- Jump block alternatives. Depending on the value of the state counter,
1136 -- the control flow jumps to a sequence of finalization statments. This
1137 -- list contains the following:
1139 -- when <counter value> =>
1140 -- goto L<counter value>;
1142 Jump_Block_Insert_Nod : Node_Id := Empty;
1143 -- Specific point in the finalizer statements where the jump block is
1146 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1147 -- The last controlled construct encountered when processing the top
1148 -- level lists of N. This can be a nested package, an instantiation or
1149 -- an object declaration.
1151 Prev_At_End : Entity_Id := Empty;
1152 -- The previous at end procedure of the handled statements block of N
1154 Priv_Decls : List_Id := No_List;
1155 -- The private declarations of N if N is a package declaration
1157 Raised_Id : Entity_Id := Empty;
1158 -- Entity for the raised flag. Along with E_Id, the flag is used in the
1159 -- propagation of exceptions which occur during finalization.
1161 Spec_Id : Entity_Id := Empty;
1162 Spec_Decls : List_Id := Top_Decls;
1163 Stmts : List_Id := No_List;
1165 -----------------------
1166 -- Local subprograms --
1167 -----------------------
1169 procedure Build_Components;
1170 -- Create all entites and initialize all lists used in the creation of
1173 procedure Create_Finalizer;
1174 -- Create the spec and body of the finalizer and insert them in the
1175 -- proper place in the tree depending on the context.
1177 procedure Process_Declarations
1179 Preprocess : Boolean := False;
1180 Top_Level : Boolean := False);
1181 -- Inspect a list of declarations or statements which may contain
1182 -- objects that need finalization. When flag Preprocess is set, the
1183 -- routine will simply count the total number of controlled objects in
1184 -- Decls. Flag Top_Level denotes whether the processing is done for
1185 -- objects in nested package decparations or instances.
1187 procedure Process_Object_Declaration
1189 Has_No_Init : Boolean := False;
1190 Is_Protected : Boolean := False);
1191 -- Generate all the machinery associated with the finalization of a
1192 -- single object. Flag Has_No_Init is used to denote certain contexts
1193 -- where Decl does not have initialization call(s). Flag Is_Protected
1194 -- is set when Decl denotes a simple protected object.
1196 ----------------------
1197 -- Build_Components --
1198 ----------------------
1200 procedure Build_Components is
1201 Counter_Decl : Node_Id;
1202 Counter_Typ : Entity_Id;
1203 Counter_Typ_Decl : Node_Id;
1206 pragma Assert (Present (Decls));
1208 -- This routine might be invoked several times when dealing with
1209 -- constructs that have two lists (either two declarative regions
1210 -- or declarations and statements). Avoid double initialization.
1212 if Components_Built then
1216 Components_Built := True;
1218 if Has_Ctrl_Objs then
1220 -- Create entities for the counter, its type, the local exception
1221 -- and the raised flag.
1223 Counter_Id := Make_Temporary (Loc, 'C');
1224 Counter_Typ := Make_Temporary (Loc, 'T');
1226 if Exceptions_OK then
1227 Abort_Id := Make_Temporary (Loc, 'A');
1228 E_Id := Make_Temporary (Loc, 'E');
1229 Raised_Id := Make_Temporary (Loc, 'R');
1232 -- Since the total number of controlled objects is always known,
1233 -- build a subtype of Natural with precise bounds. This allows
1234 -- the backend to optimize the case statement. Generate:
1236 -- subtype Tnn is Natural range 0 .. Counter_Val;
1239 Make_Subtype_Declaration (Loc,
1240 Defining_Identifier => Counter_Typ,
1241 Subtype_Indication =>
1242 Make_Subtype_Indication (Loc,
1243 Subtype_Mark => New_Reference_To (Standard_Natural, Loc),
1245 Make_Range_Constraint (Loc,
1249 Make_Integer_Literal (Loc, Uint_0),
1251 Make_Integer_Literal (Loc, Counter_Val)))));
1253 -- Generate the declaration of the counter itself:
1255 -- Counter : Integer := 0;
1258 Make_Object_Declaration (Loc,
1259 Defining_Identifier => Counter_Id,
1260 Object_Definition => New_Reference_To (Counter_Typ, Loc),
1261 Expression => Make_Integer_Literal (Loc, 0));
1263 -- Set the type of the counter explicitly to prevent errors when
1264 -- examining object declarations later on.
1266 Set_Etype (Counter_Id, Counter_Typ);
1268 -- The counter and its type are inserted before the source
1269 -- declarations of N.
1271 Prepend_To (Decls, Counter_Decl);
1272 Prepend_To (Decls, Counter_Typ_Decl);
1274 -- The counter and its associated type must be manually analized
1275 -- since N has already been analyzed. Use the scope of the spec
1276 -- when inserting in a package.
1279 Push_Scope (Spec_Id);
1280 Analyze (Counter_Typ_Decl);
1281 Analyze (Counter_Decl);
1285 Analyze (Counter_Typ_Decl);
1286 Analyze (Counter_Decl);
1289 Finalizer_Decls := New_List;
1290 Jump_Alts := New_List;
1293 -- If the context requires additional clean up, the finalization
1294 -- machinery is added after the clean up code.
1296 if Acts_As_Clean then
1297 Finalizer_Stmts := Clean_Stmts;
1298 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1300 Finalizer_Stmts := New_List;
1302 end Build_Components;
1304 ----------------------
1305 -- Create_Finalizer --
1306 ----------------------
1308 procedure Create_Finalizer is
1309 Body_Id : Entity_Id;
1312 Jump_Block : Node_Id;
1314 Label_Id : Entity_Id;
1316 function New_Finalizer_Name return Name_Id;
1317 -- Create a fully qualified name of a package spec or body finalizer.
1318 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1320 ------------------------
1321 -- New_Finalizer_Name --
1322 ------------------------
1324 function New_Finalizer_Name return Name_Id is
1325 procedure New_Finalizer_Name (Id : Entity_Id);
1326 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1327 -- has a non-standard scope, process the scope first.
1329 ------------------------
1330 -- New_Finalizer_Name --
1331 ------------------------
1333 procedure New_Finalizer_Name (Id : Entity_Id) is
1335 if Scope (Id) = Standard_Standard then
1336 Get_Name_String (Chars (Id));
1339 New_Finalizer_Name (Scope (Id));
1340 Add_Str_To_Name_Buffer ("__");
1341 Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1343 end New_Finalizer_Name;
1345 -- Start of processing for New_Finalizer_Name
1348 -- Create the fully qualified name of the enclosing scope
1350 New_Finalizer_Name (Spec_Id);
1353 -- __finalize_[spec|body]
1355 Add_Str_To_Name_Buffer ("__finalize_");
1357 if For_Package_Spec then
1358 Add_Str_To_Name_Buffer ("spec");
1360 Add_Str_To_Name_Buffer ("body");
1364 end New_Finalizer_Name;
1366 -- Start of processing for Create_Finalizer
1369 -- Step 1: Creation of the finalizer name
1371 -- Packages must use a distinct name for their finalizers since the
1372 -- binder will have to generate calls to them by name. The name is
1373 -- of the following form:
1375 -- xx__yy__finalize_[spec|body]
1378 Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1379 Set_Has_Qualified_Name (Fin_Id);
1380 Set_Has_Fully_Qualified_Name (Fin_Id);
1382 -- The default name is _finalizer
1386 Make_Defining_Identifier (Loc,
1387 Chars => New_External_Name (Name_uFinalizer));
1390 -- Step 2: Creation of the finalizer specification
1393 -- procedure Fin_Id;
1396 Make_Subprogram_Declaration (Loc,
1398 Make_Procedure_Specification (Loc,
1399 Defining_Unit_Name => Fin_Id));
1401 -- Step 3: Creation of the finalizer body
1403 if Has_Ctrl_Objs then
1405 -- Add L0, the default destination to the jump block
1407 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1408 Set_Entity (Label_Id,
1409 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1410 Label := Make_Label (Loc, Label_Id);
1415 Prepend_To (Finalizer_Decls,
1416 Make_Implicit_Label_Declaration (Loc,
1417 Defining_Identifier => Entity (Label_Id),
1418 Label_Construct => Label));
1424 Append_To (Jump_Alts,
1425 Make_Case_Statement_Alternative (Loc,
1426 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1427 Statements => New_List (
1428 Make_Goto_Statement (Loc,
1429 Name => New_Reference_To (Entity (Label_Id), Loc)))));
1434 Append_To (Finalizer_Stmts, Label);
1436 -- The local exception does not need to be reraised for library-
1437 -- level finalizers. Generate:
1440 -- Raise_From_Controlled_Operation (E, Abort);
1444 and then Exceptions_OK
1446 Append_To (Finalizer_Stmts,
1447 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
1450 -- Create the jump block which controls the finalization flow
1451 -- depending on the value of the state counter.
1454 Make_Case_Statement (Loc,
1455 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
1456 Alternatives => Jump_Alts);
1459 and then Present (Jump_Block_Insert_Nod)
1461 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1463 Prepend_To (Finalizer_Stmts, Jump_Block);
1467 -- Add a call to the previous At_End handler if it exists. The call
1468 -- must always precede the jump block.
1470 if Present (Prev_At_End) then
1471 Prepend_To (Finalizer_Stmts,
1472 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1474 -- Clear the At_End handler since we have already generated the
1475 -- proper replacement call for it.
1477 Set_At_End_Proc (HSS, Empty);
1480 -- Release the secondary stack mark
1482 if Present (Mark_Id) then
1483 Append_To (Finalizer_Stmts,
1484 Make_Procedure_Call_Statement (Loc,
1486 New_Reference_To (RTE (RE_SS_Release), Loc),
1487 Parameter_Associations => New_List (
1488 New_Reference_To (Mark_Id, Loc))));
1491 -- Protect the statements with abort defer/undefer. This is only when
1492 -- aborts are allowed and the clean up statements require deferral or
1493 -- there are controlled objects to be finalized.
1497 (Defer_Abort or else Has_Ctrl_Objs)
1499 Prepend_To (Finalizer_Stmts,
1500 Make_Procedure_Call_Statement (Loc,
1501 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc)));
1503 Append_To (Finalizer_Stmts,
1504 Make_Procedure_Call_Statement (Loc,
1505 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
1509 -- procedure Fin_Id is
1510 -- Abort : constant Boolean :=
1511 -- Exception_Occurrence (Get_Current_Excep.all.all) =
1512 -- Standard'Abort_Signal'Identity;
1514 -- Abort : constant Boolean := False; -- no abort
1516 -- E : Exception_Occurrence; -- All added if flag
1517 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1523 -- Abort_Defer; -- Added if abort is allowed
1524 -- <call to Prev_At_End> -- Added if exists
1525 -- <cleanup statements> -- Added if Acts_As_Clean
1526 -- <jump block> -- Added if Has_Ctrl_Objs
1527 -- <finalization statements> -- Added if Has_Ctrl_Objs
1528 -- <stack release> -- Added if Mark_Id exists
1529 -- Abort_Undefer; -- Added if abort is allowed
1533 and then Exceptions_OK
1535 Prepend_List_To (Finalizer_Decls,
1536 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id));
1539 -- Create the body of the finalizer
1541 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1544 Set_Has_Qualified_Name (Body_Id);
1545 Set_Has_Fully_Qualified_Name (Body_Id);
1549 Make_Subprogram_Body (Loc,
1551 Make_Procedure_Specification (Loc,
1552 Defining_Unit_Name => Body_Id),
1554 Declarations => Finalizer_Decls,
1556 Handled_Statement_Sequence =>
1557 Make_Handled_Sequence_Of_Statements (Loc, Finalizer_Stmts));
1559 -- Step 4: Spec and body insertion, analysis
1563 -- If the package spec has private declarations, the finalizer
1564 -- body must be added to the end of the list in order to have
1565 -- visibility of all private controlled objects. The spec is
1566 -- inserted at the top of the visible declarations.
1568 if For_Package_Spec then
1569 Prepend_To (Decls, Fin_Spec);
1571 if Present (Priv_Decls) then
1572 Append_To (Priv_Decls, Fin_Body);
1574 Append_To (Decls, Fin_Body);
1577 -- For package bodies, the finalizer body is added to the
1578 -- declarative region of the body and finalizer spec goes
1579 -- on the visible declarations of the package spec.
1584 Vis_Decls : List_Id;
1587 Spec_Nod := Spec_Id;
1588 while Nkind (Spec_Nod) /= N_Package_Specification loop
1589 Spec_Nod := Parent (Spec_Nod);
1592 Vis_Decls := Visible_Declarations (Spec_Nod);
1594 Prepend_To (Vis_Decls, Fin_Spec);
1595 Append_To (Decls, Fin_Body);
1599 -- Push the name of the package
1601 Push_Scope (Spec_Id);
1609 -- Create the spec for the finalizer. The At_End handler must be
1610 -- able to call the body which resides in a nested structure.
1614 -- procedure Fin_Id; -- Spec
1616 -- <objects and possibly statements>
1617 -- procedure Fin_Id is ... -- Body
1620 -- Fin_Id; -- At_End handler
1623 pragma Assert (Present (Spec_Decls));
1625 Append_To (Spec_Decls, Fin_Spec);
1628 -- When the finalizer acts solely as a clean up routine, the body
1629 -- is inserted right after the spec.
1632 and then not Has_Ctrl_Objs
1634 Insert_After (Fin_Spec, Fin_Body);
1636 -- In all other cases the body is inserted after either:
1638 -- 1) The counter update statement of the last controlled object
1639 -- 2) The last top level nested controlled package
1640 -- 3) The last top level controlled instantiation
1643 -- Manually freeze the spec. This is somewhat of a hack because
1644 -- a subprogram is frozen when its body is seen and the freeze
1645 -- node appears right before the body. However, in this case,
1646 -- the spec must be frozen earlier since the At_End handler
1647 -- must be able to call it.
1650 -- procedure Fin_Id; -- Spec
1651 -- [Fin_Id] -- Freeze node
1655 -- Fin_Id; -- At_End handler
1658 Ensure_Freeze_Node (Fin_Id);
1659 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1660 Set_Is_Frozen (Fin_Id);
1662 -- In the case where the last construct to contain a controlled
1663 -- object is either a nested package, an instantiation or a
1664 -- freeze node, the body must be inserted directly after the
1667 if Nkind_In (Last_Top_Level_Ctrl_Construct,
1669 N_Package_Declaration,
1672 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1675 Insert_After (Finalizer_Insert_Nod, Fin_Body);
1680 end Create_Finalizer;
1682 --------------------------
1683 -- Process_Declarations --
1684 --------------------------
1686 procedure Process_Declarations
1688 Preprocess : Boolean := False;
1689 Top_Level : Boolean := False)
1694 Obj_Typ : Entity_Id;
1695 Pack_Id : Entity_Id;
1699 Old_Counter_Val : Int;
1700 -- This variable is used to determine whether a nested package or
1701 -- instance contains at least one controlled object.
1703 procedure Processing_Actions
1704 (Has_No_Init : Boolean := False;
1705 Is_Protected : Boolean := False);
1706 -- Depending on the mode of operation of Process_Declarations, either
1707 -- increment the controlled object counter, set the controlled object
1708 -- flag and store the last top level construct or process the current
1709 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1710 -- the current declaration may not have initialization proc(s). Flag
1711 -- Is_Protected should be set when the current declaration denotes a
1712 -- simple protected object.
1714 ------------------------
1715 -- Processing_Actions --
1716 ------------------------
1718 procedure Processing_Actions
1719 (Has_No_Init : Boolean := False;
1720 Is_Protected : Boolean := False)
1724 Counter_Val := Counter_Val + 1;
1725 Has_Ctrl_Objs := True;
1728 and then No (Last_Top_Level_Ctrl_Construct)
1730 Last_Top_Level_Ctrl_Construct := Decl;
1733 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
1735 end Processing_Actions;
1737 -- Start of processing for Process_Declarations
1740 if No (Decls) or else Is_Empty_List (Decls) then
1744 -- Process all declarations in reverse order
1746 Decl := Last_Non_Pragma (Decls);
1747 while Present (Decl) loop
1749 -- Regular object declarations
1751 if Nkind (Decl) = N_Object_Declaration then
1752 Obj_Id := Defining_Identifier (Decl);
1753 Obj_Typ := Base_Type (Etype (Obj_Id));
1754 Expr := Expression (Decl);
1756 -- Bypass any form of processing for objects which have their
1757 -- finalization disabled. This applies only to objects at the
1761 and then Finalize_Storage_Only (Obj_Typ)
1765 -- Transient variables are treated separately in order to
1766 -- minimize the size of the generated code. See Process_
1767 -- Transient_Objects.
1769 elsif Is_Processed_Transient (Obj_Id) then
1772 -- The object is of the form:
1773 -- Obj : Typ [:= Expr];
1775 -- Do not process the incomplete view of a deferred constant
1777 elsif not Is_Imported (Obj_Id)
1778 and then Needs_Finalization (Obj_Typ)
1779 and then not (Ekind (Obj_Id) = E_Constant
1780 and then not Has_Completion (Obj_Id))
1784 -- The object is of the form:
1785 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1787 -- Obj : Access_Typ :=
1788 -- BIP_Function_Call
1789 -- (..., BIPaccess => null, ...)'reference;
1791 elsif Is_Access_Type (Obj_Typ)
1792 and then Needs_Finalization
1793 (Available_View (Designated_Type (Obj_Typ)))
1794 and then Present (Expr)
1796 (Is_Null_Access_BIP_Func_Call (Expr)
1797 or else (Is_Non_BIP_Func_Call (Expr)
1799 Is_Related_To_Func_Return (Obj_Id)))
1801 Processing_Actions (Has_No_Init => True);
1803 -- Simple protected objects which use type System.Tasking.
1804 -- Protected_Objects.Protection to manage their locks should
1805 -- be treated as controlled since they require manual cleanup.
1806 -- The only exception is illustrated in the following example:
1809 -- type Ctrl is new Controlled ...
1810 -- procedure Finalize (Obj : in out Ctrl);
1814 -- package body Pkg is
1815 -- protected Prot is
1816 -- procedure Do_Something (Obj : in out Ctrl);
1819 -- protected body Prot is
1820 -- procedure Do_Something (Obj : in out Ctrl) is ...
1823 -- procedure Finalize (Obj : in out Ctrl) is
1825 -- Prot.Do_Something (Obj);
1829 -- Since for the most part entities in package bodies depend on
1830 -- those in package specs, Prot's lock should be cleaned up
1831 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1832 -- This act however attempts to invoke Do_Something and fails
1833 -- because the lock has disappeared.
1835 elsif Ekind (Obj_Id) = E_Variable
1836 and then not In_Library_Level_Package_Body (Obj_Id)
1838 (Is_Simple_Protected_Type (Obj_Typ)
1839 or else Has_Simple_Protected_Object (Obj_Typ))
1841 Processing_Actions (Is_Protected => True);
1844 -- Specific cases of object renamings
1846 elsif Nkind (Decl) = N_Object_Renaming_Declaration
1847 and then Nkind (Name (Decl)) = N_Explicit_Dereference
1848 and then Nkind (Prefix (Name (Decl))) = N_Identifier
1850 Obj_Id := Defining_Identifier (Decl);
1851 Obj_Typ := Base_Type (Etype (Obj_Id));
1853 -- Bypass any form of processing for objects which have their
1854 -- finalization disabled. This applies only to objects at the
1858 and then Finalize_Storage_Only (Obj_Typ)
1862 -- Return object of a build-in-place function. This case is
1863 -- recognized and marked by the expansion of an extended return
1864 -- statement (see Expand_N_Extended_Return_Statement).
1866 elsif Needs_Finalization (Obj_Typ)
1867 and then Is_Return_Object (Obj_Id)
1868 and then Present (Return_Flag (Obj_Id))
1870 Processing_Actions (Has_No_Init => True);
1873 -- Inspect the freeze node of an access-to-controlled type and
1874 -- look for a delayed finalization collection. This case arises
1875 -- when the freeze actions are inserted at a later time than the
1876 -- expansion of the context. Since Build_Finalizer is never called
1877 -- on a single construct twice, the collection will be ultimately
1878 -- left out and never finalized. This is also needed for freeze
1879 -- actions of designated types themselves, since in some cases the
1880 -- finalization collection is associated with a designated type's
1881 -- freeze node rather than that of the access type (see handling
1882 -- for freeze actions in Build_Finalization_Collection).
1884 elsif Nkind (Decl) = N_Freeze_Entity
1885 and then Present (Actions (Decl))
1887 Typ := Entity (Decl);
1889 if (Is_Access_Type (Typ)
1890 and then not Is_Access_Subprogram_Type (Typ)
1891 and then Needs_Finalization
1892 (Available_View (Designated_Type (Typ))))
1893 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
1895 Old_Counter_Val := Counter_Val;
1897 -- Freeze nodes are considered to be identical to packages
1898 -- and blocks in terms of nesting. The difference is that
1899 -- a finalization collection created inside the freeze node
1900 -- is at the same nesting level as the node itself.
1902 Process_Declarations (Actions (Decl), Preprocess);
1904 -- The freeze node contains a finalization collection
1908 and then No (Last_Top_Level_Ctrl_Construct)
1909 and then Counter_Val > Old_Counter_Val
1911 Last_Top_Level_Ctrl_Construct := Decl;
1915 -- Nested package declarations, avoid generics
1917 elsif Nkind (Decl) = N_Package_Declaration then
1918 Spec := Specification (Decl);
1919 Pack_Id := Defining_Unit_Name (Spec);
1921 if Nkind (Pack_Id) = N_Defining_Program_Unit_Name then
1922 Pack_Id := Defining_Identifier (Pack_Id);
1925 if Ekind (Pack_Id) /= E_Generic_Package then
1926 Old_Counter_Val := Counter_Val;
1927 Process_Declarations
1928 (Private_Declarations (Spec), Preprocess);
1929 Process_Declarations
1930 (Visible_Declarations (Spec), Preprocess);
1932 -- Either the visible or the private declarations contain a
1933 -- controlled object. The nested package declaration is the
1934 -- last such construct.
1938 and then No (Last_Top_Level_Ctrl_Construct)
1939 and then Counter_Val > Old_Counter_Val
1941 Last_Top_Level_Ctrl_Construct := Decl;
1945 -- Nested package bodies, avoid generics
1947 elsif Nkind (Decl) = N_Package_Body then
1948 Spec := Corresponding_Spec (Decl);
1950 if Ekind (Spec) /= E_Generic_Package then
1951 Old_Counter_Val := Counter_Val;
1952 Process_Declarations (Declarations (Decl), Preprocess);
1954 -- The nested package body is the last construct to contain
1955 -- a controlled object.
1959 and then No (Last_Top_Level_Ctrl_Construct)
1960 and then Counter_Val > Old_Counter_Val
1962 Last_Top_Level_Ctrl_Construct := Decl;
1966 -- Handle a rare case caused by a controlled transient variable
1967 -- created as part of a record init proc. The variable is wrapped
1968 -- in a block, but the block is not associated with a transient
1971 elsif Nkind (Decl) = N_Block_Statement
1972 and then Inside_Init_Proc
1974 Old_Counter_Val := Counter_Val;
1976 if Present (Handled_Statement_Sequence (Decl)) then
1977 Process_Declarations
1978 (Statements (Handled_Statement_Sequence (Decl)),
1982 Process_Declarations (Declarations (Decl), Preprocess);
1984 -- Either the declaration or statement list of the block has a
1985 -- controlled object.
1989 and then No (Last_Top_Level_Ctrl_Construct)
1990 and then Counter_Val > Old_Counter_Val
1992 Last_Top_Level_Ctrl_Construct := Decl;
1996 Prev_Non_Pragma (Decl);
1998 end Process_Declarations;
2000 --------------------------------
2001 -- Process_Object_Declaration --
2002 --------------------------------
2004 procedure Process_Object_Declaration
2006 Has_No_Init : Boolean := False;
2007 Is_Protected : Boolean := False)
2009 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2010 Loc : constant Source_Ptr := Sloc (Decl);
2012 Count_Ins : Node_Id;
2014 Fin_Stmts : List_Id;
2017 Label_Id : Entity_Id;
2019 Obj_Typ : Entity_Id;
2021 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2022 -- Once it has been established that the current object is in fact a
2023 -- return object of build-in-place function Func_Id, generate the
2024 -- following cleanup code:
2026 -- if BIPallocfrom > Secondary_Stack'Pos
2027 -- and then BIPcollection /= null
2030 -- type Ptr_Typ is access Obj_Typ;
2031 -- for Ptr_Typ'Storage_Pool use Base_Pool (BIPcollection);
2034 -- Free (Ptr_Typ (Temp));
2038 -- Obj_Typ is the type of the current object, Temp is the original
2039 -- allocation which Obj_Id renames.
2041 procedure Find_Last_Init
2044 Last_Init : out Node_Id;
2045 Body_Insert : out Node_Id);
2046 -- An object declaration has at least one and at most two init calls:
2047 -- that of the type and the user-defined initialize. Given an object
2048 -- declaration, Last_Init denotes the last initialization call which
2049 -- follows the declaration. Body_Insert denotes the place where the
2050 -- finalizer body could be potentially inserted.
2052 -----------------------------
2053 -- Build_BIP_Cleanup_Stmts --
2054 -----------------------------
2056 function Build_BIP_Cleanup_Stmts
2057 (Func_Id : Entity_Id) return Node_Id
2059 Collect : constant Entity_Id :=
2060 Build_In_Place_Formal (Func_Id, BIP_Collection);
2061 Decls : constant List_Id := New_List;
2062 Obj_Typ : constant Entity_Id := Etype (Func_Id);
2063 Temp_Id : constant Entity_Id :=
2064 Entity (Prefix (Name (Parent (Obj_Id))));
2068 Free_Stmt : Node_Id;
2069 Pool_Id : Entity_Id;
2070 Ptr_Typ : Entity_Id;
2074 -- Pool_Id renames Base_Pool (BIPcollection.all).all;
2076 Pool_Id := Make_Temporary (Loc, 'P');
2079 Make_Object_Renaming_Declaration (Loc,
2080 Defining_Identifier => Pool_Id,
2082 New_Reference_To (RTE (RE_Root_Storage_Pool), Loc),
2084 Make_Explicit_Dereference (Loc,
2086 Make_Function_Call (Loc,
2088 New_Reference_To (RTE (RE_Base_Pool), Loc),
2089 Parameter_Associations => New_List (
2090 Make_Explicit_Dereference (Loc,
2091 Prefix => New_Reference_To (Collect, Loc)))))));
2093 -- Create an access type which uses the storage pool of the
2094 -- caller's collection.
2097 -- type Ptr_Typ is access Obj_Typ;
2099 Ptr_Typ := Make_Temporary (Loc, 'P');
2102 Make_Full_Type_Declaration (Loc,
2103 Defining_Identifier => Ptr_Typ,
2105 Make_Access_To_Object_Definition (Loc,
2106 Subtype_Indication => New_Reference_To (Obj_Typ, Loc))));
2108 -- Perform minor decoration in order to set the collection and the
2109 -- storage pool attributes.
2111 Set_Ekind (Ptr_Typ, E_Access_Type);
2112 Set_Associated_Collection (Ptr_Typ, Collect);
2113 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2115 -- Create an explicit free statement. Note that the free uses the
2116 -- caller's pool expressed as a renaming.
2119 Make_Free_Statement (Loc,
2121 Unchecked_Convert_To (Ptr_Typ,
2122 New_Reference_To (Temp_Id, Loc)));
2124 Set_Storage_Pool (Free_Stmt, Pool_Id);
2126 -- Create a block to house the dummy type and the instantiation as
2127 -- well as to perform the cleanup the temporary.
2133 -- Free (Ptr_Typ (Temp_Id));
2137 Make_Block_Statement (Loc,
2138 Declarations => Decls,
2139 Handled_Statement_Sequence =>
2140 Make_Handled_Sequence_Of_Statements (Loc,
2141 Statements => New_List (Free_Stmt)));
2144 -- if BIPcollection /= null then
2148 Left_Opnd => New_Reference_To (Collect, Loc),
2149 Right_Opnd => Make_Null (Loc));
2151 -- For constrained or tagged results escalate the condition to
2152 -- include the allocation format. Generate:
2154 -- if BIPallocform > Secondary_Stack'Pos
2155 -- and then BIPcollection /= null
2158 if not Is_Constrained (Obj_Typ)
2159 or else Is_Tagged_Type (Obj_Typ)
2162 Alloc : constant Entity_Id :=
2163 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2169 Left_Opnd => New_Reference_To (Alloc, Loc),
2171 Make_Integer_Literal (Loc,
2173 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2175 Right_Opnd => Cond);
2185 Make_If_Statement (Loc,
2187 Then_Statements => New_List (Free_Blk));
2188 end Build_BIP_Cleanup_Stmts;
2190 --------------------
2191 -- Find_Last_Init --
2192 --------------------
2194 procedure Find_Last_Init
2197 Last_Init : out Node_Id;
2198 Body_Insert : out Node_Id)
2200 Nod_1 : Node_Id := Empty;
2201 Nod_2 : Node_Id := Empty;
2204 function Is_Init_Call
2206 Typ : Entity_Id) return Boolean;
2207 -- Given an arbitrary node, determine whether N is a procedure
2208 -- call and if it is, try to match the name of the call with the
2209 -- [Deep_]Initialize proc of Typ.
2215 function Is_Init_Call
2217 Typ : Entity_Id) return Boolean
2220 -- A call to [Deep_]Initialize is always direct
2222 if Nkind (N) = N_Procedure_Call_Statement
2223 and then Nkind (Name (N)) = N_Identifier
2226 Call_Nam : constant Name_Id := Chars (Entity (Name (N)));
2227 Deep_Init : constant Entity_Id :=
2228 TSS (Typ, TSS_Deep_Initialize);
2229 Init : Entity_Id := Empty;
2232 -- A type may have controlled components but not be
2235 if Is_Controlled (Typ) then
2236 Init := Find_Prim_Op (Typ, Name_Initialize);
2240 (Present (Deep_Init)
2241 and then Chars (Deep_Init) = Call_Nam)
2244 and then Chars (Init) = Call_Nam);
2251 -- Start of processing for Find_Last_Init
2255 Body_Insert := Empty;
2257 -- Object renamings and objects associated with controlled
2258 -- function results do not have initialization calls.
2264 if Is_Concurrent_Type (Typ) then
2265 Utyp := Corresponding_Record_Type (Typ);
2270 -- The init procedures are arranged as follows:
2272 -- Object : Controlled_Type;
2273 -- Controlled_TypeIP (Object);
2274 -- [[Deep_]Initialize (Object);]
2276 -- where the user-defined initialize may be optional or may appear
2277 -- inside a block when abort deferral is needed.
2279 Nod_1 := Next (Decl);
2280 if Present (Nod_1) then
2281 Nod_2 := Next (Nod_1);
2283 -- The statement following an object declaration is always a
2284 -- call to the type init proc.
2289 -- Optional user-defined init or deep init processing
2291 if Present (Nod_2) then
2293 -- The statement following the type init proc may be a block
2294 -- statement in cases where abort deferral is required.
2296 if Nkind (Nod_2) = N_Block_Statement then
2298 HSS : constant Node_Id :=
2299 Handled_Statement_Sequence (Nod_2);
2304 and then Present (Statements (HSS))
2306 Stmt := First (Statements (HSS));
2308 -- Examine individual block statements and locate the
2309 -- call to [Deep_]Initialze.
2311 while Present (Stmt) loop
2312 if Is_Init_Call (Stmt, Utyp) then
2314 Body_Insert := Nod_2;
2324 elsif Is_Init_Call (Nod_2, Utyp) then
2330 -- Start of processing for Process_Object_Declaration
2333 Obj_Ref := New_Reference_To (Obj_Id, Loc);
2334 Obj_Typ := Base_Type (Etype (Obj_Id));
2336 -- Handle access types
2338 if Is_Access_Type (Obj_Typ) then
2339 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2340 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2343 Set_Etype (Obj_Ref, Obj_Typ);
2345 -- Set a new value for the state counter and insert the statement
2346 -- after the object declaration. Generate:
2348 -- Counter := <value>;
2351 Make_Assignment_Statement (Loc,
2352 Name => New_Reference_To (Counter_Id, Loc),
2353 Expression => Make_Integer_Literal (Loc, Counter_Val));
2355 -- Insert the counter after all initialization has been done. The
2356 -- place of insertion depends on the context. When dealing with a
2357 -- controlled function, the counter is inserted directly after the
2358 -- declaration because such objects lack init calls.
2360 Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
2362 Insert_After (Count_Ins, Inc_Decl);
2365 -- If the current declaration is the last in the list, the finalizer
2366 -- body needs to be inserted after the set counter statement for the
2367 -- current object declaration. This is complicated by the fact that
2368 -- the set counter statement may appear in abort deferred block. In
2369 -- that case, the proper insertion place is after the block.
2371 if No (Finalizer_Insert_Nod) then
2373 -- Insertion after an abort deffered block
2375 if Present (Body_Ins) then
2376 Finalizer_Insert_Nod := Body_Ins;
2378 Finalizer_Insert_Nod := Inc_Decl;
2382 -- Create the associated label with this object, generate:
2384 -- L<counter> : label;
2387 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2388 Set_Entity (Label_Id,
2389 Make_Defining_Identifier (Loc, Chars (Label_Id)));
2390 Label := Make_Label (Loc, Label_Id);
2392 Prepend_To (Finalizer_Decls,
2393 Make_Implicit_Label_Declaration (Loc,
2394 Defining_Identifier => Entity (Label_Id),
2395 Label_Construct => Label));
2397 -- Create the associated jump with this object, generate:
2399 -- when <counter> =>
2402 Prepend_To (Jump_Alts,
2403 Make_Case_Statement_Alternative (Loc,
2404 Discrete_Choices => New_List (
2405 Make_Integer_Literal (Loc, Counter_Val)),
2406 Statements => New_List (
2407 Make_Goto_Statement (Loc,
2408 Name => New_Reference_To (Entity (Label_Id), Loc)))));
2410 -- Insert the jump destination, generate:
2414 Append_To (Finalizer_Stmts, Label);
2416 -- Processing for simple protected objects. Such objects require
2417 -- manual finalization of their lock managers.
2419 if Is_Protected then
2420 Fin_Stmts := No_List;
2422 if Is_Simple_Protected_Type (Obj_Typ) then
2424 New_List (Cleanup_Protected_Object (Decl, Obj_Ref));
2426 elsif Has_Simple_Protected_Object (Obj_Typ) then
2427 if Is_Record_Type (Obj_Typ) then
2428 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2430 elsif Is_Array_Type (Obj_Typ) then
2431 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2437 -- System.Tasking.Protected_Objects.Finalize_Protection
2445 if Present (Fin_Stmts) then
2446 Append_To (Finalizer_Stmts,
2447 Make_Block_Statement (Loc,
2448 Handled_Statement_Sequence =>
2449 Make_Handled_Sequence_Of_Statements (Loc,
2450 Statements => Fin_Stmts,
2452 Exception_Handlers => New_List (
2453 Make_Exception_Handler (Loc,
2454 Exception_Choices => New_List (
2455 Make_Others_Choice (Loc)),
2457 Statements => New_List (
2458 Make_Null_Statement (Loc)))))));
2461 -- Processing for regular controlled objects
2465 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2467 -- begin -- Exception handlers allowed
2468 -- [Deep_]Finalize (Obj);
2471 -- when Id : others =>
2472 -- if not Raised then
2474 -- Save_Occurrence (E, Id);
2483 if Exceptions_OK then
2484 Fin_Stmts := New_List (
2485 Make_Block_Statement (Loc,
2486 Handled_Statement_Sequence =>
2487 Make_Handled_Sequence_Of_Statements (Loc,
2488 Statements => New_List (Fin_Call),
2490 Exception_Handlers => New_List (
2491 Build_Exception_Handler
2492 (Loc, E_Id, Raised_Id, For_Package)))));
2494 -- When exception handlers are prohibited, the finalization call
2495 -- appears unprotected. Any exception raised during finalization
2496 -- will bypass the circuitry which ensures the cleanup of all
2497 -- remaining objects.
2500 Fin_Stmts := New_List (Fin_Call);
2503 -- If we are dealing with a return object of a build-in-place
2504 -- function, generate the following cleanup statements:
2506 -- if BIPallocfrom > Secondary_Stack'Pos then
2508 -- type Ptr_Typ is access Obj_Typ;
2509 -- for Ptr_Typ'Storage_Pool use
2510 -- Base_Pool (BIPcollection.all).all;
2513 -- Free (Ptr_Typ (Temp));
2517 -- The generated code effectively detaches the temporary from the
2518 -- caller finalization chain and deallocates the object. This is
2519 -- disabled on .NET/JVM because pools are not supported.
2521 -- H505-021 This needs to be revisited on .NET/JVM
2523 if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2525 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2527 if Is_Build_In_Place_Function (Func_Id)
2528 and then Needs_BIP_Collection (Func_Id)
2530 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2535 -- Return objects use a flag to aid their potential finalization
2536 -- then the enclosing function fails to return properly. Generate:
2539 -- <object finalization statements>
2542 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2543 and then Is_Return_Object (Obj_Id)
2544 and then Present (Return_Flag (Obj_Id))
2546 Fin_Stmts := New_List (
2547 Make_If_Statement (Loc,
2551 New_Reference_To (Return_Flag (Obj_Id), Loc)),
2553 Then_Statements => Fin_Stmts));
2557 Append_List_To (Finalizer_Stmts, Fin_Stmts);
2559 -- Since the declarations are examined in reverse, the state counter
2560 -- must be decremented in order to keep with the true position of
2563 Counter_Val := Counter_Val - 1;
2564 end Process_Object_Declaration;
2566 -- Start of processing for Build_Finalizer
2571 -- Step 1: Extract all lists which may contain controlled objects
2573 if For_Package_Spec then
2574 Decls := Visible_Declarations (Specification (N));
2575 Priv_Decls := Private_Declarations (Specification (N));
2577 -- Retrieve the package spec id
2579 Spec_Id := Defining_Unit_Name (Specification (N));
2581 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2582 Spec_Id := Defining_Identifier (Spec_Id);
2585 -- Accept statement, block, entry body, package body, protected body,
2586 -- subprogram body or task body.
2589 Decls := Declarations (N);
2590 HSS := Handled_Statement_Sequence (N);
2592 if Present (HSS) then
2593 if Present (Statements (HSS)) then
2594 Stmts := Statements (HSS);
2597 if Present (At_End_Proc (HSS)) then
2598 Prev_At_End := At_End_Proc (HSS);
2602 -- Retrieve the package spec id for package bodies
2604 if For_Package_Body then
2605 Spec_Id := Corresponding_Spec (N);
2609 -- Do not process nested packages since those are handled by the
2610 -- enclosing scope's finalizer. Do not process non-expanded package
2611 -- instantiations since those will be re-analyzed and re-expanded.
2615 (not Is_Library_Level_Entity (Spec_Id)
2617 -- Nested packages are considered to be library level entities,
2618 -- but do not need to be processed separately. True library level
2619 -- packages have a scope value of 1.
2621 or else Scope_Depth_Value (Spec_Id) /= Uint_1
2622 or else (Is_Generic_Instance (Spec_Id)
2623 and then Package_Instantiation (Spec_Id) /= N))
2628 -- Step 2: Object [pre]processing
2632 -- Preprocess the visible declarations now in order to obtain the
2633 -- correct number of controlled object by the time the private
2634 -- declarations are processed.
2636 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2638 -- From all the possible contexts, only package specifications may
2639 -- have private declarations.
2641 if For_Package_Spec then
2642 Process_Declarations
2643 (Priv_Decls, Preprocess => True, Top_Level => True);
2645 -- The preprocessing has determined that the context has objects
2646 -- that need finalization actions. Private declarations are
2647 -- processed first in order to preserve possible dependencies
2648 -- between public and private objects.
2650 if Has_Ctrl_Objs then
2652 Process_Declarations (Priv_Decls);
2656 -- Process the public declarations
2658 if Has_Ctrl_Objs then
2660 Process_Declarations (Decls);
2666 -- Preprocess both declarations and statements
2668 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2669 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
2671 -- At this point it is known that N has controlled objects. Ensure
2672 -- that N has a declarative list since the finalizer spec will be
2675 if Has_Ctrl_Objs and then No (Decls) then
2676 Set_Declarations (N, New_List);
2677 Decls := Declarations (N);
2678 Spec_Decls := Decls;
2681 -- The current context may lack controlled objects, but require some
2682 -- other form of completion (task termination for instance). In such
2683 -- cases, the finalizer must be created and carry the additional
2686 if Acts_As_Clean or else Has_Ctrl_Objs then
2690 if Has_Ctrl_Objs then
2691 Process_Declarations (Stmts);
2692 Process_Declarations (Decls);
2696 -- Step 3: Finalizer creation
2698 if Acts_As_Clean or else Has_Ctrl_Objs then
2701 end Build_Finalizer;
2703 --------------------------
2704 -- Build_Finalizer_Call --
2705 --------------------------
2707 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
2708 Loc : constant Source_Ptr := Sloc (N);
2709 HSS : Node_Id := Handled_Statement_Sequence (N);
2711 Is_Prot_Body : constant Boolean :=
2712 Nkind (N) = N_Subprogram_Body
2713 and then Is_Protected_Subprogram_Body (N);
2714 -- Determine whether N denotes the protected version of a subprogram
2715 -- which belongs to a protected type.
2718 -- The At_End handler should have been assimilated by the finalizer
2720 pragma Assert (No (At_End_Proc (HSS)));
2722 -- If the construct to be cleaned up is a protected subprogram body, the
2723 -- finalizer call needs to be associated with the block which wraps the
2724 -- unprotected version of the subprogram. The following illustrates this
2727 -- procedure Prot_SubpP is
2728 -- procedure finalizer is
2730 -- Service_Entries (Prot_Obj);
2737 -- Prot_SubpN (Prot_Obj);
2743 if Is_Prot_Body then
2744 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
2746 -- An At_End handler and regular exception handlers cannot coexist in
2747 -- the same statement sequence. Wrap the original statements in a block.
2749 elsif Present (Exception_Handlers (HSS)) then
2751 End_Lab : constant Node_Id := End_Label (HSS);
2756 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
2758 Set_Handled_Statement_Sequence (N,
2759 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
2761 HSS := Handled_Statement_Sequence (N);
2762 Set_End_Label (HSS, End_Lab);
2766 Set_At_End_Proc (HSS, New_Reference_To (Fin_Id, Loc));
2768 Analyze (At_End_Proc (HSS));
2769 Expand_At_End_Handler (HSS, Empty);
2770 end Build_Finalizer_Call;
2772 ---------------------
2773 -- Build_Late_Proc --
2774 ---------------------
2776 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
2778 for Final_Prim in Name_Of'Range loop
2779 if Name_Of (Final_Prim) = Nam then
2782 (Prim => Final_Prim,
2784 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
2787 end Build_Late_Proc;
2789 -------------------------------
2790 -- Build_Object_Declarations --
2791 -------------------------------
2793 function Build_Object_Declarations
2795 Abort_Id : Entity_Id;
2797 Raised_Id : Entity_Id) return List_Id
2804 if Restriction_Active (No_Exception_Propagation) then
2808 pragma Assert (Present (Abort_Id));
2809 pragma Assert (Present (E_Id));
2810 pragma Assert (Present (Raised_Id));
2814 -- In certain scenarios, finalization can be triggered by an abort. If
2815 -- the finalization itself fails and raises an exception, the resulting
2816 -- Program_Error must be supressed and replaced by an abort signal. In
2817 -- order to detect this scenario, save the state of entry into the
2818 -- finalization code.
2820 if Abort_Allowed then
2822 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'E');
2826 -- Temp : constant Exception_Occurrence_Access :=
2827 -- Get_Current_Excep.all;
2830 Make_Object_Declaration (Loc,
2831 Defining_Identifier => Temp_Id,
2832 Constant_Present => True,
2833 Object_Definition =>
2834 New_Reference_To (RTE (RE_Exception_Occurrence_Access), Loc),
2836 Make_Function_Call (Loc,
2838 Make_Explicit_Dereference (Loc,
2841 (RTE (RE_Get_Current_Excep), Loc)))));
2845 -- and then Exception_Identity (Temp.all) =
2846 -- Standard'Abort_Signal'Identity;
2852 Left_Opnd => New_Reference_To (Temp_Id, Loc),
2853 Right_Opnd => Make_Null (Loc)),
2858 Make_Function_Call (Loc,
2860 New_Reference_To (RTE (RE_Exception_Identity), Loc),
2861 Parameter_Associations => New_List (
2862 Make_Explicit_Dereference (Loc,
2863 Prefix => New_Reference_To (Temp_Id, Loc)))),
2866 Make_Attribute_Reference (Loc,
2868 New_Reference_To (Stand.Abort_Signal, Loc),
2869 Attribute_Name => Name_Identity)));
2875 A_Expr := New_Reference_To (Standard_False, Loc);
2879 -- Abort_Id : constant Boolean := <A_Expr>;
2882 Make_Object_Declaration (Loc,
2883 Defining_Identifier => Abort_Id,
2884 Constant_Present => True,
2885 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
2886 Expression => A_Expr));
2889 -- E_Id : Exception_Occurrence;
2892 Make_Object_Declaration (Loc,
2893 Defining_Identifier => E_Id,
2894 Object_Definition =>
2895 New_Reference_To (RTE (RE_Exception_Occurrence), Loc));
2896 Set_No_Initialization (E_Decl);
2898 Append_To (Result, E_Decl);
2901 -- Raised_Id : Boolean := False;
2904 Make_Object_Declaration (Loc,
2905 Defining_Identifier => Raised_Id,
2906 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
2907 Expression => New_Reference_To (Standard_False, Loc)));
2910 end Build_Object_Declarations;
2912 ---------------------------
2913 -- Build_Raise_Statement --
2914 ---------------------------
2916 function Build_Raise_Statement
2918 Abort_Id : Entity_Id;
2920 Raised_Id : Entity_Id) return Node_Id
2923 Proc_Id : Entity_Id;
2926 -- The default parameter is the local exception occurrence
2928 Params := New_List (New_Reference_To (E_Id, Loc));
2932 if VM_Target /= No_VM then
2933 Proc_Id := RTE (RE_Reraise_Occurrence);
2935 -- Standard run-time library, this case handles finalization exceptions
2936 -- raised during an abort.
2938 elsif RTE_Available (RE_Raise_From_Controlled_Operation) then
2939 Proc_Id := RTE (RE_Raise_From_Controlled_Operation);
2940 Append_To (Params, New_Reference_To (Abort_Id, Loc));
2942 -- Restricted runtime: exception messages are not supported and hence
2943 -- Raise_From_Controlled_Operation is not supported.
2946 Proc_Id := RTE (RE_Reraise_Occurrence);
2950 -- if Raised_Id then
2951 -- <Proc_Id> (<Params>);
2955 Make_If_Statement (Loc,
2956 Condition => New_Reference_To (Raised_Id, Loc),
2957 Then_Statements => New_List (
2958 Make_Procedure_Call_Statement (Loc,
2959 Name => New_Reference_To (Proc_Id, Loc),
2960 Parameter_Associations => Params)));
2961 end Build_Raise_Statement;
2963 -----------------------------
2964 -- Build_Record_Deep_Procs --
2965 -----------------------------
2967 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
2971 (Prim => Initialize_Case,
2973 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
2975 if not Is_Immutably_Limited_Type (Typ) then
2978 (Prim => Adjust_Case,
2980 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
2985 (Prim => Finalize_Case,
2987 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
2989 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
2990 -- .NET do not support address arithmetic and unchecked conversions.
2992 if VM_Target = No_VM then
2995 (Prim => Address_Case,
2997 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
2999 end Build_Record_Deep_Procs;
3005 function Cleanup_Array
3008 Typ : Entity_Id) return List_Id
3010 Loc : constant Source_Ptr := Sloc (N);
3011 Index_List : constant List_Id := New_List;
3013 function Free_Component return List_Id;
3014 -- Generate the code to finalize the task or protected subcomponents
3015 -- of a single component of the array.
3017 function Free_One_Dimension (Dim : Int) return List_Id;
3018 -- Generate a loop over one dimension of the array
3020 --------------------
3021 -- Free_Component --
3022 --------------------
3024 function Free_Component return List_Id is
3025 Stmts : List_Id := New_List;
3027 C_Typ : constant Entity_Id := Component_Type (Typ);
3030 -- Component type is known to contain tasks or protected objects
3033 Make_Indexed_Component (Loc,
3034 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3035 Expressions => Index_List);
3037 Set_Etype (Tsk, C_Typ);
3039 if Is_Task_Type (C_Typ) then
3040 Append_To (Stmts, Cleanup_Task (N, Tsk));
3042 elsif Is_Simple_Protected_Type (C_Typ) then
3043 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3045 elsif Is_Record_Type (C_Typ) then
3046 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3048 elsif Is_Array_Type (C_Typ) then
3049 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3055 ------------------------
3056 -- Free_One_Dimension --
3057 ------------------------
3059 function Free_One_Dimension (Dim : Int) return List_Id is
3063 if Dim > Number_Dimensions (Typ) then
3064 return Free_Component;
3066 -- Here we generate the required loop
3069 Index := Make_Temporary (Loc, 'J');
3070 Append (New_Reference_To (Index, Loc), Index_List);
3073 Make_Implicit_Loop_Statement (N,
3074 Identifier => Empty,
3076 Make_Iteration_Scheme (Loc,
3077 Loop_Parameter_Specification =>
3078 Make_Loop_Parameter_Specification (Loc,
3079 Defining_Identifier => Index,
3080 Discrete_Subtype_Definition =>
3081 Make_Attribute_Reference (Loc,
3082 Prefix => Duplicate_Subexpr (Obj),
3083 Attribute_Name => Name_Range,
3084 Expressions => New_List (
3085 Make_Integer_Literal (Loc, Dim))))),
3086 Statements => Free_One_Dimension (Dim + 1)));
3088 end Free_One_Dimension;
3090 -- Start of processing for Cleanup_Array
3093 return Free_One_Dimension (1);
3096 --------------------
3097 -- Cleanup_Record --
3098 --------------------
3100 function Cleanup_Record
3103 Typ : Entity_Id) return List_Id
3105 Loc : constant Source_Ptr := Sloc (N);
3108 Stmts : constant List_Id := New_List;
3109 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3112 if Has_Discriminants (U_Typ)
3113 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3115 Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3118 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3120 -- For now, do not attempt to free a component that may appear in a
3121 -- variant, and instead issue a warning. Doing this "properly" would
3122 -- require building a case statement and would be quite a mess. Note
3123 -- that the RM only requires that free "work" for the case of a task
3124 -- access value, so already we go way beyond this in that we deal
3125 -- with the array case and non-discriminated record cases.
3128 ("task/protected object in variant record will not be freed?", N);
3129 return New_List (Make_Null_Statement (Loc));
3132 Comp := First_Component (Typ);
3133 while Present (Comp) loop
3134 if Has_Task (Etype (Comp))
3135 or else Has_Simple_Protected_Object (Etype (Comp))
3138 Make_Selected_Component (Loc,
3139 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3140 Selector_Name => New_Occurrence_Of (Comp, Loc));
3141 Set_Etype (Tsk, Etype (Comp));
3143 if Is_Task_Type (Etype (Comp)) then
3144 Append_To (Stmts, Cleanup_Task (N, Tsk));
3146 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3147 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3149 elsif Is_Record_Type (Etype (Comp)) then
3151 -- Recurse, by generating the prefix of the argument to
3152 -- the eventual cleanup call.
3154 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3156 elsif Is_Array_Type (Etype (Comp)) then
3157 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3161 Next_Component (Comp);
3167 ------------------------------
3168 -- Cleanup_Protected_Object --
3169 ------------------------------
3171 function Cleanup_Protected_Object
3173 Ref : Node_Id) return Node_Id
3175 Loc : constant Source_Ptr := Sloc (N);
3178 -- For restricted run-time libraries (Ravenscar), tasks are
3179 -- non-terminating, and protected objects can only appear at library
3180 -- level, so we do not want finalization of protected objects.
3182 if Restricted_Profile then
3187 Make_Procedure_Call_Statement (Loc,
3189 New_Reference_To (RTE (RE_Finalize_Protection), Loc),
3190 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3192 end Cleanup_Protected_Object;
3198 function Cleanup_Task
3200 Ref : Node_Id) return Node_Id
3202 Loc : constant Source_Ptr := Sloc (N);
3205 -- For restricted run-time libraries (Ravenscar), tasks are
3206 -- non-terminating and they can only appear at library level, so we do
3207 -- not want finalization of task objects.
3209 if Restricted_Profile then
3214 Make_Procedure_Call_Statement (Loc,
3216 New_Reference_To (RTE (RE_Free_Task), Loc),
3217 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3221 ------------------------------
3222 -- Check_Visibly_Controlled --
3223 ------------------------------
3225 procedure Check_Visibly_Controlled
3226 (Prim : Final_Primitives;
3228 E : in out Entity_Id;
3229 Cref : in out Node_Id)
3231 Parent_Type : Entity_Id;
3235 if Is_Derived_Type (Typ)
3236 and then Comes_From_Source (E)
3237 and then not Present (Overridden_Operation (E))
3239 -- We know that the explicit operation on the type does not override
3240 -- the inherited operation of the parent, and that the derivation
3241 -- is from a private type that is not visibly controlled.
3243 Parent_Type := Etype (Typ);
3244 Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3246 if Present (Op) then
3249 -- Wrap the object to be initialized into the proper
3250 -- unchecked conversion, to be compatible with the operation
3253 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3254 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3256 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3260 end Check_Visibly_Controlled;
3262 -------------------------------
3263 -- CW_Or_Has_Controlled_Part --
3264 -------------------------------
3266 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3268 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3269 end CW_Or_Has_Controlled_Part;
3275 function Convert_View
3278 Ind : Pos := 1) return Node_Id
3280 Fent : Entity_Id := First_Entity (Proc);
3285 for J in 2 .. Ind loop
3289 Ftyp := Etype (Fent);
3291 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3292 Atyp := Entity (Subtype_Mark (Arg));
3294 Atyp := Etype (Arg);
3297 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3298 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3301 and then Present (Atyp)
3302 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3303 and then Base_Type (Underlying_Type (Atyp)) =
3304 Base_Type (Underlying_Type (Ftyp))
3306 return Unchecked_Convert_To (Ftyp, Arg);
3308 -- If the argument is already a conversion, as generated by
3309 -- Make_Init_Call, set the target type to the type of the formal
3310 -- directly, to avoid spurious typing problems.
3312 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3313 and then not Is_Class_Wide_Type (Atyp)
3315 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3316 Set_Etype (Arg, Ftyp);
3324 ------------------------
3325 -- Enclosing_Function --
3326 ------------------------
3328 function Enclosing_Function (E : Entity_Id) return Entity_Id is
3329 Func_Id : Entity_Id;
3333 while Present (Func_Id)
3334 and then Func_Id /= Standard_Standard
3336 if Ekind (Func_Id) = E_Function then
3340 Func_Id := Scope (Func_Id);
3344 end Enclosing_Function;
3346 -------------------------------
3347 -- Establish_Transient_Scope --
3348 -------------------------------
3350 -- This procedure is called each time a transient block has to be inserted
3351 -- that is to say for each call to a function with unconstrained or tagged
3352 -- result. It creates a new scope on the stack scope in order to enclose
3353 -- all transient variables generated
3355 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3356 Loc : constant Source_Ptr := Sloc (N);
3357 Wrap_Node : Node_Id;
3360 -- Nothing to do for virtual machines where memory is GCed
3362 if VM_Target /= No_VM then
3366 -- Do not create a transient scope if we are already inside one
3368 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3369 if Scope_Stack.Table (S).Is_Transient then
3371 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3376 -- If we have encountered Standard there are no enclosing
3377 -- transient scopes.
3379 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3385 Wrap_Node := Find_Node_To_Be_Wrapped (N);
3387 -- Case of no wrap node, false alert, no transient scope needed
3389 if No (Wrap_Node) then
3392 -- If the node to wrap is an iteration_scheme, the expression is
3393 -- one of the bounds, and the expansion will make an explicit
3394 -- declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3395 -- so do not apply any transformations here.
3397 elsif Nkind (Wrap_Node) = N_Iteration_Scheme then
3401 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3402 Set_Scope_Is_Transient;
3405 Set_Uses_Sec_Stack (Current_Scope);
3406 Check_Restriction (No_Secondary_Stack, N);
3409 Set_Etype (Current_Scope, Standard_Void_Type);
3410 Set_Node_To_Be_Wrapped (Wrap_Node);
3412 if Debug_Flag_W then
3413 Write_Str (" <Transient>");
3417 end Establish_Transient_Scope;
3419 ----------------------------
3420 -- Expand_Cleanup_Actions --
3421 ----------------------------
3423 procedure Expand_Cleanup_Actions (N : Node_Id) is
3424 Scop : constant Entity_Id := Current_Scope;
3426 Is_Asynchronous_Call : constant Boolean :=
3427 Nkind (N) = N_Block_Statement
3428 and then Is_Asynchronous_Call_Block (N);
3429 Is_Master : constant Boolean :=
3430 Nkind (N) /= N_Entry_Body
3431 and then Is_Task_Master (N);
3432 Is_Protected_Body : constant Boolean :=
3433 Nkind (N) = N_Subprogram_Body
3434 and then Is_Protected_Subprogram_Body (N);
3435 Is_Task_Allocation : constant Boolean :=
3436 Nkind (N) = N_Block_Statement
3437 and then Is_Task_Allocation_Block (N);
3438 Is_Task_Body : constant Boolean :=
3439 Nkind (Original_Node (N)) = N_Task_Body;
3440 Needs_Sec_Stack_Mark : constant Boolean :=
3441 Uses_Sec_Stack (Scop)
3443 not Sec_Stack_Needed_For_Return (Scop)
3444 and then VM_Target = No_VM;
3446 Actions_Required : constant Boolean :=
3447 Has_Controlled_Objects (N)
3448 or else Is_Asynchronous_Call
3450 or else Is_Protected_Body
3451 or else Is_Task_Allocation
3452 or else Is_Task_Body
3453 or else Needs_Sec_Stack_Mark;
3455 HSS : Node_Id := Handled_Statement_Sequence (N);
3458 procedure Wrap_HSS_In_Block;
3459 -- Move HSS inside a new block along with the original exception
3460 -- handlers. Make the newly generated block the sole statement of HSS.
3462 -----------------------
3463 -- Wrap_HSS_In_Block --
3464 -----------------------
3466 procedure Wrap_HSS_In_Block is
3471 -- Preserve end label to provide proper cross-reference information
3473 End_Lab := End_Label (HSS);
3475 Make_Block_Statement (Loc,
3476 Handled_Statement_Sequence => HSS);
3478 Set_Handled_Statement_Sequence (N,
3479 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3480 HSS := Handled_Statement_Sequence (N);
3482 Set_First_Real_Statement (HSS, Block);
3483 Set_End_Label (HSS, End_Lab);
3485 -- Comment needed here, see RH for 1.306 ???
3487 if Nkind (N) = N_Subprogram_Body then
3488 Set_Has_Nested_Block_With_Handler (Scop);
3490 end Wrap_HSS_In_Block;
3492 -- Start of processing for Expand_Cleanup_Actions
3495 -- The current construct does not need any form of servicing
3497 if not Actions_Required then
3500 -- If the current node is a rewritten task body and the descriptors have
3501 -- not been delayed (due to some nested instantiations), do not generate
3502 -- redundant cleanup actions.
3505 and then Nkind (N) = N_Subprogram_Body
3506 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3512 Decls : List_Id := Declarations (N);
3514 Mark : Entity_Id := Empty;
3515 New_Decls : List_Id;
3519 -- If we are generating expanded code for debugging purposes, use the
3520 -- Sloc of the point of insertion for the cleanup code. The Sloc will
3521 -- be updated subsequently to reference the proper line in .dg files.
3522 -- If we are not debugging generated code, use No_Location instead,
3523 -- so that no debug information is generated for the cleanup code.
3524 -- This makes the behavior of the NEXT command in GDB monotonic, and
3525 -- makes the placement of breakpoints more accurate.
3527 if Debug_Generated_Code then
3533 -- Set polling off. The finalization and cleanup code is executed
3534 -- with aborts deferred.
3536 Old_Poll := Polling_Required;
3537 Polling_Required := False;
3539 -- A task activation call has already been built for a task
3540 -- allocation block.
3542 if not Is_Task_Allocation then
3543 Build_Task_Activation_Call (N);
3547 Establish_Task_Master (N);
3550 New_Decls := New_List;
3552 -- If secondary stack is in use, generate:
3554 -- Mnn : constant Mark_Id := SS_Mark;
3556 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3557 -- secondary stack is never used on a VM.
3559 if Needs_Sec_Stack_Mark then
3560 Mark := Make_Temporary (Loc, 'M');
3562 Append_To (New_Decls,
3563 Make_Object_Declaration (Loc,
3564 Defining_Identifier => Mark,
3565 Object_Definition =>
3566 New_Reference_To (RTE (RE_Mark_Id), Loc),
3568 Make_Function_Call (Loc,
3569 Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
3571 Set_Uses_Sec_Stack (Scop, False);
3574 -- If exception handlers are present, wrap the sequence of statements
3575 -- in a block since it is not possible to have exception handlers and
3576 -- an At_End handler in the same construct.
3578 if Present (Exception_Handlers (HSS)) then
3581 -- Ensure that the First_Real_Statement field is set
3583 elsif No (First_Real_Statement (HSS)) then
3584 Set_First_Real_Statement (HSS, First (Statements (HSS)));
3587 -- Do not move the Activation_Chain declaration in the context of
3588 -- task allocation blocks. Task allocation blocks use _chain in their
3589 -- cleanup handlers and gigi complains if it is declared in the
3590 -- sequence of statements of the scope that declares the handler.
3592 if Is_Task_Allocation then
3594 Chain : constant Entity_Id := Activation_Chain_Entity (N);
3598 Decl := First (Decls);
3599 while Nkind (Decl) /= N_Object_Declaration
3600 or else Defining_Identifier (Decl) /= Chain
3604 -- A task allocation block should always include a _chain
3607 pragma Assert (Present (Decl));
3611 Prepend_To (New_Decls, Decl);
3615 -- Ensure the presence of a declaration list in order to successfully
3616 -- append all original statements to it.
3619 Set_Declarations (N, New_List);
3620 Decls := Declarations (N);
3623 -- Move the declarations into the sequence of statements in order to
3624 -- have them protected by the At_End handler. It may seem weird to
3625 -- put declarations in the sequence of statement but in fact nothing
3626 -- forbids that at the tree level.
3628 Append_List_To (Decls, Statements (HSS));
3629 Set_Statements (HSS, Decls);
3631 -- Reset the Sloc of the handled statement sequence to properly
3632 -- reflect the new initial "statement" in the sequence.
3634 Set_Sloc (HSS, Sloc (First (Decls)));
3636 -- The declarations of finalizer spec and auxiliary variables replace
3637 -- the old declarations that have been moved inward.
3639 Set_Declarations (N, New_Decls);
3640 Analyze_Declarations (New_Decls);
3642 -- Generate finalization calls for all controlled objects appearing
3643 -- in the statements of N. Add context specific cleanup for various
3648 Clean_Stmts => Build_Cleanup_Statements (N),
3650 Top_Decls => New_Decls,
3651 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
3655 if Present (Fin_Id) then
3656 Build_Finalizer_Call (N, Fin_Id);
3659 -- Restore saved polling mode
3661 Polling_Required := Old_Poll;
3663 end Expand_Cleanup_Actions;
3665 ---------------------------
3666 -- Expand_N_Package_Body --
3667 ---------------------------
3669 -- Add call to Activate_Tasks if body is an activator (actual processing
3670 -- is in chapter 9).
3672 -- Generate subprogram descriptor for elaboration routine
3674 -- Encode entity names in package body
3676 procedure Expand_N_Package_Body (N : Node_Id) is
3677 Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
3681 -- This is done only for non-generic packages
3683 if Ekind (Spec_Ent) = E_Package then
3684 Push_Scope (Corresponding_Spec (N));
3686 -- Build dispatch tables of library level tagged types
3688 if Is_Library_Level_Entity (Spec_Ent) then
3689 if Tagged_Type_Expansion then
3690 Build_Static_Dispatch_Tables (N);
3692 -- In VM targets there is no need to build dispatch tables but
3693 -- we must generate the corresponding Type Specific Data record.
3695 elsif Unit (Cunit (Main_Unit)) = N then
3697 -- If the runtime package Ada_Tags has not been loaded then
3698 -- this package does not have tagged type declarations and
3699 -- there is no need to search for tagged types to generate
3702 if RTU_Loaded (Ada_Tags) then
3708 Build_Task_Activation_Call (N);
3712 Set_Elaboration_Flag (N, Corresponding_Spec (N));
3713 Set_In_Package_Body (Spec_Ent, False);
3715 -- Set to encode entity names in package body before gigi is called
3717 Qualify_Entity_Names (N);
3719 if Ekind (Spec_Ent) /= E_Generic_Package then
3722 Clean_Stmts => No_List,
3724 Top_Decls => No_List,
3725 Defer_Abort => False,
3728 if Present (Fin_Id) then
3730 Body_Ent : Node_Id := Defining_Unit_Name (N);
3733 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
3734 Body_Ent := Defining_Identifier (Body_Ent);
3737 Set_Finalizer (Body_Ent, Fin_Id);
3741 end Expand_N_Package_Body;
3743 ----------------------------------
3744 -- Expand_N_Package_Declaration --
3745 ----------------------------------
3747 -- Add call to Activate_Tasks if there are tasks declared and the package
3748 -- has no body. Note that in Ada83, this may result in premature activation
3749 -- of some tasks, given that we cannot tell whether a body will eventually
3752 procedure Expand_N_Package_Declaration (N : Node_Id) is
3753 Id : constant Entity_Id := Defining_Entity (N);
3754 Spec : constant Node_Id := Specification (N);
3758 No_Body : Boolean := False;
3759 -- True in the case of a package declaration that is a compilation
3760 -- unit and for which no associated body will be compiled in this
3764 -- Case of a package declaration other than a compilation unit
3766 if Nkind (Parent (N)) /= N_Compilation_Unit then
3769 -- Case of a compilation unit that does not require a body
3771 elsif not Body_Required (Parent (N))
3772 and then not Unit_Requires_Body (Id)
3776 -- Special case of generating calling stubs for a remote call interface
3777 -- package: even though the package declaration requires one, the body
3778 -- won't be processed in this compilation (so any stubs for RACWs
3779 -- declared in the package must be generated here, along with the spec).
3781 elsif Parent (N) = Cunit (Main_Unit)
3782 and then Is_Remote_Call_Interface (Id)
3783 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
3788 -- For a package declaration that implies no associated body, generate
3789 -- task activation call and RACW supporting bodies now (since we won't
3790 -- have a specific separate compilation unit for that).
3795 if Has_RACW (Id) then
3797 -- Generate RACW subprogram bodies
3799 Decls := Private_Declarations (Spec);
3802 Decls := Visible_Declarations (Spec);
3807 Set_Visible_Declarations (Spec, Decls);
3810 Append_RACW_Bodies (Decls, Id);
3811 Analyze_List (Decls);
3814 if Present (Activation_Chain_Entity (N)) then
3816 -- Generate task activation call as last step of elaboration
3818 Build_Task_Activation_Call (N);
3824 -- Build dispatch tables of library level tagged types
3826 if Is_Compilation_Unit (Id)
3827 or else (Is_Generic_Instance (Id)
3828 and then Is_Library_Level_Entity (Id))
3830 if Tagged_Type_Expansion then
3831 Build_Static_Dispatch_Tables (N);
3833 -- In VM targets there is no need to build dispatch tables, but we
3834 -- must generate the corresponding Type Specific Data record.
3836 elsif Unit (Cunit (Main_Unit)) = N then
3838 -- If the runtime package Ada_Tags has not been loaded then
3839 -- this package does not have tagged types and there is no need
3840 -- to search for tagged types to generate their TSDs.
3842 if RTU_Loaded (Ada_Tags) then
3844 -- Enter the scope of the package because the new declarations
3845 -- are appended at the end of the package and must be analyzed
3850 if Is_Generic_Instance (Main_Unit_Entity) then
3851 if Package_Instantiation (Main_Unit_Entity) = N then
3864 -- Note: it is not necessary to worry about generating a subprogram
3865 -- descriptor, since the only way to get exception handlers into a
3866 -- package spec is to include instantiations, and that would cause
3867 -- generation of subprogram descriptors to be delayed in any case.
3869 -- Set to encode entity names in package spec before gigi is called
3871 Qualify_Entity_Names (N);
3873 if Ekind (Id) /= E_Generic_Package then
3876 Clean_Stmts => No_List,
3878 Top_Decls => No_List,
3879 Defer_Abort => False,
3882 Set_Finalizer (Id, Fin_Id);
3884 end Expand_N_Package_Declaration;
3886 -----------------------------
3887 -- Find_Node_To_Be_Wrapped --
3888 -----------------------------
3890 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
3892 The_Parent : Node_Id;
3898 pragma Assert (P /= Empty);
3899 The_Parent := Parent (P);
3901 case Nkind (The_Parent) is
3903 -- Simple statement can be wrapped
3908 -- Usually assignments are good candidate for wrapping
3909 -- except when they have been generated as part of a
3910 -- controlled aggregate where the wrapping should take
3911 -- place more globally.
3913 when N_Assignment_Statement =>
3914 if No_Ctrl_Actions (The_Parent) then
3920 -- An entry call statement is a special case if it occurs in
3921 -- the context of a Timed_Entry_Call. In this case we wrap
3922 -- the entire timed entry call.
3924 when N_Entry_Call_Statement |
3925 N_Procedure_Call_Statement =>
3926 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
3927 and then Nkind_In (Parent (Parent (The_Parent)),
3929 N_Conditional_Entry_Call)
3931 return Parent (Parent (The_Parent));
3936 -- Object declarations are also a boundary for the transient scope
3937 -- even if they are not really wrapped
3938 -- (see Wrap_Transient_Declaration)
3940 when N_Object_Declaration |
3941 N_Object_Renaming_Declaration |
3942 N_Subtype_Declaration =>
3945 -- The expression itself is to be wrapped if its parent is a
3946 -- compound statement or any other statement where the expression
3947 -- is known to be scalar
3949 when N_Accept_Alternative |
3950 N_Attribute_Definition_Clause |
3953 N_Delay_Alternative |
3954 N_Delay_Until_Statement |
3955 N_Delay_Relative_Statement |
3956 N_Discriminant_Association |
3958 N_Entry_Body_Formal_Part |
3961 N_Iteration_Scheme |
3962 N_Terminate_Alternative =>
3965 when N_Attribute_Reference =>
3967 if Is_Procedure_Attribute_Name
3968 (Attribute_Name (The_Parent))
3973 -- A raise statement can be wrapped. This will arise when the
3974 -- expression in a raise_with_expression uses the secondary
3975 -- stack, for example.
3977 when N_Raise_Statement =>
3980 -- If the expression is within the iteration scheme of a loop,
3981 -- we must create a declaration for it, followed by an assignment
3982 -- in order to have a usable statement to wrap.
3984 when N_Loop_Parameter_Specification =>
3985 return Parent (The_Parent);
3987 -- The following nodes contains "dummy calls" which don't
3988 -- need to be wrapped.
3990 when N_Parameter_Specification |
3991 N_Discriminant_Specification |
3992 N_Component_Declaration =>
3995 -- The return statement is not to be wrapped when the function
3996 -- itself needs wrapping at the outer-level
3998 when N_Simple_Return_Statement =>
4000 Applies_To : constant Entity_Id :=
4002 (Return_Statement_Entity (The_Parent));
4003 Return_Type : constant Entity_Id := Etype (Applies_To);
4005 if Requires_Transient_Scope (Return_Type) then
4012 -- If we leave a scope without having been able to find a node to
4013 -- wrap, something is going wrong but this can happen in error
4014 -- situation that are not detected yet (such as a dynamic string
4015 -- in a pragma export)
4017 when N_Subprogram_Body |
4018 N_Package_Declaration |
4020 N_Block_Statement =>
4023 -- otherwise continue the search
4029 end Find_Node_To_Be_Wrapped;
4031 ----------------------------------
4032 -- Has_New_Controlled_Component --
4033 ----------------------------------
4035 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4039 if not Is_Tagged_Type (E) then
4040 return Has_Controlled_Component (E);
4041 elsif not Is_Derived_Type (E) then
4042 return Has_Controlled_Component (E);
4045 Comp := First_Component (E);
4046 while Present (Comp) loop
4047 if Chars (Comp) = Name_uParent then
4050 elsif Scope (Original_Record_Component (Comp)) = E
4051 and then Needs_Finalization (Etype (Comp))
4056 Next_Component (Comp);
4060 end Has_New_Controlled_Component;
4062 ---------------------------------
4063 -- Has_Simple_Protected_Object --
4064 ---------------------------------
4066 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4068 if Has_Task (T) then
4071 elsif Is_Simple_Protected_Type (T) then
4074 elsif Is_Array_Type (T) then
4075 return Has_Simple_Protected_Object (Component_Type (T));
4077 elsif Is_Record_Type (T) then
4082 Comp := First_Component (T);
4083 while Present (Comp) loop
4084 if Has_Simple_Protected_Object (Etype (Comp)) then
4088 Next_Component (Comp);
4097 end Has_Simple_Protected_Object;
4099 ------------------------------------
4100 -- Insert_Actions_In_Scope_Around --
4101 ------------------------------------
4103 procedure Insert_Actions_In_Scope_Around (N : Node_Id) is
4104 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
4105 After : List_Id renames SE.Actions_To_Be_Wrapped_After;
4106 Before : List_Id renames SE.Actions_To_Be_Wrapped_Before;
4108 procedure Process_Transient_Objects
4109 (First_Object : Node_Id;
4110 Last_Object : Node_Id;
4111 Related_Node : Node_Id);
4112 -- First_Object and Last_Object define a list which contains potential
4113 -- controlled transient objects. Finalization flags are inserted before
4114 -- First_Object and finalization calls are inserted after Last_Object.
4115 -- Related_Node is the node for which transient objects have been
4118 -------------------------------
4119 -- Process_Transient_Objects --
4120 -------------------------------
4122 procedure Process_Transient_Objects
4123 (First_Object : Node_Id;
4124 Last_Object : Node_Id;
4125 Related_Node : Node_Id)
4127 Abort_Id : Entity_Id;
4128 Built : Boolean := False;
4131 Fin_Block : Node_Id;
4132 Last_Fin : Node_Id := Empty;
4136 Obj_Typ : Entity_Id;
4137 Raised_Id : Entity_Id;
4141 -- Examine all objects in the list First_Object .. Last_Object
4143 Stmt := First_Object;
4144 while Present (Stmt) loop
4145 if Nkind (Stmt) = N_Object_Declaration
4146 and then Analyzed (Stmt)
4147 and then Is_Finalizable_Transient (Stmt, N)
4149 -- Do not process the node to be wrapped since it will be
4150 -- handled by the enclosing finalizer.
4152 and then Stmt /= Related_Node
4155 Obj_Id := Defining_Identifier (Stmt);
4156 Obj_Typ := Base_Type (Etype (Obj_Id));
4159 Set_Is_Processed_Transient (Obj_Id);
4161 -- Handle access types
4163 if Is_Access_Type (Desig) then
4164 Desig := Available_View (Designated_Type (Desig));
4167 -- Create the necessary entities and declarations the first
4171 Abort_Id := Make_Temporary (Loc, 'A');
4172 E_Id := Make_Temporary (Loc, 'E');
4173 Raised_Id := Make_Temporary (Loc, 'R');
4175 Insert_List_Before_And_Analyze (First_Object,
4176 Build_Object_Declarations
4177 (Loc, Abort_Id, E_Id, Raised_Id));
4184 -- [Deep_]Finalize (Obj_Ref);
4191 -- (Enn, Get_Current_Excep.all.all);
4195 Obj_Ref := New_Reference_To (Obj_Id, Loc);
4197 if Is_Access_Type (Obj_Typ) then
4198 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4202 Make_Block_Statement (Loc,
4203 Handled_Statement_Sequence =>
4204 Make_Handled_Sequence_Of_Statements (Loc,
4205 Statements => New_List (
4207 (Obj_Ref => Obj_Ref,
4210 Exception_Handlers => New_List (
4211 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4212 Insert_After_And_Analyze (Last_Object, Fin_Block);
4214 -- The raise statement must be inserted after all the
4215 -- finalization blocks.
4217 if No (Last_Fin) then
4218 Last_Fin := Fin_Block;
4221 -- When the associated node is an array object, the expander may
4222 -- sometimes generate a loop and create transient objects inside
4225 elsif Nkind (Stmt) = N_Loop_Statement then
4226 Process_Transient_Objects
4227 (First_Object => First (Statements (Stmt)),
4228 Last_Object => Last (Statements (Stmt)),
4229 Related_Node => Related_Node);
4231 -- Terminate the scan after the last object has been processed
4233 elsif Stmt = Last_Object then
4242 -- Raise_From_Controlled_Operation (E, Abort);
4246 and then Present (Last_Fin)
4248 Insert_After_And_Analyze (Last_Fin,
4249 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4251 end Process_Transient_Objects;
4253 -- Start of processing for Insert_Actions_In_Scope_Around
4256 if No (Before) and then No (After) then
4261 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
4262 First_Obj : Node_Id;
4267 -- If the node to be wrapped is the trigger of an asynchronous
4268 -- select, it is not part of a statement list. The actions must be
4269 -- inserted before the select itself, which is part of some list of
4270 -- statements. Note that the triggering alternative includes the
4271 -- triggering statement and an optional statement list. If the node
4272 -- to be wrapped is part of that list, the normal insertion applies.
4274 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4275 and then not Is_List_Member (Node_To_Wrap)
4277 Target := Parent (Parent (Node_To_Wrap));
4282 First_Obj := Target;
4285 -- Add all actions associated with a transient scope into the main
4286 -- tree. There are several scenarios here:
4288 -- +--- Before ----+ +----- After ---+
4289 -- 1) First_Obj ....... Target ........ Last_Obj
4291 -- 2) First_Obj ....... Target
4293 -- 3) Target ........ Last_Obj
4295 if Present (Before) then
4297 -- Flag declarations are inserted before the first object
4299 First_Obj := First (Before);
4301 Insert_List_Before (Target, Before);
4304 if Present (After) then
4306 -- Finalization calls are inserted after the last object
4308 Last_Obj := Last (After);
4310 Insert_List_After (Target, After);
4313 -- Check for transient controlled objects associated with Target and
4314 -- generate the appropriate finalization actions for them.
4316 Process_Transient_Objects
4317 (First_Object => First_Obj,
4318 Last_Object => Last_Obj,
4319 Related_Node => Target);
4321 -- Reset the action lists
4323 if Present (Before) then
4327 if Present (After) then
4331 end Insert_Actions_In_Scope_Around;
4333 ------------------------------
4334 -- Is_Simple_Protected_Type --
4335 ------------------------------
4337 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
4340 Is_Protected_Type (T)
4341 and then not Has_Entries (T)
4342 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
4343 end Is_Simple_Protected_Type;
4345 -----------------------
4346 -- Make_Adjust_Call --
4347 -----------------------
4349 function Make_Adjust_Call
4352 For_Parent : Boolean := False) return Node_Id
4354 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4355 Adj_Id : Entity_Id := Empty;
4356 Ref : Node_Id := Obj_Ref;
4360 -- Recover the proper type which contains Deep_Adjust
4362 if Is_Class_Wide_Type (Typ) then
4363 Utyp := Root_Type (Typ);
4368 Utyp := Underlying_Type (Base_Type (Utyp));
4369 Set_Assignment_OK (Ref);
4371 -- Deal with non-tagged derivation of private views
4373 if Is_Untagged_Derivation (Typ) then
4374 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
4375 Ref := Unchecked_Convert_To (Utyp, Ref);
4376 Set_Assignment_OK (Ref);
4379 -- When dealing with the completion of a private type, use the base
4382 if Utyp /= Base_Type (Utyp) then
4383 pragma Assert (Is_Private_Type (Typ));
4385 Utyp := Base_Type (Utyp);
4386 Ref := Unchecked_Convert_To (Utyp, Ref);
4389 -- Select the appropriate version of adjust
4392 if Has_Controlled_Component (Utyp) then
4393 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4396 -- For types that are both controlled and have controlled components,
4397 -- generate a call to Deep_Adjust.
4399 elsif Is_Controlled (Utyp)
4400 and then Has_Controlled_Component (Utyp)
4402 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4404 -- For types that are not controlled themselves, but contain controlled
4405 -- components or can be extended by types with controlled components,
4406 -- create a call to Deep_Adjust.
4408 elsif Is_Class_Wide_Type (Typ)
4409 or else Has_Controlled_Component (Utyp)
4411 if Is_Tagged_Type (Utyp) then
4412 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4414 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
4417 -- For types that are derived from Controlled and do not have controlled
4418 -- components, build a call to Adjust.
4421 Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
4424 if Present (Adj_Id) then
4426 -- If the object is unanalyzed, set its expected type for use in
4427 -- Convert_View in case an additional conversion is needed.
4430 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
4432 Set_Etype (Ref, Typ);
4435 -- The object reference may need another conversion depending on the
4436 -- type of the formal and that of the actual.
4438 if not Is_Class_Wide_Type (Typ) then
4439 Ref := Convert_View (Adj_Id, Ref);
4442 return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent);
4446 end Make_Adjust_Call;
4448 ----------------------
4449 -- Make_Attach_Call --
4450 ----------------------
4452 function Make_Attach_Call
4454 Ptr_Typ : Entity_Id) return Node_Id
4456 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4459 Make_Procedure_Call_Statement (Loc,
4461 New_Reference_To (RTE (RE_Attach), Loc),
4462 Parameter_Associations => New_List (
4463 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
4464 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4465 end Make_Attach_Call;
4467 ----------------------
4468 -- Make_Detach_Call --
4469 ----------------------
4471 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
4472 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4476 Make_Procedure_Call_Statement (Loc,
4478 New_Reference_To (RTE (RE_Detach), Loc),
4479 Parameter_Associations => New_List (
4480 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4481 end Make_Detach_Call;
4489 Proc_Id : Entity_Id;
4491 For_Parent : Boolean := False) return Node_Id
4493 Params : constant List_Id := New_List (Param);
4496 -- When creating a call to Deep_Finalize for a _parent field of a
4497 -- derived type, disable the invocation of the nested Finalize by giving
4498 -- the corresponding flag a False value.
4501 Append_To (Params, New_Reference_To (Standard_False, Loc));
4505 Make_Procedure_Call_Statement (Loc,
4506 Name => New_Reference_To (Proc_Id, Loc),
4507 Parameter_Associations => Params);
4510 --------------------------
4511 -- Make_Deep_Array_Body --
4512 --------------------------
4514 function Make_Deep_Array_Body
4515 (Prim : Final_Primitives;
4516 Typ : Entity_Id) return List_Id
4518 function Build_Adjust_Or_Finalize_Statements
4519 (Typ : Entity_Id) return List_Id;
4520 -- Create the statements necessary to adjust or finalize an array of
4521 -- controlled elements. Generate:
4524 -- Temp : constant Exception_Occurrence_Access :=
4525 -- Get_Current_Excep.all;
4526 -- Abort : constant Boolean :=
4528 -- and then Exception_Identity (Temp_Id.all) =
4529 -- Standard'Abort_Signal'Identity;
4531 -- Abort : constant Boolean := False; -- no abort
4533 -- E : Exception_Occurrence;
4534 -- Raised : Boolean := False;
4537 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
4538 -- ^-- in the finalization case
4540 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
4542 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
4546 -- if not Raised then
4548 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4556 -- Raise_From_Controlled_Operation (E, Abort);
4560 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
4561 -- Create the statements necessary to initialize an array of controlled
4562 -- elements. Include a mechanism to carry out partial finalization if an
4563 -- exception occurs. Generate:
4566 -- Counter : Integer := 0;
4569 -- for J1 in V'Range (1) loop
4571 -- for JN in V'Range (N) loop
4573 -- [Deep_]Initialize (V (J1, ..., JN));
4575 -- Counter := Counter + 1;
4580 -- Temp : constant Exception_Occurrence_Access :=
4581 -- Get_Current_Excep.all;
4582 -- Abort : constant Boolean :=
4584 -- and then Exception_Identity (Temp_Id.all) =
4585 -- Standard'Abort_Signal'Identity;
4587 -- Abort : constant Boolean := False; -- no abort
4588 -- E : Exception_Occurence;
4589 -- Raised : Boolean := False;
4596 -- V'Length (N) - Counter;
4598 -- for F1 in reverse V'Range (1) loop
4600 -- for FN in reverse V'Range (N) loop
4601 -- if Counter > 0 then
4602 -- Counter := Counter - 1;
4605 -- [Deep_]Finalize (V (F1, ..., FN));
4609 -- if not Raised then
4611 -- Save_Occurrence (E,
4612 -- Get_Current_Excep.all.all);
4622 -- Raise_From_Controlled_Operation (E, Abort);
4631 function New_References_To
4633 Loc : Source_Ptr) return List_Id;
4634 -- Given a list of defining identifiers, return a list of references to
4635 -- the original identifiers, in the same order as they appear.
4637 -----------------------------------------
4638 -- Build_Adjust_Or_Finalize_Statements --
4639 -----------------------------------------
4641 function Build_Adjust_Or_Finalize_Statements
4642 (Typ : Entity_Id) return List_Id
4644 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4645 Index_List : constant List_Id := New_List;
4646 Loc : constant Source_Ptr := Sloc (Typ);
4647 Num_Dims : constant Int := Number_Dimensions (Typ);
4648 Abort_Id : Entity_Id := Empty;
4651 Core_Loop : Node_Id;
4653 E_Id : Entity_Id := Empty;
4655 Loop_Id : Entity_Id;
4656 Raised_Id : Entity_Id := Empty;
4659 Exceptions_OK : constant Boolean :=
4660 not Restriction_Active (No_Exception_Propagation);
4662 procedure Build_Indices;
4663 -- Generate the indices used in the dimension loops
4669 procedure Build_Indices is
4671 -- Generate the following identifiers:
4672 -- Jnn - for initialization
4674 for Dim in 1 .. Num_Dims loop
4675 Append_To (Index_List,
4676 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4680 -- Start of processing for Build_Adjust_Or_Finalize_Statements
4685 if Exceptions_OK then
4686 Abort_Id := Make_Temporary (Loc, 'A');
4687 E_Id := Make_Temporary (Loc, 'E');
4688 Raised_Id := Make_Temporary (Loc, 'R');
4692 Make_Indexed_Component (Loc,
4693 Prefix => Make_Identifier (Loc, Name_V),
4694 Expressions => New_References_To (Index_List, Loc));
4695 Set_Etype (Comp_Ref, Comp_Typ);
4698 -- [Deep_]Adjust (V (J1, ..., JN))
4700 if Prim = Adjust_Case then
4701 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4704 -- [Deep_]Finalize (V (J1, ..., JN))
4706 else pragma Assert (Prim = Finalize_Case);
4707 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4710 -- Generate the block which houses the adjust or finalize call:
4712 -- <adjust or finalize call>; -- No_Exception_Propagation
4714 -- begin -- Exception handlers allowed
4715 -- <adjust or finalize call>
4719 -- if not Raised then
4721 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4725 if Exceptions_OK then
4727 Make_Block_Statement (Loc,
4728 Handled_Statement_Sequence =>
4729 Make_Handled_Sequence_Of_Statements (Loc,
4730 Statements => New_List (Call),
4731 Exception_Handlers => New_List (
4732 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4737 -- Generate the dimension loops starting from the innermost one
4739 -- for Jnn in [reverse] V'Range (Dim) loop
4743 J := Last (Index_List);
4745 while Present (J) and then Dim > 0 loop
4751 Make_Loop_Statement (Loc,
4753 Make_Iteration_Scheme (Loc,
4754 Loop_Parameter_Specification =>
4755 Make_Loop_Parameter_Specification (Loc,
4756 Defining_Identifier => Loop_Id,
4757 Discrete_Subtype_Definition =>
4758 Make_Attribute_Reference (Loc,
4759 Prefix => Make_Identifier (Loc, Name_V),
4760 Attribute_Name => Name_Range,
4761 Expressions => New_List (
4762 Make_Integer_Literal (Loc, Dim))),
4764 Reverse_Present => Prim = Finalize_Case)),
4766 Statements => New_List (Core_Loop),
4767 End_Label => Empty);
4772 -- Generate the block which contains the core loop, the declarations
4773 -- of the abort flag, the exception occurrence, the raised flag and
4774 -- the conditional raise:
4777 -- Abort : constant Boolean :=
4778 -- Exception_Occurrence (Get_Current_Excep.all.all) =
4779 -- Standard'Abort_Signal'Identity;
4781 -- Abort : constant Boolean := False; -- no abort
4783 -- E : Exception_Occurrence;
4784 -- Raised : Boolean := False;
4789 -- if Raised then -- Expection handlers allowed
4790 -- Raise_From_Controlled_Operation (E, Abort);
4794 Stmts := New_List (Core_Loop);
4796 if Exceptions_OK then
4798 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4803 Make_Block_Statement (Loc,
4805 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
4806 Handled_Statement_Sequence =>
4807 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4808 end Build_Adjust_Or_Finalize_Statements;
4810 ---------------------------------
4811 -- Build_Initialize_Statements --
4812 ---------------------------------
4814 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
4815 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4816 Final_List : constant List_Id := New_List;
4817 Index_List : constant List_Id := New_List;
4818 Loc : constant Source_Ptr := Sloc (Typ);
4819 Num_Dims : constant Int := Number_Dimensions (Typ);
4820 Abort_Id : Entity_Id;
4821 Counter_Id : Entity_Id;
4823 E_Id : Entity_Id := Empty;
4826 Final_Block : Node_Id;
4827 Final_Loop : Node_Id;
4828 Init_Loop : Node_Id;
4831 Raised_Id : Entity_Id := Empty;
4834 Exceptions_OK : constant Boolean :=
4835 not Restriction_Active (No_Exception_Propagation);
4837 function Build_Counter_Assignment return Node_Id;
4838 -- Generate the following assignment:
4839 -- Counter := V'Length (1) *
4841 -- V'Length (N) - Counter;
4843 function Build_Finalization_Call return Node_Id;
4844 -- Generate a deep finalization call for an array element
4846 procedure Build_Indices;
4847 -- Generate the initialization and finalization indices used in the
4850 function Build_Initialization_Call return Node_Id;
4851 -- Generate a deep initialization call for an array element
4853 ------------------------------
4854 -- Build_Counter_Assignment --
4855 ------------------------------
4857 function Build_Counter_Assignment return Node_Id is
4862 -- Start from the first dimension and generate:
4867 Make_Attribute_Reference (Loc,
4868 Prefix => Make_Identifier (Loc, Name_V),
4869 Attribute_Name => Name_Length,
4870 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
4872 -- Process the rest of the dimensions, generate:
4873 -- Expr * V'Length (N)
4876 while Dim <= Num_Dims loop
4878 Make_Op_Multiply (Loc,
4881 Make_Attribute_Reference (Loc,
4882 Prefix => Make_Identifier (Loc, Name_V),
4883 Attribute_Name => Name_Length,
4884 Expressions => New_List (
4885 Make_Integer_Literal (Loc, Dim))));
4891 -- Counter := Expr - Counter;
4894 Make_Assignment_Statement (Loc,
4895 Name => New_Reference_To (Counter_Id, Loc),
4897 Make_Op_Subtract (Loc,
4899 Right_Opnd => New_Reference_To (Counter_Id, Loc)));
4900 end Build_Counter_Assignment;
4902 -----------------------------
4903 -- Build_Finalization_Call --
4904 -----------------------------
4906 function Build_Finalization_Call return Node_Id is
4907 Comp_Ref : constant Node_Id :=
4908 Make_Indexed_Component (Loc,
4909 Prefix => Make_Identifier (Loc, Name_V),
4910 Expressions => New_References_To (Final_List, Loc));
4913 Set_Etype (Comp_Ref, Comp_Typ);
4916 -- [Deep_]Finalize (V);
4918 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4919 end Build_Finalization_Call;
4925 procedure Build_Indices is
4927 -- Generate the following identifiers:
4928 -- Jnn - for initialization
4929 -- Fnn - for finalization
4931 for Dim in 1 .. Num_Dims loop
4932 Append_To (Index_List,
4933 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4935 Append_To (Final_List,
4936 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
4940 -------------------------------
4941 -- Build_Initialization_Call --
4942 -------------------------------
4944 function Build_Initialization_Call return Node_Id is
4945 Comp_Ref : constant Node_Id :=
4946 Make_Indexed_Component (Loc,
4947 Prefix => Make_Identifier (Loc, Name_V),
4948 Expressions => New_References_To (Index_List, Loc));
4951 Set_Etype (Comp_Ref, Comp_Typ);
4954 -- [Deep_]Initialize (V (J1, ..., JN));
4956 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4957 end Build_Initialization_Call;
4959 -- Start of processing for Build_Initialize_Statements
4964 Counter_Id := Make_Temporary (Loc, 'C');
4966 if Exceptions_OK then
4967 Abort_Id := Make_Temporary (Loc, 'A');
4968 E_Id := Make_Temporary (Loc, 'E');
4969 Raised_Id := Make_Temporary (Loc, 'R');
4972 -- Generate the block which houses the finalization call, the index
4973 -- guard and the handler which triggers Program_Error later on.
4975 -- if Counter > 0 then
4976 -- Counter := Counter - 1;
4978 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
4980 -- begin -- Exceptions allowed
4981 -- [Deep_]Finalize (V (F1, ..., FN));
4984 -- if not Raised then
4986 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4991 if Exceptions_OK then
4993 Make_Block_Statement (Loc,
4994 Handled_Statement_Sequence =>
4995 Make_Handled_Sequence_Of_Statements (Loc,
4996 Statements => New_List (Build_Finalization_Call),
4997 Exception_Handlers => New_List (
4998 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5000 Fin_Stmt := Build_Finalization_Call;
5003 -- This is the core of the loop, the dimension iterators are added
5004 -- one by one in reverse.
5007 Make_If_Statement (Loc,
5010 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5011 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5013 Then_Statements => New_List (
5014 Make_Assignment_Statement (Loc,
5015 Name => New_Reference_To (Counter_Id, Loc),
5017 Make_Op_Subtract (Loc,
5018 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5019 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5021 Else_Statements => New_List (Fin_Stmt));
5023 -- Generate all finalization loops starting from the innermost
5026 -- for Fnn in reverse V'Range (Dim) loop
5030 F := Last (Final_List);
5032 while Present (F) and then Dim > 0 loop
5038 Make_Loop_Statement (Loc,
5040 Make_Iteration_Scheme (Loc,
5041 Loop_Parameter_Specification =>
5042 Make_Loop_Parameter_Specification (Loc,
5043 Defining_Identifier => Loop_Id,
5044 Discrete_Subtype_Definition =>
5045 Make_Attribute_Reference (Loc,
5046 Prefix => Make_Identifier (Loc, Name_V),
5047 Attribute_Name => Name_Range,
5048 Expressions => New_List (
5049 Make_Integer_Literal (Loc, Dim))),
5051 Reverse_Present => True)),
5053 Statements => New_List (Final_Loop),
5054 End_Label => Empty);
5059 -- Generate the block which contains the finalization loops, the
5060 -- declarations of the abort flag, the exception occurrence, the
5061 -- raised flag and the conditional raise.
5064 -- Abort : constant Boolean :=
5065 -- Exception_Occurrence (Get_Current_Excep.all.all) =
5066 -- Standard'Abort_Signal'Identity;
5068 -- Abort : constant Boolean := False; -- no abort
5070 -- E : Exception_Occurrence;
5071 -- Raised : Boolean := False;
5077 -- V'Length (N) - Counter;
5081 -- if Raised then -- Exception handlers allowed
5082 -- Raise_From_Controlled_Operation (E, Abort);
5085 -- raise; -- Exception handlers allowed
5088 Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5090 if Exceptions_OK then
5092 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
5093 Append_To (Stmts, Make_Raise_Statement (Loc));
5097 Make_Block_Statement (Loc,
5099 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
5100 Handled_Statement_Sequence =>
5101 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5103 -- Generate the block which contains the initialization call and
5104 -- the partial finalization code.
5107 -- [Deep_]Initialize (V (J1, ..., JN));
5109 -- Counter := Counter + 1;
5113 -- <finalization code>
5117 Make_Block_Statement (Loc,
5118 Handled_Statement_Sequence =>
5119 Make_Handled_Sequence_Of_Statements (Loc,
5120 Statements => New_List (Build_Initialization_Call),
5121 Exception_Handlers => New_List (
5122 Make_Exception_Handler (Loc,
5123 Exception_Choices => New_List (Make_Others_Choice (Loc)),
5124 Statements => New_List (Final_Block)))));
5126 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5127 Make_Assignment_Statement (Loc,
5128 Name => New_Reference_To (Counter_Id, Loc),
5131 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5132 Right_Opnd => Make_Integer_Literal (Loc, 1))));
5134 -- Generate all initialization loops starting from the innermost
5137 -- for Jnn in V'Range (Dim) loop
5141 J := Last (Index_List);
5143 while Present (J) and then Dim > 0 loop
5149 Make_Loop_Statement (Loc,
5151 Make_Iteration_Scheme (Loc,
5152 Loop_Parameter_Specification =>
5153 Make_Loop_Parameter_Specification (Loc,
5154 Defining_Identifier => Loop_Id,
5155 Discrete_Subtype_Definition =>
5156 Make_Attribute_Reference (Loc,
5157 Prefix => Make_Identifier (Loc, Name_V),
5158 Attribute_Name => Name_Range,
5159 Expressions => New_List (
5160 Make_Integer_Literal (Loc, Dim))))),
5162 Statements => New_List (Init_Loop),
5163 End_Label => Empty);
5168 -- Generate the block which contains the counter variable and the
5169 -- initialization loops.
5172 -- Counter : Integer := 0;
5179 Make_Block_Statement (Loc,
5180 Declarations => New_List (
5181 Make_Object_Declaration (Loc,
5182 Defining_Identifier => Counter_Id,
5183 Object_Definition =>
5184 New_Reference_To (Standard_Integer, Loc),
5185 Expression => Make_Integer_Literal (Loc, 0))),
5187 Handled_Statement_Sequence =>
5188 Make_Handled_Sequence_Of_Statements (Loc,
5189 Statements => New_List (Init_Loop))));
5190 end Build_Initialize_Statements;
5192 -----------------------
5193 -- New_References_To --
5194 -----------------------
5196 function New_References_To
5198 Loc : Source_Ptr) return List_Id
5200 Refs : constant List_Id := New_List;
5205 while Present (Id) loop
5206 Append_To (Refs, New_Reference_To (Id, Loc));
5211 end New_References_To;
5213 -- Start of processing for Make_Deep_Array_Body
5217 when Address_Case =>
5218 return Make_Finalize_Address_Stmts (Typ);
5222 return Build_Adjust_Or_Finalize_Statements (Typ);
5224 when Initialize_Case =>
5225 return Build_Initialize_Statements (Typ);
5227 end Make_Deep_Array_Body;
5229 --------------------
5230 -- Make_Deep_Proc --
5231 --------------------
5233 function Make_Deep_Proc
5234 (Prim : Final_Primitives;
5236 Stmts : List_Id) return Entity_Id
5238 Loc : constant Source_Ptr := Sloc (Typ);
5240 Proc_Id : Entity_Id;
5243 -- Create the object formal, generate:
5244 -- V : System.Address
5246 if Prim = Address_Case then
5247 Formals := New_List (
5248 Make_Parameter_Specification (Loc,
5249 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5250 Parameter_Type => New_Reference_To (RTE (RE_Address), Loc)));
5257 Formals := New_List (
5258 Make_Parameter_Specification (Loc,
5259 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5261 Out_Present => True,
5262 Parameter_Type => New_Reference_To (Typ, Loc)));
5264 -- F : Boolean := True
5266 if Prim = Adjust_Case
5267 or else Prim = Finalize_Case
5270 Make_Parameter_Specification (Loc,
5271 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5273 New_Reference_To (Standard_Boolean, Loc),
5275 New_Reference_To (Standard_True, Loc)));
5280 Make_Defining_Identifier (Loc,
5281 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5284 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5287 -- exception -- Finalize and Adjust cases only
5288 -- raise Program_Error;
5289 -- end Deep_Initialize / Adjust / Finalize;
5293 -- procedure Finalize_Address (V : System.Address) is
5296 -- end Finalize_Address;
5299 Make_Subprogram_Body (Loc,
5301 Make_Procedure_Specification (Loc,
5302 Defining_Unit_Name => Proc_Id,
5303 Parameter_Specifications => Formals),
5305 Declarations => Empty_List,
5307 Handled_Statement_Sequence =>
5308 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
5313 ---------------------------
5314 -- Make_Deep_Record_Body --
5315 ---------------------------
5317 function Make_Deep_Record_Body
5318 (Prim : Final_Primitives;
5320 Is_Local : Boolean := False) return List_Id
5322 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
5323 -- Build the statements necessary to adjust a record type. The type may
5324 -- have discriminants and contain variant parts. Generate:
5327 -- Root_Controlled (V).Finalized := False;
5330 -- [Deep_]Adjust (V.Comp_1);
5332 -- when Id : others =>
5333 -- if not Raised then
5335 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5340 -- [Deep_]Adjust (V.Comp_N);
5342 -- when Id : others =>
5343 -- if not Raised then
5345 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5350 -- Deep_Adjust (V._parent, False); -- If applicable
5352 -- when Id : others =>
5353 -- if not Raised then
5355 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5361 -- Adjust (V); -- If applicable
5364 -- if not Raised then
5366 -- Save_Occurence (E, Get_Current_Excep.all.all);
5372 -- Raise_From_Controlled_Object (E, Abort);
5376 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
5377 -- Build the statements necessary to finalize a record type. The type
5378 -- may have discriminants and contain variant parts. Generate:
5381 -- Temp : constant Exception_Occurrence_Access :=
5382 -- Get_Current_Excep.all;
5383 -- Abort : constant Boolean :=
5385 -- and then Exception_Identity (Temp_Id.all) =
5386 -- Standard'Abort_Signal'Identity;
5388 -- Abort : constant Boolean := False; -- no abort
5389 -- E : Exception_Occurence;
5390 -- Raised : Boolean := False;
5393 -- if Root_Controlled (V).Finalized then
5399 -- Finalize (V); -- If applicable
5402 -- if not Raised then
5404 -- Save_Occurence (E, Get_Current_Excep.all.all);
5409 -- case Variant_1 is
5411 -- case State_Counter_N => -- If Is_Local is enabled
5421 -- <<LN>> -- If Is_Local is enabled
5423 -- [Deep_]Finalize (V.Comp_N);
5426 -- if not Raised then
5428 -- Save_Occurence (E, Get_Current_Excep.all.all);
5434 -- [Deep_]Finalize (V.Comp_1);
5437 -- if not Raised then
5439 -- Save_Occurence (E, Get_Current_Excep.all.all);
5445 -- case State_Counter_1 => -- If Is_Local is enabled
5451 -- Deep_Finalize (V._parent, False); -- If applicable
5453 -- when Id : others =>
5454 -- if not Raised then
5456 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5460 -- Root_Controlled (V).Finalized := True;
5463 -- Raise_From_Controlled_Object (E, Abort);
5467 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
5468 -- Given a derived tagged type Typ, traverse all components, find field
5469 -- _parent and return its type.
5471 procedure Preprocess_Components
5473 Num_Comps : out Int;
5474 Has_POC : out Boolean);
5475 -- Examine all components in component list Comps, count all controlled
5476 -- components and determine whether at least one of them is per-object
5477 -- constrained. Component _parent is always skipped.
5479 -----------------------------
5480 -- Build_Adjust_Statements --
5481 -----------------------------
5483 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
5484 Loc : constant Source_Ptr := Sloc (Typ);
5485 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
5486 Abort_Id : Entity_Id := Empty;
5487 Bod_Stmts : List_Id;
5488 E_Id : Entity_Id := Empty;
5489 Raised_Id : Entity_Id := Empty;
5493 Exceptions_OK : constant Boolean :=
5494 not Restriction_Active (No_Exception_Propagation);
5496 function Process_Component_List_For_Adjust
5497 (Comps : Node_Id) return List_Id;
5498 -- Build all necessary adjust statements for a single component list
5500 ---------------------------------------
5501 -- Process_Component_List_For_Adjust --
5502 ---------------------------------------
5504 function Process_Component_List_For_Adjust
5505 (Comps : Node_Id) return List_Id
5507 Stmts : constant List_Id := New_List;
5509 Decl_Id : Entity_Id;
5510 Decl_Typ : Entity_Id;
5514 procedure Process_Component_For_Adjust (Decl : Node_Id);
5515 -- Process the declaration of a single controlled component
5517 ----------------------------------
5518 -- Process_Component_For_Adjust --
5519 ----------------------------------
5521 procedure Process_Component_For_Adjust (Decl : Node_Id) is
5522 Id : constant Entity_Id := Defining_Identifier (Decl);
5523 Typ : constant Entity_Id := Etype (Id);
5528 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
5530 -- begin -- Exception handlers allowed
5531 -- [Deep_]Adjust (V.Id);
5534 -- if not Raised then
5536 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5543 Make_Selected_Component (Loc,
5544 Prefix => Make_Identifier (Loc, Name_V),
5545 Selector_Name => Make_Identifier (Loc, Chars (Id))),
5548 if Exceptions_OK then
5550 Make_Block_Statement (Loc,
5551 Handled_Statement_Sequence =>
5552 Make_Handled_Sequence_Of_Statements (Loc,
5553 Statements => New_List (Adj_Stmt),
5554 Exception_Handlers => New_List (
5555 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5558 Append_To (Stmts, Adj_Stmt);
5559 end Process_Component_For_Adjust;
5561 -- Start of processing for Process_Component_List_For_Adjust
5564 -- Perform an initial check, determine the number of controlled
5565 -- components in the current list and whether at least one of them
5566 -- is per-object constrained.
5568 Preprocess_Components (Comps, Num_Comps, Has_POC);
5570 -- The processing in this routine is done in the following order:
5571 -- 1) Regular components
5572 -- 2) Per-object constrained components
5575 if Num_Comps > 0 then
5577 -- Process all regular components in order of declarations
5579 Decl := First_Non_Pragma (Component_Items (Comps));
5580 while Present (Decl) loop
5581 Decl_Id := Defining_Identifier (Decl);
5582 Decl_Typ := Etype (Decl_Id);
5584 -- Skip _parent as well as per-object constrained components
5586 if Chars (Decl_Id) /= Name_uParent
5587 and then Needs_Finalization (Decl_Typ)
5589 if Has_Access_Constraint (Decl_Id)
5590 and then No (Expression (Decl))
5594 Process_Component_For_Adjust (Decl);
5598 Next_Non_Pragma (Decl);
5601 -- Process all per-object constrained components in order of
5605 Decl := First_Non_Pragma (Component_Items (Comps));
5606 while Present (Decl) loop
5607 Decl_Id := Defining_Identifier (Decl);
5608 Decl_Typ := Etype (Decl_Id);
5612 if Chars (Decl_Id) /= Name_uParent
5613 and then Needs_Finalization (Decl_Typ)
5614 and then Has_Access_Constraint (Decl_Id)
5615 and then No (Expression (Decl))
5617 Process_Component_For_Adjust (Decl);
5620 Next_Non_Pragma (Decl);
5625 -- Process all variants, if any
5628 if Present (Variant_Part (Comps)) then
5630 Var_Alts : constant List_Id := New_List;
5634 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
5635 while Present (Var) loop
5638 -- when <discrete choices> =>
5639 -- <adjust statements>
5641 Append_To (Var_Alts,
5642 Make_Case_Statement_Alternative (Loc,
5644 New_Copy_List (Discrete_Choices (Var)),
5646 Process_Component_List_For_Adjust (
5647 Component_List (Var))));
5649 Next_Non_Pragma (Var);
5653 -- case V.<discriminant> is
5654 -- when <discrete choices 1> =>
5655 -- <adjust statements 1>
5657 -- when <discrete choices N> =>
5658 -- <adjust statements N>
5662 Make_Case_Statement (Loc,
5664 Make_Selected_Component (Loc,
5665 Prefix => Make_Identifier (Loc, Name_V),
5667 Make_Identifier (Loc,
5668 Chars => Chars (Name (Variant_Part (Comps))))),
5669 Alternatives => Var_Alts);
5673 -- Add the variant case statement to the list of statements
5675 if Present (Var_Case) then
5676 Append_To (Stmts, Var_Case);
5679 -- If the component list did not have any controlled components
5680 -- nor variants, return null.
5682 if Is_Empty_List (Stmts) then
5683 Append_To (Stmts, Make_Null_Statement (Loc));
5687 end Process_Component_List_For_Adjust;
5689 -- Start of processing for Build_Adjust_Statements
5692 if Exceptions_OK then
5693 Abort_Id := Make_Temporary (Loc, 'A');
5694 E_Id := Make_Temporary (Loc, 'E');
5695 Raised_Id := Make_Temporary (Loc, 'R');
5698 if Nkind (Typ_Def) = N_Derived_Type_Definition then
5699 Rec_Def := Record_Extension_Part (Typ_Def);
5704 -- Create an adjust sequence for all record components
5706 if Present (Component_List (Rec_Def)) then
5708 Process_Component_List_For_Adjust (Component_List (Rec_Def));
5711 -- A derived record type must adjust all inherited components. This
5712 -- action poses the following problem:
5714 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
5719 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
5721 -- Deep_Adjust (Obj._parent);
5726 -- Adjusting the derived type will invoke Adjust of the parent and
5727 -- then that of the derived type. This is undesirable because both
5728 -- routines may modify shared components. Only the Adjust of the
5729 -- derived type should be invoked.
5731 -- To prevent this double adjustment of shared components,
5732 -- Deep_Adjust uses a flag to control the invocation of Adjust:
5734 -- procedure Deep_Adjust
5735 -- (Obj : in out Some_Type;
5736 -- Flag : Boolean := True)
5744 -- When Deep_Adjust is invokes for field _parent, a value of False is
5745 -- provided for the flag:
5747 -- Deep_Adjust (Obj._parent, False);
5749 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
5751 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
5756 if Needs_Finalization (Par_Typ) then
5760 Make_Selected_Component (Loc,
5761 Prefix => Make_Identifier (Loc, Name_V),
5763 Make_Identifier (Loc, Name_uParent)),
5765 For_Parent => True);
5768 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
5770 -- begin -- Exceptions OK
5771 -- Deep_Adjust (V._parent, False);
5773 -- when Id : others =>
5774 -- if not Raised then
5776 -- Save_Occurrence (E,
5777 -- Get_Current_Excep.all.all);
5781 if Present (Call) then
5784 if Exceptions_OK then
5786 Make_Block_Statement (Loc,
5787 Handled_Statement_Sequence =>
5788 Make_Handled_Sequence_Of_Statements (Loc,
5789 Statements => New_List (Adj_Stmt),
5790 Exception_Handlers => New_List (
5791 Build_Exception_Handler
5792 (Loc, E_Id, Raised_Id))));
5795 Prepend_To (Bod_Stmts, Adj_Stmt);
5801 -- Adjust the object. This action must be performed last after all
5802 -- components have been adjusted.
5804 if Is_Controlled (Typ) then
5810 Proc := Find_Prim_Op (Typ, Name_Adjust);
5814 -- Adjust (V); -- No_Exception_Propagation
5816 -- begin -- Exception handlers allowed
5820 -- if not Raised then
5822 -- Save_Occurrence (E,
5823 -- Get_Current_Excep.all.all);
5828 if Present (Proc) then
5830 Make_Procedure_Call_Statement (Loc,
5831 Name => New_Reference_To (Proc, Loc),
5832 Parameter_Associations => New_List (
5833 Make_Identifier (Loc, Name_V)));
5835 if Exceptions_OK then
5837 Make_Block_Statement (Loc,
5838 Handled_Statement_Sequence =>
5839 Make_Handled_Sequence_Of_Statements (Loc,
5840 Statements => New_List (Adj_Stmt),
5841 Exception_Handlers => New_List (
5842 Build_Exception_Handler
5843 (Loc, E_Id, Raised_Id))));
5846 Append_To (Bod_Stmts,
5847 Make_If_Statement (Loc,
5848 Condition => Make_Identifier (Loc, Name_F),
5849 Then_Statements => New_List (Adj_Stmt)));
5854 -- At this point either all adjustment statements have been generated
5855 -- or the type is not controlled.
5857 if Is_Empty_List (Bod_Stmts) then
5858 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
5864 -- Abort : constant Boolean :=
5865 -- Exception_Occurrence (Get_Current_Excep.all.all) =
5866 -- Standard'Abort_Signal'Identity;
5868 -- Abort : constant Boolean := False; -- no abort
5870 -- E : Exception_Occurence;
5871 -- Raised : Boolean := False;
5874 -- Root_Controlled (V).Finalized := False;
5876 -- <adjust statements>
5879 -- Raise_From_Controlled_Operation (E, Abort);
5884 if Exceptions_OK then
5885 Append_To (Bod_Stmts,
5886 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
5891 Make_Block_Statement (Loc,
5893 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
5894 Handled_Statement_Sequence =>
5895 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
5897 end Build_Adjust_Statements;
5899 -------------------------------
5900 -- Build_Finalize_Statements --
5901 -------------------------------
5903 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
5904 Loc : constant Source_Ptr := Sloc (Typ);
5905 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
5906 Abort_Id : Entity_Id := Empty;
5907 Bod_Stmts : List_Id;
5909 E_Id : Entity_Id := Empty;
5910 Raised_Id : Entity_Id := Empty;
5914 Exceptions_OK : constant Boolean :=
5915 not Restriction_Active (No_Exception_Propagation);
5917 function Process_Component_List_For_Finalize
5918 (Comps : Node_Id) return List_Id;
5919 -- Build all necessary finalization statements for a single component
5920 -- list. The statements may include a jump circuitry if flag Is_Local
5923 -----------------------------------------
5924 -- Process_Component_List_For_Finalize --
5925 -----------------------------------------
5927 function Process_Component_List_For_Finalize
5928 (Comps : Node_Id) return List_Id
5931 Counter_Id : Entity_Id;
5933 Decl_Id : Entity_Id;
5934 Decl_Typ : Entity_Id;
5937 Jump_Block : Node_Id;
5939 Label_Id : Entity_Id;
5943 procedure Process_Component_For_Finalize
5948 -- Process the declaration of a single controlled component. If
5949 -- flag Is_Local is enabled, create the corresponding label and
5950 -- jump circuitry. Alts is the list of case alternatives, Decls
5951 -- is the top level declaration list where labels are declared
5952 -- and Stmts is the list of finalization actions.
5954 ------------------------------------
5955 -- Process_Component_For_Finalize --
5956 ------------------------------------
5958 procedure Process_Component_For_Finalize
5964 Id : constant Entity_Id := Defining_Identifier (Decl);
5965 Typ : constant Entity_Id := Etype (Id);
5972 Label_Id : Entity_Id;
5979 Make_Identifier (Loc,
5980 Chars => New_External_Name ('L', Num_Comps));
5981 Set_Entity (Label_Id,
5982 Make_Defining_Identifier (Loc, Chars (Label_Id)));
5983 Label := Make_Label (Loc, Label_Id);
5986 Make_Implicit_Label_Declaration (Loc,
5987 Defining_Identifier => Entity (Label_Id),
5988 Label_Construct => Label));
5995 Make_Case_Statement_Alternative (Loc,
5996 Discrete_Choices => New_List (
5997 Make_Integer_Literal (Loc, Num_Comps)),
5999 Statements => New_List (
6000 Make_Goto_Statement (Loc,
6002 New_Reference_To (Entity (Label_Id), Loc)))));
6007 Append_To (Stmts, Label);
6009 -- Decrease the number of components to be processed.
6010 -- This action yields a new Label_Id in future calls.
6012 Num_Comps := Num_Comps - 1;
6017 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6019 -- begin -- Exception handlers allowed
6020 -- [Deep_]Finalize (V.Id);
6023 -- if not Raised then
6025 -- Save_Occurrence (E,
6026 -- Get_Current_Excep.all.all);
6033 Make_Selected_Component (Loc,
6034 Prefix => Make_Identifier (Loc, Name_V),
6035 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6038 if not Restriction_Active (No_Exception_Propagation) then
6040 Make_Block_Statement (Loc,
6041 Handled_Statement_Sequence =>
6042 Make_Handled_Sequence_Of_Statements (Loc,
6043 Statements => New_List (Fin_Stmt),
6044 Exception_Handlers => New_List (
6045 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
6048 Append_To (Stmts, Fin_Stmt);
6049 end Process_Component_For_Finalize;
6051 -- Start of processing for Process_Component_List_For_Finalize
6054 -- Perform an initial check, look for controlled and per-object
6055 -- constrained components.
6057 Preprocess_Components (Comps, Num_Comps, Has_POC);
6059 -- Create a state counter to service the current component list.
6060 -- This step is performed before the variants are inspected in
6061 -- order to generate the same state counter names as those from
6062 -- Build_Initialize_Statements.
6067 Counter := Counter + 1;
6070 Make_Defining_Identifier (Loc,
6071 Chars => New_External_Name ('C', Counter));
6074 -- Process the component in the following order:
6076 -- 2) Per-object constrained components
6077 -- 3) Regular components
6079 -- Start with the variant parts
6082 if Present (Variant_Part (Comps)) then
6084 Var_Alts : constant List_Id := New_List;
6088 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6089 while Present (Var) loop
6092 -- when <discrete choices> =>
6093 -- <finalize statements>
6095 Append_To (Var_Alts,
6096 Make_Case_Statement_Alternative (Loc,
6098 New_Copy_List (Discrete_Choices (Var)),
6100 Process_Component_List_For_Finalize (
6101 Component_List (Var))));
6103 Next_Non_Pragma (Var);
6107 -- case V.<discriminant> is
6108 -- when <discrete choices 1> =>
6109 -- <finalize statements 1>
6111 -- when <discrete choices N> =>
6112 -- <finalize statements N>
6116 Make_Case_Statement (Loc,
6118 Make_Selected_Component (Loc,
6119 Prefix => Make_Identifier (Loc, Name_V),
6121 Make_Identifier (Loc,
6122 Chars => Chars (Name (Variant_Part (Comps))))),
6123 Alternatives => Var_Alts);
6127 -- The current component list does not have a single controlled
6128 -- component, however it may contain variants. Return the case
6129 -- statement for the variants or nothing.
6131 if Num_Comps = 0 then
6132 if Present (Var_Case) then
6133 return New_List (Var_Case);
6135 return New_List (Make_Null_Statement (Loc));
6139 -- Prepare all lists
6145 -- Process all per-object constrained components in reverse order
6148 Decl := Last_Non_Pragma (Component_Items (Comps));
6149 while Present (Decl) loop
6150 Decl_Id := Defining_Identifier (Decl);
6151 Decl_Typ := Etype (Decl_Id);
6155 if Chars (Decl_Id) /= Name_uParent
6156 and then Needs_Finalization (Decl_Typ)
6157 and then Has_Access_Constraint (Decl_Id)
6158 and then No (Expression (Decl))
6160 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6163 Prev_Non_Pragma (Decl);
6167 -- Process the rest of the components in reverse order
6169 Decl := Last_Non_Pragma (Component_Items (Comps));
6170 while Present (Decl) loop
6171 Decl_Id := Defining_Identifier (Decl);
6172 Decl_Typ := Etype (Decl_Id);
6176 if Chars (Decl_Id) /= Name_uParent
6177 and then Needs_Finalization (Decl_Typ)
6179 -- Skip per-object constrained components since they were
6180 -- handled in the above step.
6182 if Has_Access_Constraint (Decl_Id)
6183 and then No (Expression (Decl))
6187 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6191 Prev_Non_Pragma (Decl);
6196 -- LN : label; -- If Is_Local is enabled
6201 -- case CounterX is .
6211 -- <<LN>> -- If Is_Local is enabled
6213 -- [Deep_]Finalize (V.CompY);
6215 -- when Id : others =>
6216 -- if not Raised then
6218 -- Save_Occurrence (E,
6219 -- Get_Current_Excep.all.all);
6223 -- <<L0>> -- If Is_Local is enabled
6228 -- Add the declaration of default jump location L0, its
6229 -- corresponding alternative and its place in the statements.
6231 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6232 Set_Entity (Label_Id,
6233 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6234 Label := Make_Label (Loc, Label_Id);
6236 Append_To (Decls, -- declaration
6237 Make_Implicit_Label_Declaration (Loc,
6238 Defining_Identifier => Entity (Label_Id),
6239 Label_Construct => Label));
6241 Append_To (Alts, -- alternative
6242 Make_Case_Statement_Alternative (Loc,
6243 Discrete_Choices => New_List (
6244 Make_Others_Choice (Loc)),
6246 Statements => New_List (
6247 Make_Goto_Statement (Loc,
6248 Name => New_Reference_To (Entity (Label_Id), Loc)))));
6250 Append_To (Stmts, Label); -- statement
6252 -- Create the jump block
6255 Make_Case_Statement (Loc,
6256 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
6257 Alternatives => Alts));
6261 Make_Block_Statement (Loc,
6262 Declarations => Decls,
6263 Handled_Statement_Sequence =>
6264 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6266 if Present (Var_Case) then
6267 return New_List (Var_Case, Jump_Block);
6269 return New_List (Jump_Block);
6271 end Process_Component_List_For_Finalize;
6273 -- Start of processing for Build_Finalize_Statements
6276 if Exceptions_OK then
6277 Abort_Id := Make_Temporary (Loc, 'A');
6278 E_Id := Make_Temporary (Loc, 'E');
6279 Raised_Id := Make_Temporary (Loc, 'R');
6282 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6283 Rec_Def := Record_Extension_Part (Typ_Def);
6288 -- Create a finalization sequence for all record components
6290 if Present (Component_List (Rec_Def)) then
6292 Process_Component_List_For_Finalize (Component_List (Rec_Def));
6295 -- A derived record type must finalize all inherited components. This
6296 -- action poses the following problem:
6298 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6303 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6305 -- Deep_Finalize (Obj._parent);
6310 -- Finalizing the derived type will invoke Finalize of the parent and
6311 -- then that of the derived type. This is undesirable because both
6312 -- routines may modify shared components. Only the Finalize of the
6313 -- derived type should be invoked.
6315 -- To prevent this double adjustment of shared components,
6316 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6318 -- procedure Deep_Finalize
6319 -- (Obj : in out Some_Type;
6320 -- Flag : Boolean := True)
6328 -- When Deep_Finalize is invokes for field _parent, a value of False
6329 -- is provided for the flag:
6331 -- Deep_Finalize (Obj._parent, False);
6333 if Is_Tagged_Type (Typ)
6334 and then Is_Derived_Type (Typ)
6337 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6342 if Needs_Finalization (Par_Typ) then
6346 Make_Selected_Component (Loc,
6347 Prefix => Make_Identifier (Loc, Name_V),
6349 Make_Identifier (Loc, Name_uParent)),
6351 For_Parent => True);
6354 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
6356 -- begin -- Exceptions OK
6357 -- Deep_Finalize (V._parent, False);
6359 -- when Id : others =>
6360 -- if not Raised then
6362 -- Save_Occurrence (E,
6363 -- Get_Current_Excep.all.all);
6367 if Present (Call) then
6370 if Exceptions_OK then
6372 Make_Block_Statement (Loc,
6373 Handled_Statement_Sequence =>
6374 Make_Handled_Sequence_Of_Statements (Loc,
6375 Statements => New_List (Fin_Stmt),
6376 Exception_Handlers => New_List (
6377 Build_Exception_Handler
6378 (Loc, E_Id, Raised_Id))));
6381 Append_To (Bod_Stmts, Fin_Stmt);
6387 -- Finalize the object. This action must be performed first before
6388 -- all components have been finalized.
6390 if Is_Controlled (Typ)
6391 and then not Is_Local
6398 Proc := Find_Prim_Op (Typ, Name_Finalize);
6402 -- Finalize (V); -- No_Exception_Propagation
6408 -- if not Raised then
6410 -- Save_Occurrence (E,
6411 -- Get_Current_Excep.all.all);
6416 if Present (Proc) then
6418 Make_Procedure_Call_Statement (Loc,
6419 Name => New_Reference_To (Proc, Loc),
6420 Parameter_Associations => New_List (
6421 Make_Identifier (Loc, Name_V)));
6423 if Exceptions_OK then
6425 Make_Block_Statement (Loc,
6426 Handled_Statement_Sequence =>
6427 Make_Handled_Sequence_Of_Statements (Loc,
6428 Statements => New_List (Fin_Stmt),
6429 Exception_Handlers => New_List (
6430 Build_Exception_Handler
6431 (Loc, E_Id, Raised_Id))));
6434 Prepend_To (Bod_Stmts,
6435 Make_If_Statement (Loc,
6436 Condition => Make_Identifier (Loc, Name_F),
6437 Then_Statements => New_List (Fin_Stmt)));
6442 -- At this point either all finalization statements have been
6443 -- generated or the type is not controlled.
6445 if No (Bod_Stmts) then
6446 return New_List (Make_Null_Statement (Loc));
6450 -- Abort : constant Boolean :=
6451 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6452 -- Standard'Abort_Signal'Identity;
6454 -- Abort : constant Boolean := False; -- no abort
6456 -- E : Exception_Occurence;
6457 -- Raised : Boolean := False;
6460 -- if V.Finalized then
6464 -- <finalize statements>
6465 -- V.Finalized := True;
6468 -- Raise_From_Controlled_Operation (E, Abort);
6473 if Exceptions_OK then
6474 Append_To (Bod_Stmts,
6475 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6480 Make_Block_Statement (Loc,
6482 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6483 Handled_Statement_Sequence =>
6484 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6486 end Build_Finalize_Statements;
6488 -----------------------
6489 -- Parent_Field_Type --
6490 -----------------------
6492 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
6496 Field := First_Entity (Typ);
6497 while Present (Field) loop
6498 if Chars (Field) = Name_uParent then
6499 return Etype (Field);
6502 Next_Entity (Field);
6505 -- A derived tagged type should always have a parent field
6507 raise Program_Error;
6508 end Parent_Field_Type;
6510 ---------------------------
6511 -- Preprocess_Components --
6512 ---------------------------
6514 procedure Preprocess_Components
6516 Num_Comps : out Int;
6517 Has_POC : out Boolean)
6527 Decl := First_Non_Pragma (Component_Items (Comps));
6528 while Present (Decl) loop
6529 Id := Defining_Identifier (Decl);
6532 -- Skip field _parent
6534 if Chars (Id) /= Name_uParent
6535 and then Needs_Finalization (Typ)
6537 Num_Comps := Num_Comps + 1;
6539 if Has_Access_Constraint (Id)
6540 and then No (Expression (Decl))
6546 Next_Non_Pragma (Decl);
6548 end Preprocess_Components;
6550 -- Start of processing for Make_Deep_Record_Body
6554 when Address_Case =>
6555 return Make_Finalize_Address_Stmts (Typ);
6558 return Build_Adjust_Statements (Typ);
6560 when Finalize_Case =>
6561 return Build_Finalize_Statements (Typ);
6563 when Initialize_Case =>
6565 Loc : constant Source_Ptr := Sloc (Typ);
6568 if Is_Controlled (Typ) then
6570 Make_Procedure_Call_Statement (Loc,
6573 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
6574 Parameter_Associations => New_List (
6575 Make_Identifier (Loc, Name_V))));
6581 end Make_Deep_Record_Body;
6583 ----------------------
6584 -- Make_Final_Call --
6585 ----------------------
6587 function Make_Final_Call
6590 For_Parent : Boolean := False) return Node_Id
6592 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6593 Fin_Id : Entity_Id := Empty;
6598 -- Recover the proper type which contains [Deep_]Finalize
6600 if Is_Class_Wide_Type (Typ) then
6601 Utyp := Root_Type (Typ);
6604 elsif Is_Concurrent_Type (Typ) then
6605 Utyp := Corresponding_Record_Type (Typ);
6606 Ref := Convert_Concurrent (Obj_Ref, Typ);
6608 elsif Is_Private_Type (Typ)
6609 and then Present (Full_View (Typ))
6610 and then Is_Concurrent_Type (Full_View (Typ))
6612 Utyp := Corresponding_Record_Type (Full_View (Typ));
6613 Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ));
6620 Utyp := Underlying_Type (Base_Type (Utyp));
6621 Set_Assignment_OK (Ref);
6623 -- Deal with non-tagged derivation of private views. If the parent type
6624 -- is a protected type, Deep_Finalize is found on the corresponding
6625 -- record of the ancestor.
6627 if Is_Untagged_Derivation (Typ) then
6628 if Is_Protected_Type (Typ) then
6629 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
6631 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6633 if Is_Protected_Type (Utyp) then
6634 Utyp := Corresponding_Record_Type (Utyp);
6638 Ref := Unchecked_Convert_To (Utyp, Ref);
6639 Set_Assignment_OK (Ref);
6642 -- Deal with derived private types which do not inherit primitives from
6643 -- their parents. In this case, [Deep_]Finalize can be found in the full
6644 -- view of the parent type.
6646 if Is_Tagged_Type (Utyp)
6647 and then Is_Derived_Type (Utyp)
6648 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
6649 and then Is_Private_Type (Etype (Utyp))
6650 and then Present (Full_View (Etype (Utyp)))
6652 Utyp := Full_View (Etype (Utyp));
6653 Ref := Unchecked_Convert_To (Utyp, Ref);
6654 Set_Assignment_OK (Ref);
6657 -- When dealing with the completion of a private type, use the base type
6660 if Utyp /= Base_Type (Utyp) then
6661 pragma Assert (Is_Private_Type (Typ));
6663 Utyp := Base_Type (Utyp);
6664 Ref := Unchecked_Convert_To (Utyp, Ref);
6665 Set_Assignment_OK (Ref);
6668 -- Select the appropriate version of finalize
6671 if Has_Controlled_Component (Utyp) then
6672 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6675 -- For types that are both controlled and have controlled components,
6676 -- generate a call to Deep_Finalize.
6678 elsif Is_Controlled (Utyp)
6679 and then Has_Controlled_Component (Utyp)
6681 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6683 -- For types that are not controlled themselves, but contain controlled
6684 -- components or can be extended by types with controlled components,
6685 -- create a call to Deep_Finalize.
6687 elsif Is_Class_Wide_Type (Typ)
6688 or else Is_Interface (Typ)
6689 or else Has_Controlled_Component (Utyp)
6691 if Is_Tagged_Type (Utyp) then
6692 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6694 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
6697 -- For types that are derived from Controlled and do not have controlled
6698 -- components, build a call to Finalize.
6701 Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
6704 if Present (Fin_Id) then
6706 -- When finalizing a class-wide object, do not convert to the root
6707 -- type in order to produce a dispatching call.
6709 if Is_Class_Wide_Type (Typ) then
6712 -- Ensure that a finalization routine is at least decorated in order
6713 -- to inspect the object parameter.
6715 elsif Analyzed (Fin_Id)
6716 or else Ekind (Fin_Id) = E_Procedure
6718 -- In certain cases, such as the creation of Stream_Read, the
6719 -- visible entity of the type is its full view. Since Stream_Read
6720 -- will have to create an object of type Typ, the local object
6721 -- will be finalzed by the scope finalizer generated later on. The
6722 -- object parameter of Deep_Finalize will always use the private
6723 -- view of the type. To avoid such a clash between a private and a
6724 -- full view, perform an unchecked conversion of the object
6725 -- reference to the private view.
6728 Formal_Typ : constant Entity_Id :=
6729 Etype (First_Formal (Fin_Id));
6731 if Is_Private_Type (Formal_Typ)
6732 and then Present (Full_View (Formal_Typ))
6733 and then Full_View (Formal_Typ) = Utyp
6735 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
6739 Ref := Convert_View (Fin_Id, Ref);
6742 return Make_Call (Loc, Fin_Id, New_Copy_Tree (Ref), For_Parent);
6746 end Make_Final_Call;
6748 --------------------------------
6749 -- Make_Finalize_Address_Body --
6750 --------------------------------
6752 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
6754 -- Nothing to do if the type is not controlled or it already has a
6755 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
6756 -- come from source. These are usually generated for completeness and
6757 -- do not need the Finalize_Address primitive.
6759 if not Needs_Finalization (Typ)
6760 or else Present (TSS (Typ, TSS_Finalize_Address))
6762 (Is_Class_Wide_Type (Typ)
6763 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
6764 and then not Comes_From_Source (Root_Type (Typ)))
6770 Loc : constant Source_Ptr := Sloc (Typ);
6771 Proc_Id : Entity_Id;
6775 Make_Defining_Identifier (Loc,
6776 Make_TSS_Name (Typ, TSS_Finalize_Address));
6779 -- procedure TypFD (V : System.Address) is
6782 -- type Pnn is access all Typ;
6783 -- for Pnn'Storage_Size use 0;
6785 -- [Deep_]Finalize (Pnn (V).all);
6790 Make_Subprogram_Body (Loc,
6792 Make_Procedure_Specification (Loc,
6793 Defining_Unit_Name => Proc_Id,
6795 Parameter_Specifications => New_List (
6796 Make_Parameter_Specification (Loc,
6797 Defining_Identifier =>
6798 Make_Defining_Identifier (Loc, Name_V),
6800 New_Reference_To (RTE (RE_Address), Loc)))),
6802 Declarations => No_List,
6804 Handled_Statement_Sequence =>
6805 Make_Handled_Sequence_Of_Statements (Loc,
6807 Make_Finalize_Address_Stmts (Typ))));
6809 Set_TSS (Typ, Proc_Id);
6811 end Make_Finalize_Address_Body;
6813 ---------------------------------
6814 -- Make_Finalize_Address_Stmts --
6815 ---------------------------------
6817 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
6818 Loc : constant Source_Ptr := Sloc (Typ);
6819 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
6821 Desg_Typ : Entity_Id;
6825 if Is_Array_Type (Typ) then
6826 if Is_Constrained (First_Subtype (Typ)) then
6827 Desg_Typ := First_Subtype (Typ);
6829 Desg_Typ := Base_Type (Typ);
6832 -- Class-wide types of constrained root types
6834 elsif Is_Class_Wide_Type (Typ)
6835 and then Has_Discriminants (Root_Type (Typ))
6837 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
6840 Parent_Typ : Entity_Id := Root_Type (Typ);
6843 -- Climb the parent type chain looking for a non-constrained type
6845 while Parent_Typ /= Etype (Parent_Typ)
6846 and then Has_Discriminants (Parent_Typ)
6848 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
6850 Parent_Typ := Etype (Parent_Typ);
6853 -- Handle views created for tagged types with unknown
6856 if Is_Underlying_Record_View (Parent_Typ) then
6857 Parent_Typ := Underlying_Record_View (Parent_Typ);
6860 Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
6870 -- type Ptr_Typ is access all Typ;
6871 -- for Ptr_Typ'Storage_Size use 0;
6874 Make_Full_Type_Declaration (Loc,
6875 Defining_Identifier => Ptr_Typ,
6877 Make_Access_To_Object_Definition (Loc,
6878 All_Present => True,
6879 Subtype_Indication => New_Reference_To (Desg_Typ, Loc))),
6881 Make_Attribute_Definition_Clause (Loc,
6882 Name => New_Reference_To (Ptr_Typ, Loc),
6883 Chars => Name_Storage_Size,
6884 Expression => Make_Integer_Literal (Loc, 0)));
6886 Obj_Expr := Make_Identifier (Loc, Name_V);
6888 -- Unconstrained arrays require special processing in order to retrieve
6889 -- the elements. To achieve this, we have to skip the dope vector which
6890 -- lays infront of the elements and then use a thin pointer to perform
6891 -- the address-to-access conversion.
6893 if Is_Array_Type (Typ)
6894 and then not Is_Constrained (First_Subtype (Typ))
6897 Dope_Expr : Node_Id;
6898 Dope_Id : Entity_Id;
6899 For_First : Boolean := True;
6902 function Bounds_Size_Expression (Typ : Entity_Id) return Node_Id;
6903 -- Given the type of an array index, create the following
6906 -- 2 * Esize (Typ) / Storage_Unit
6908 ----------------------------
6909 -- Bounds_Size_Expression --
6910 ----------------------------
6912 function Bounds_Size_Expression (Typ : Entity_Id) return Node_Id is
6915 Make_Op_Multiply (Loc,
6916 Left_Opnd => Make_Integer_Literal (Loc, 2),
6918 Make_Op_Divide (Loc,
6919 Left_Opnd => Make_Integer_Literal (Loc, Esize (Typ)),
6921 Make_Integer_Literal (Loc, System_Storage_Unit)));
6922 end Bounds_Size_Expression;
6924 -- Start of processing for arrays
6927 -- Ensure that Ptr_Typ a thin pointer, generate:
6929 -- for Ptr_Typ'Size use System.Address'Size;
6932 Make_Attribute_Definition_Clause (Loc,
6933 Name => New_Reference_To (Ptr_Typ, Loc),
6936 Make_Integer_Literal (Loc, System_Address_Size)));
6938 -- For unconstrained arrays, create the expression which computes
6939 -- the size of the dope vector. Note that in the end, all values
6940 -- will be constant folded.
6942 Index := First_Index (Typ);
6943 while Present (Index) loop
6946 -- 2 * Esize (Index_Typ) / Storage_Unit
6950 Dope_Expr := Bounds_Size_Expression (Etype (Index));
6953 -- Dope_Expr + 2 * Esize (Index_Typ) / Storage_Unit
6958 Left_Opnd => Dope_Expr,
6959 Right_Opnd => Bounds_Size_Expression (Etype (Index)));
6966 -- Dnn : Storage_Offset := Dope_Expr;
6968 Dope_Id := Make_Temporary (Loc, 'D');
6971 Make_Object_Declaration (Loc,
6972 Defining_Identifier => Dope_Id,
6973 Constant_Present => True,
6974 Object_Definition =>
6975 New_Reference_To (RTE (RE_Storage_Offset), Loc),
6976 Expression => Dope_Expr));
6978 -- Shift the address from the start of the dope vector to the
6979 -- start of the elements:
6983 -- Note that this is done through a wrapper routine since RTSfind
6984 -- cannot retrieve operations with string names of the form "+".
6987 Make_Function_Call (Loc,
6989 New_Reference_To (RTE (RE_Add_Offset_To_Address), Loc),
6990 Parameter_Associations => New_List (
6992 New_Reference_To (Dope_Id, Loc)));
6996 -- Create the block and the finalization call
6999 Make_Block_Statement (Loc,
7000 Declarations => Decls,
7002 Handled_Statement_Sequence =>
7003 Make_Handled_Sequence_Of_Statements (Loc,
7004 Statements => New_List (
7007 Make_Explicit_Dereference (Loc,
7008 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7009 Typ => Desg_Typ)))));
7010 end Make_Finalize_Address_Stmts;
7012 -------------------------------------
7013 -- Make_Handler_For_Ctrl_Operation --
7014 -------------------------------------
7018 -- when E : others =>
7019 -- Raise_From_Controlled_Operation (E, False);
7024 -- raise Program_Error [finalize raised exception];
7026 -- depending on whether Raise_From_Controlled_Operation is available
7028 function Make_Handler_For_Ctrl_Operation
7029 (Loc : Source_Ptr) return Node_Id
7032 -- Choice parameter (for the first case above)
7034 Raise_Node : Node_Id;
7035 -- Procedure call or raise statement
7038 -- .NET/JVM runtime: add choice parameter E and pass it to Reraise_
7041 if VM_Target /= No_VM then
7042 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7044 Make_Procedure_Call_Statement (Loc,
7046 New_Reference_To (RTE (RE_Reraise_Occurrence), Loc),
7047 Parameter_Associations => New_List (
7048 New_Reference_To (E_Occ, Loc)));
7050 -- Standard runtime: add choice parameter E and pass it to Raise_From_
7051 -- Controlled_Operation so that the original exception name and message
7052 -- can be recorded in the exception message for Program_Error.
7054 elsif RTE_Available (RE_Raise_From_Controlled_Operation) then
7055 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7057 Make_Procedure_Call_Statement (Loc,
7060 (RTE (RE_Raise_From_Controlled_Operation), Loc),
7061 Parameter_Associations => New_List (
7062 New_Reference_To (E_Occ, Loc),
7063 New_Reference_To (Standard_False, Loc)));
7065 -- Restricted runtime: exception messages are not supported
7070 Make_Raise_Program_Error (Loc,
7071 Reason => PE_Finalize_Raised_Exception);
7075 Make_Implicit_Exception_Handler (Loc,
7076 Exception_Choices => New_List (Make_Others_Choice (Loc)),
7077 Choice_Parameter => E_Occ,
7078 Statements => New_List (Raise_Node));
7079 end Make_Handler_For_Ctrl_Operation;
7081 --------------------
7082 -- Make_Init_Call --
7083 --------------------
7085 function Make_Init_Call
7087 Typ : Entity_Id) return Node_Id
7089 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7096 -- Deal with the type and object reference. Depending on the context, an
7097 -- object reference may need several conversions.
7099 if Is_Concurrent_Type (Typ) then
7101 Utyp := Corresponding_Record_Type (Typ);
7102 Ref := Convert_Concurrent (Obj_Ref, Typ);
7104 elsif Is_Private_Type (Typ)
7105 and then Present (Full_View (Typ))
7106 and then Is_Concurrent_Type (Underlying_Type (Typ))
7109 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7110 Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7118 Set_Assignment_OK (Ref);
7120 Utyp := Underlying_Type (Base_Type (Utyp));
7122 -- Deal with non-tagged derivation of private views
7124 if Is_Untagged_Derivation (Typ)
7125 and then not Is_Conc
7127 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7128 Ref := Unchecked_Convert_To (Utyp, Ref);
7130 Set_Assignment_OK (Ref);
7131 -- To prevent problems with UC see 1.156 RH ???
7134 -- If the underlying_type is a subtype, then we are dealing with the
7135 -- completion of a private type. We need to access the base type and
7136 -- generate a conversion to it.
7138 if Utyp /= Base_Type (Utyp) then
7139 pragma Assert (Is_Private_Type (Typ));
7140 Utyp := Base_Type (Utyp);
7141 Ref := Unchecked_Convert_To (Utyp, Ref);
7144 -- Select the appropriate version of initialize
7146 if Has_Controlled_Component (Utyp) then
7147 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7149 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7150 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7153 -- The object reference may need another conversion depending on the
7154 -- type of the formal and that of the actual.
7156 Ref := Convert_View (Proc, Ref);
7159 -- [Deep_]Initialize (Ref);
7162 Make_Procedure_Call_Statement (Loc,
7164 New_Reference_To (Proc, Loc),
7165 Parameter_Associations => New_List (Ref));
7168 ------------------------------
7169 -- Make_Local_Deep_Finalize --
7170 ------------------------------
7172 function Make_Local_Deep_Finalize
7174 Nam : Entity_Id) return Node_Id
7176 Loc : constant Source_Ptr := Sloc (Typ);
7180 Formals := New_List (
7184 Make_Parameter_Specification (Loc,
7185 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7187 Out_Present => True,
7188 Parameter_Type => New_Reference_To (Typ, Loc)),
7190 -- F : Boolean := True
7192 Make_Parameter_Specification (Loc,
7193 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7194 Parameter_Type => New_Reference_To (Standard_Boolean, Loc),
7195 Expression => New_Reference_To (Standard_True, Loc)));
7197 -- Add the necessary number of counters to represent the initialization
7198 -- state of an object.
7201 Make_Subprogram_Body (Loc,
7203 Make_Procedure_Specification (Loc,
7204 Defining_Unit_Name => Nam,
7205 Parameter_Specifications => Formals),
7207 Declarations => No_List,
7209 Handled_Statement_Sequence =>
7210 Make_Handled_Sequence_Of_Statements (Loc,
7211 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7212 end Make_Local_Deep_Finalize;
7214 ----------------------------------------
7215 -- Make_Set_Finalize_Address_Ptr_Call --
7216 ----------------------------------------
7218 function Make_Set_Finalize_Address_Ptr_Call
7221 Ptr_Typ : Entity_Id) return Node_Id
7223 Desig_Typ : constant Entity_Id :=
7224 Available_View (Designated_Type (Ptr_Typ));
7228 -- If the context is a class-wide allocator, we use the class-wide type
7229 -- to obtain the proper Finalize_Address routine.
7231 if Is_Class_Wide_Type (Desig_Typ) then
7237 if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
7238 Utyp := Full_View (Utyp);
7241 if Is_Concurrent_Type (Utyp) then
7242 Utyp := Corresponding_Record_Type (Utyp);
7246 Utyp := Underlying_Type (Base_Type (Utyp));
7248 -- Deal with non-tagged derivation of private views. If the parent is
7249 -- now known to be protected, the finalization routine is the one
7250 -- defined on the corresponding record of the ancestor (corresponding
7251 -- records do not automatically inherit operations, but maybe they
7254 if Is_Untagged_Derivation (Typ) then
7255 if Is_Protected_Type (Typ) then
7256 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7258 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7260 if Is_Protected_Type (Utyp) then
7261 Utyp := Corresponding_Record_Type (Utyp);
7266 -- If the underlying_type is a subtype, we are dealing with the
7267 -- completion of a private type. We need to access the base type and
7268 -- generate a conversion to it.
7270 if Utyp /= Base_Type (Utyp) then
7271 pragma Assert (Is_Private_Type (Typ));
7273 Utyp := Base_Type (Utyp);
7277 -- Set_Finalize_Address_Ptr
7278 -- (<Ptr_Typ>FC, <Utyp>FD'Unrestricted_Access);
7281 Make_Procedure_Call_Statement (Loc,
7283 New_Reference_To (RTE (RE_Set_Finalize_Address_Ptr), Loc),
7285 Parameter_Associations => New_List (
7286 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
7288 Make_Attribute_Reference (Loc,
7290 New_Reference_To (TSS (Utyp, TSS_Finalize_Address), Loc),
7291 Attribute_Name => Name_Unrestricted_Access)));
7292 end Make_Set_Finalize_Address_Ptr_Call;
7294 --------------------------
7295 -- Make_Transient_Block --
7296 --------------------------
7298 function Make_Transient_Block
7301 Par : Node_Id) return Node_Id
7303 Decls : constant List_Id := New_List;
7304 Instrs : constant List_Id := New_List (Action);
7309 -- Case where only secondary stack use is involved
7311 if VM_Target = No_VM
7312 and then Uses_Sec_Stack (Current_Scope)
7313 and then Nkind (Action) /= N_Simple_Return_Statement
7314 and then Nkind (Par) /= N_Exception_Handler
7320 S := Scope (Current_Scope);
7322 -- At the outer level, no need to release the sec stack
7324 if S = Standard_Standard then
7325 Set_Uses_Sec_Stack (Current_Scope, False);
7328 -- In a function, only release the sec stack if the
7329 -- function does not return on the sec stack otherwise
7330 -- the result may be lost. The caller is responsible for
7333 elsif Ekind (S) = E_Function then
7334 Set_Uses_Sec_Stack (Current_Scope, False);
7336 if not Requires_Transient_Scope (Etype (S)) then
7337 Set_Uses_Sec_Stack (S, True);
7338 Check_Restriction (No_Secondary_Stack, Action);
7343 -- In a loop or entry we should install a block encompassing
7344 -- all the construct. For now just release right away.
7346 elsif Ekind_In (S, E_Entry, E_Loop) then
7349 -- In a procedure or a block, we release on exit of the
7350 -- procedure or block. ??? memory leak can be created by
7353 elsif Ekind_In (S, E_Block, E_Procedure) then
7354 Set_Uses_Sec_Stack (S, True);
7355 Check_Restriction (No_Secondary_Stack, Action);
7356 Set_Uses_Sec_Stack (Current_Scope, False);
7366 -- Create the transient block. Set the parent now since the block itself
7367 -- is not part of the tree.
7370 Make_Block_Statement (Loc,
7371 Identifier => New_Reference_To (Current_Scope, Loc),
7372 Declarations => Decls,
7373 Handled_Statement_Sequence =>
7374 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7375 Has_Created_Identifier => True);
7376 Set_Parent (Block, Par);
7378 -- Insert actions stuck in the transient scopes as well as all freezing
7379 -- nodes needed by those actions.
7381 Insert_Actions_In_Scope_Around (Action);
7383 Insert := Prev (Action);
7384 if Present (Insert) then
7385 Freeze_All (First_Entity (Current_Scope), Insert);
7388 -- When the transient scope was established, we pushed the entry for
7389 -- the transient scope onto the scope stack, so that the scope was
7390 -- active for the installation of finalizable entities etc. Now we
7391 -- must remove this entry, since we have constructed a proper block.
7396 end Make_Transient_Block;
7398 ------------------------
7399 -- Node_To_Be_Wrapped --
7400 ------------------------
7402 function Node_To_Be_Wrapped return Node_Id is
7404 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
7405 end Node_To_Be_Wrapped;
7407 ----------------------------
7408 -- Set_Node_To_Be_Wrapped --
7409 ----------------------------
7411 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
7413 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
7414 end Set_Node_To_Be_Wrapped;
7416 ----------------------------------
7417 -- Store_After_Actions_In_Scope --
7418 ----------------------------------
7420 procedure Store_After_Actions_In_Scope (L : List_Id) is
7421 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7424 if Present (SE.Actions_To_Be_Wrapped_After) then
7425 Insert_List_Before_And_Analyze (
7426 First (SE.Actions_To_Be_Wrapped_After), L);
7429 SE.Actions_To_Be_Wrapped_After := L;
7431 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7432 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7434 Set_Parent (L, SE.Node_To_Be_Wrapped);
7439 end Store_After_Actions_In_Scope;
7441 -----------------------------------
7442 -- Store_Before_Actions_In_Scope --
7443 -----------------------------------
7445 procedure Store_Before_Actions_In_Scope (L : List_Id) is
7446 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7449 if Present (SE.Actions_To_Be_Wrapped_Before) then
7450 Insert_List_After_And_Analyze (
7451 Last (SE.Actions_To_Be_Wrapped_Before), L);
7454 SE.Actions_To_Be_Wrapped_Before := L;
7456 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7457 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7459 Set_Parent (L, SE.Node_To_Be_Wrapped);
7464 end Store_Before_Actions_In_Scope;
7466 --------------------------------
7467 -- Wrap_Transient_Declaration --
7468 --------------------------------
7470 -- If a transient scope has been established during the processing of the
7471 -- Expression of an Object_Declaration, it is not possible to wrap the
7472 -- declaration into a transient block as usual case, otherwise the object
7473 -- would be itself declared in the wrong scope. Therefore, all entities (if
7474 -- any) defined in the transient block are moved to the proper enclosing
7475 -- scope, furthermore, if they are controlled variables they are finalized
7476 -- right after the declaration. The finalization list of the transient
7477 -- scope is defined as a renaming of the enclosing one so during their
7478 -- initialization they will be attached to the proper finalization list.
7479 -- For instance, the following declaration :
7481 -- X : Typ := F (G (A), G (B));
7483 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7484 -- is expanded into :
7486 -- X : Typ := [ complex Expression-Action ];
7487 -- [Deep_]Finalize (_v1);
7488 -- [Deep_]Finalize (_v2);
7490 procedure Wrap_Transient_Declaration (N : Node_Id) is
7497 Encl_S := Scope (S);
7499 -- Insert Actions kept in the Scope stack
7501 Insert_Actions_In_Scope_Around (N);
7503 -- If the declaration is consuming some secondary stack, mark the
7504 -- enclosing scope appropriately.
7506 Uses_SS := Uses_Sec_Stack (S);
7509 -- Put the local entities back in the enclosing scope, and set the
7510 -- Is_Public flag appropriately.
7512 Transfer_Entities (S, Encl_S);
7514 -- Mark the enclosing dynamic scope so that the sec stack will be
7515 -- released upon its exit unless this is a function that returns on
7516 -- the sec stack in which case this will be done by the caller.
7518 if VM_Target = No_VM and then Uses_SS then
7519 S := Enclosing_Dynamic_Scope (S);
7521 if Ekind (S) = E_Function
7522 and then Requires_Transient_Scope (Etype (S))
7526 Set_Uses_Sec_Stack (S);
7527 Check_Restriction (No_Secondary_Stack, N);
7530 end Wrap_Transient_Declaration;
7532 -------------------------------
7533 -- Wrap_Transient_Expression --
7534 -------------------------------
7536 procedure Wrap_Transient_Expression (N : Node_Id) is
7537 Expr : constant Node_Id := Relocate_Node (N);
7538 Loc : constant Source_Ptr := Sloc (N);
7539 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
7540 Typ : constant Entity_Id := Etype (N);
7547 -- M : constant Mark_Id := SS_Mark;
7548 -- procedure Finalizer is ... (See Build_Finalizer)
7557 Insert_Actions (N, New_List (
7558 Make_Object_Declaration (Loc,
7559 Defining_Identifier => Temp,
7560 Object_Definition => New_Reference_To (Typ, Loc)),
7562 Make_Transient_Block (Loc,
7564 Make_Assignment_Statement (Loc,
7565 Name => New_Reference_To (Temp, Loc),
7566 Expression => Expr),
7567 Par => Parent (N))));
7569 Rewrite (N, New_Reference_To (Temp, Loc));
7570 Analyze_And_Resolve (N, Typ);
7571 end Wrap_Transient_Expression;
7573 ------------------------------
7574 -- Wrap_Transient_Statement --
7575 ------------------------------
7577 procedure Wrap_Transient_Statement (N : Node_Id) is
7578 Loc : constant Source_Ptr := Sloc (N);
7579 New_Stmt : constant Node_Id := Relocate_Node (N);
7584 -- M : constant Mark_Id := SS_Mark;
7585 -- procedure Finalizer is ... (See Build_Finalizer)
7595 Make_Transient_Block (Loc,
7597 Par => Parent (N)));
7599 -- With the scope stack back to normal, we can call analyze on the
7600 -- resulting block. At this point, the transient scope is being
7601 -- treated like a perfectly normal scope, so there is nothing
7602 -- special about it.
7604 -- Note: Wrap_Transient_Statement is called with the node already
7605 -- analyzed (i.e. Analyzed (N) is True). This is important, since
7606 -- otherwise we would get a recursive processing of the node when
7607 -- we do this Analyze call.
7610 end Wrap_Transient_Statement;