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 the
301 -- context does not contain the above constructs, the routine returns an
304 function Build_Exception_Handler
307 Raised_Id : Entity_Id;
308 For_Library : Boolean := False) return Node_Id;
309 -- Subsidiary to Build_Finalizer, Make_Deep_Array_Body and Make_Deep_Record
310 -- _Body. Create an exception handler of the following form:
313 -- if not Raised_Id then
314 -- Raised_Id := True;
315 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
318 -- If flag For_Library is set (and not in restricted profile):
321 -- if not Raised_Id then
322 -- Raised_Id := True;
323 -- Save_Library_Occurrence (Get_Current_Excep.all.all);
326 -- E_Id denotes the defining identifier of a local exception occurrence.
327 -- Raised_Id is the entity of a local boolean flag. Flag For_Library is
328 -- used when operating at the library level, when enabled the current
329 -- exception will be saved to a global location.
331 procedure Build_Finalizer
333 Clean_Stmts : List_Id;
336 Defer_Abort : Boolean;
337 Fin_Id : out Entity_Id);
338 -- N may denote an accept statement, block, entry body, package body,
339 -- package spec, protected body, subprogram body, and a task body. Create
340 -- a procedure which contains finalization calls for all controlled objects
341 -- declared in the declarative or statement region of N. The calls are
342 -- built in reverse order relative to the original declarations. In the
343 -- case of a tack body, the routine delays the creation of the finalizer
344 -- until all statements have been moved to the task body procedure.
345 -- Clean_Stmts may contain additional context-dependent code used to abort
346 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
347 -- Mark_Id is the secondary stack used in the current context or Empty if
348 -- missing. Top_Decls is the list on which the declaration of the finalizer
349 -- is attached in the non-package case. Defer_Abort indicates that the
350 -- statements passed in perform actions that require abort to be deferred,
351 -- such as for task termination. Fin_Id is the finalizer declaration
354 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
355 -- N is a construct which contains a handled sequence of statements, Fin_Id
356 -- is the entity of a finalizer. Create an At_End handler which covers the
357 -- statements of N and calls Fin_Id. If the handled statement sequence has
358 -- an exception handler, the statements will be wrapped in a block to avoid
359 -- unwanted interaction with the new At_End handler.
361 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
362 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
363 -- Has_Component_Component set and store them using the TSS mechanism.
365 procedure Check_Visibly_Controlled
366 (Prim : Final_Primitives;
368 E : in out Entity_Id;
369 Cref : in out Node_Id);
370 -- The controlled operation declared for a derived type may not be
371 -- overriding, if the controlled operations of the parent type are hidden,
372 -- for example when the parent is a private type whose full view is
373 -- controlled. For other primitive operations we modify the name of the
374 -- operation to indicate that it is not overriding, but this is not
375 -- possible for Initialize, etc. because they have to be retrievable by
376 -- name. Before generating the proper call to one of these operations we
377 -- check whether Typ is known to be controlled at the point of definition.
378 -- If it is not then we must retrieve the hidden operation of the parent
379 -- and use it instead. This is one case that might be solved more cleanly
380 -- once Overriding pragmas or declarations are in place.
382 function Convert_View
385 Ind : Pos := 1) return Node_Id;
386 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
387 -- argument being passed to it. Ind indicates which formal of procedure
388 -- Proc we are trying to match. This function will, if necessary, generate
389 -- a conversion between the partial and full view of Arg to match the type
390 -- of the formal of Proc, or force a conversion to the class-wide type in
391 -- the case where the operation is abstract.
393 function Enclosing_Function (E : Entity_Id) return Entity_Id;
394 -- Given an arbitrary entity, traverse the scope chain looking for the
395 -- first enclosing function. Return Empty if no function was found.
401 For_Parent : Boolean := False) return Node_Id;
402 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
403 -- routine [Deep_]Adjust / Finalize and an object parameter, create an
404 -- adjust / finalization call. Flag For_Parent should be set when field
405 -- _parent is being processed.
407 function Make_Deep_Proc
408 (Prim : Final_Primitives;
410 Stmts : List_Id) return Node_Id;
411 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
412 -- Deep_Finalize procedures according to the first parameter, these
413 -- procedures operate on the type Typ. The Stmts parameter gives the body
416 function Make_Deep_Array_Body
417 (Prim : Final_Primitives;
418 Typ : Entity_Id) return List_Id;
419 -- This function generates the list of statements for implementing
420 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
421 -- the first parameter, these procedures operate on the array type Typ.
423 function Make_Deep_Record_Body
424 (Prim : Final_Primitives;
426 Is_Local : Boolean := False) return List_Id;
427 -- This function generates the list of statements for implementing
428 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
429 -- the first parameter, these procedures operate on the record type Typ.
430 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
431 -- whether the inner logic should be dictated by state counters.
433 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
434 -- Subsidiary to Make_Finalize_Address_Body and Make_Deep_Array_Body.
435 -- Generate the following statements:
438 -- type Acc_Typ is access all Typ;
439 -- for Acc_Typ'Storage_Size use 0;
441 -- [Deep_]Finalize (Acc_Typ (V).all);
444 ----------------------------
445 -- Build_Array_Deep_Procs --
446 ----------------------------
448 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
452 (Prim => Initialize_Case,
454 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
456 if not Is_Immutably_Limited_Type (Typ) then
459 (Prim => Adjust_Case,
461 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
466 (Prim => Finalize_Case,
468 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
470 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
471 -- .NET do not support address arithmetic and unchecked conversions.
473 if VM_Target = No_VM then
476 (Prim => Address_Case,
478 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
480 end Build_Array_Deep_Procs;
482 ------------------------------
483 -- Build_Cleanup_Statements --
484 ------------------------------
486 function Build_Cleanup_Statements (N : Node_Id) return List_Id is
487 Is_Asynchronous_Call : constant Boolean :=
488 Nkind (N) = N_Block_Statement
489 and then Is_Asynchronous_Call_Block (N);
490 Is_Master : constant Boolean :=
491 Nkind (N) /= N_Entry_Body
492 and then Is_Task_Master (N);
493 Is_Protected_Body : constant Boolean :=
494 Nkind (N) = N_Subprogram_Body
495 and then Is_Protected_Subprogram_Body (N);
496 Is_Task_Allocation : constant Boolean :=
497 Nkind (N) = N_Block_Statement
498 and then Is_Task_Allocation_Block (N);
499 Is_Task_Body : constant Boolean :=
500 Nkind (Original_Node (N)) = N_Task_Body;
502 Loc : constant Source_Ptr := Sloc (N);
503 Stmts : constant List_Id := New_List;
507 if Restricted_Profile then
509 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
511 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
515 if Restriction_Active (No_Task_Hierarchy) = False then
516 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
519 -- Add statements to unlock the protected object parameter and to
520 -- undefer abort. If the context is a protected procedure and the object
521 -- has entries, call the entry service routine.
523 -- NOTE: The generated code references _object, a parameter to the
526 elsif Is_Protected_Body then
528 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
529 Conc_Typ : Entity_Id;
532 Param_Typ : Entity_Id;
535 -- Find the _object parameter representing the protected object
537 Param := First (Parameter_Specifications (Spec));
539 Param_Typ := Etype (Parameter_Type (Param));
541 if Ekind (Param_Typ) = E_Record_Type then
542 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
545 exit when No (Param) or else Present (Conc_Typ);
549 pragma Assert (Present (Param));
551 -- If the associated protected object has entries, a protected
552 -- procedure has to service entry queues. In this case generate:
554 -- Service_Entries (_object._object'Access);
556 if Nkind (Specification (N)) = N_Procedure_Specification
557 and then Has_Entries (Conc_Typ)
559 case Corresponding_Runtime_Package (Conc_Typ) is
560 when System_Tasking_Protected_Objects_Entries =>
561 Nam := New_Reference_To (RTE (RE_Service_Entries), Loc);
563 when System_Tasking_Protected_Objects_Single_Entry =>
564 Nam := New_Reference_To (RTE (RE_Service_Entry), Loc);
571 Make_Procedure_Call_Statement (Loc,
573 Parameter_Associations => New_List (
574 Make_Attribute_Reference (Loc,
576 Make_Selected_Component (Loc,
577 Prefix => New_Reference_To (
578 Defining_Identifier (Param), Loc),
580 Make_Identifier (Loc, Name_uObject)),
581 Attribute_Name => Name_Unchecked_Access))));
585 -- Unlock (_object._object'Access);
587 case Corresponding_Runtime_Package (Conc_Typ) is
588 when System_Tasking_Protected_Objects_Entries =>
589 Nam := New_Reference_To (RTE (RE_Unlock_Entries), Loc);
591 when System_Tasking_Protected_Objects_Single_Entry =>
592 Nam := New_Reference_To (RTE (RE_Unlock_Entry), Loc);
594 when System_Tasking_Protected_Objects =>
595 Nam := New_Reference_To (RTE (RE_Unlock), Loc);
602 Make_Procedure_Call_Statement (Loc,
604 Parameter_Associations => New_List (
605 Make_Attribute_Reference (Loc,
607 Make_Selected_Component (Loc,
610 (Defining_Identifier (Param), Loc),
612 Make_Identifier (Loc, Name_uObject)),
613 Attribute_Name => Name_Unchecked_Access))));
619 if Abort_Allowed then
621 Make_Procedure_Call_Statement (Loc,
623 New_Reference_To (RTE (RE_Abort_Undefer), Loc),
624 Parameter_Associations => Empty_List));
628 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
629 -- tasks. Other unactivated tasks are completed by Complete_Task or
632 -- NOTE: The generated code references _chain, a local object
634 elsif Is_Task_Allocation then
637 -- Expunge_Unactivated_Tasks (_chain);
639 -- where _chain is the list of tasks created by the allocator but not
640 -- yet activated. This list will be empty unless the block completes
644 Make_Procedure_Call_Statement (Loc,
647 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
648 Parameter_Associations => New_List (
649 New_Reference_To (Activation_Chain_Entity (N), Loc))));
651 -- Attempt to cancel an asynchronous entry call whenever the block which
652 -- contains the abortable part is exited.
654 -- NOTE: The generated code references Cnn, a local object
656 elsif Is_Asynchronous_Call then
658 Cancel_Param : constant Entity_Id :=
659 Entry_Cancel_Parameter (Entity (Identifier (N)));
662 -- If it is of type Communication_Block, this must be a protected
663 -- entry call. Generate:
665 -- if Enqueued (Cancel_Param) then
666 -- Cancel_Protected_Entry_Call (Cancel_Param);
669 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
671 Make_If_Statement (Loc,
673 Make_Function_Call (Loc,
675 New_Reference_To (RTE (RE_Enqueued), Loc),
676 Parameter_Associations => New_List (
677 New_Reference_To (Cancel_Param, Loc))),
679 Then_Statements => New_List (
680 Make_Procedure_Call_Statement (Loc,
683 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
684 Parameter_Associations => New_List (
685 New_Reference_To (Cancel_Param, Loc))))));
687 -- Asynchronous delay, generate:
688 -- Cancel_Async_Delay (Cancel_Param);
690 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
692 Make_Procedure_Call_Statement (Loc,
694 New_Reference_To (RTE (RE_Cancel_Async_Delay), Loc),
695 Parameter_Associations => New_List (
696 Make_Attribute_Reference (Loc,
698 New_Reference_To (Cancel_Param, Loc),
699 Attribute_Name => Name_Unchecked_Access))));
701 -- Task entry call, generate:
702 -- Cancel_Task_Entry_Call (Cancel_Param);
706 Make_Procedure_Call_Statement (Loc,
708 New_Reference_To (RTE (RE_Cancel_Task_Entry_Call), Loc),
709 Parameter_Associations => New_List (
710 New_Reference_To (Cancel_Param, Loc))));
716 end Build_Cleanup_Statements;
718 -----------------------------
719 -- Build_Controlling_Procs --
720 -----------------------------
722 procedure Build_Controlling_Procs (Typ : Entity_Id) is
724 if Is_Array_Type (Typ) then
725 Build_Array_Deep_Procs (Typ);
726 else pragma Assert (Is_Record_Type (Typ));
727 Build_Record_Deep_Procs (Typ);
729 end Build_Controlling_Procs;
731 -----------------------------
732 -- Build_Exception_Handler --
733 -----------------------------
735 function Build_Exception_Handler
738 Raised_Id : Entity_Id;
739 For_Library : Boolean := False) return Node_Id
742 Proc_To_Call : Entity_Id;
745 pragma Assert (Present (E_Id));
746 pragma Assert (Present (Raised_Id));
749 -- Get_Current_Excep.all.all
751 Actuals := New_List (
752 Make_Explicit_Dereference (Loc,
754 Make_Function_Call (Loc,
756 Make_Explicit_Dereference (Loc,
758 New_Reference_To (RTE (RE_Get_Current_Excep), Loc)))));
760 if For_Library and then not Restricted_Profile then
761 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
764 Proc_To_Call := RTE (RE_Save_Occurrence);
765 Prepend_To (Actuals, New_Reference_To (E_Id, Loc));
770 -- if not Raised_Id then
771 -- Raised_Id := True;
773 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
775 -- Save_Library_Occurrence (Get_Current_Excep.all.all);
779 Make_Exception_Handler (Loc,
780 Exception_Choices => New_List (
781 Make_Others_Choice (Loc)),
783 Statements => New_List (
784 Make_If_Statement (Loc,
787 Right_Opnd => New_Reference_To (Raised_Id, Loc)),
789 Then_Statements => New_List (
790 Make_Assignment_Statement (Loc,
791 Name => New_Reference_To (Raised_Id, Loc),
792 Expression => New_Reference_To (Standard_True, Loc)),
794 Make_Procedure_Call_Statement (Loc,
796 New_Reference_To (Proc_To_Call, Loc),
797 Parameter_Associations => Actuals)))));
798 end Build_Exception_Handler;
800 -----------------------------------
801 -- Build_Finalization_Collection --
802 -----------------------------------
804 procedure Build_Finalization_Collection
806 Ins_Node : Node_Id := Empty;
807 Encl_Scope : Entity_Id := Empty)
809 Desig_Typ : constant Entity_Id := Directly_Designated_Type (Typ);
811 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
812 -- Determine whether entity E is inside a wrapper package created for
813 -- an instance of Ada.Unchecked_Deallocation.
815 ------------------------------
816 -- In_Deallocation_Instance --
817 ------------------------------
819 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
820 Pkg : constant Entity_Id := Scope (E);
821 Par : Node_Id := Empty;
824 if Ekind (Pkg) = E_Package
825 and then Present (Related_Instance (Pkg))
826 and then Ekind (Related_Instance (Pkg)) = E_Procedure
828 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
832 and then Chars (Par) = Name_Unchecked_Deallocation
833 and then Chars (Scope (Par)) = Name_Ada
834 and then Scope (Scope (Par)) = Standard_Standard;
838 end In_Deallocation_Instance;
840 -- Start of processing for Build_Finalization_Collection
843 -- Certain run-time configurations and targets do not provide support
844 -- for controlled types.
846 if Restriction_Active (No_Finalization) then
849 -- Various machinery such as freezing may have already created a
852 elsif Present (Associated_Collection (Typ)) then
855 -- Do not process types that return on the secondary stack
857 -- ??? The need for a secondary stack should be revisited and perhaps
860 elsif Present (Associated_Storage_Pool (Typ))
861 and then Is_RTE (Associated_Storage_Pool (Typ), RE_SS_Pool)
865 -- Do not process types which may never allocate an object
867 elsif No_Pool_Assigned (Typ) then
870 -- Do not process access types coming from Ada.Unchecked_Deallocation
871 -- instances. Even though the designated type may be controlled, the
872 -- access type will never participate in allocation.
874 elsif In_Deallocation_Instance (Typ) then
877 -- Ignore the general use of anonymous access types unless the context
878 -- requires a collection.
880 elsif Ekind (Typ) = E_Anonymous_Access_Type
881 and then No (Ins_Node)
885 -- Do not process non-library access types when restriction No_Nested_
886 -- Finalization is in effect since collections are controlled objects.
888 elsif Restriction_Active (No_Nested_Finalization)
889 and then not Is_Library_Level_Entity (Typ)
893 -- For .NET/JVM targets, allow the processing of access-to-controlled
894 -- types where the designated type is explicitly derived from [Limited_]
897 elsif VM_Target /= No_VM
898 and then not Is_Controlled (Desig_Typ)
904 Loc : constant Source_Ptr := Sloc (Typ);
905 Actions : constant List_Id := New_List;
911 -- Fnn : Finalization_Collection;
913 -- Source access types use fixed names for their collections since
914 -- the collection is inserted only once in the same source unit and
915 -- there is no possible name overlap. Internally-generated access
916 -- types on the other hand use temporaries as collection names due
917 -- to possible name collisions.
919 if Comes_From_Source (Typ) then
921 Make_Defining_Identifier (Loc,
922 Chars => New_External_Name (Chars (Typ), "FC"));
924 Coll_Id := Make_Temporary (Loc, 'F');
928 Make_Object_Declaration (Loc,
929 Defining_Identifier => Coll_Id,
931 New_Reference_To (RTE (RE_Finalization_Collection), Loc)));
933 -- Storage pool selection and attribute decoration of the generated
934 -- collection. Since .NET/JVM compilers do not support pools, this
937 if VM_Target = No_VM then
939 -- If the access type has a user-defined pool, use it as the base
940 -- storage medium for the finalization pool.
942 if Present (Associated_Storage_Pool (Typ)) then
943 Pool_Id := Associated_Storage_Pool (Typ);
945 -- Access subtypes must use the storage pool of their base type
947 elsif Ekind (Typ) = E_Access_Subtype then
949 Base_Typ : constant Entity_Id := Base_Type (Typ);
952 if No (Associated_Storage_Pool (Base_Typ)) then
953 Pool_Id := Get_Global_Pool_For_Access_Type (Base_Typ);
954 Set_Associated_Storage_Pool (Base_Typ, Pool_Id);
956 Pool_Id := Associated_Storage_Pool (Base_Typ);
960 -- The default choice is the global pool
963 Pool_Id := Get_Global_Pool_For_Access_Type (Typ);
964 Set_Associated_Storage_Pool (Typ, Pool_Id);
968 -- Set_Storage_Pool_Ptr (Fnn, Pool_Id'Unchecked_Access);
971 Make_Procedure_Call_Statement (Loc,
973 New_Reference_To (RTE (RE_Set_Storage_Pool_Ptr), Loc),
974 Parameter_Associations => New_List (
975 New_Reference_To (Coll_Id, Loc),
976 Make_Attribute_Reference (Loc,
977 Prefix => New_Reference_To (Pool_Id, Loc),
978 Attribute_Name => Name_Unrestricted_Access))));
981 Set_Associated_Collection (Typ, Coll_Id);
983 -- A finalization collection created for an anonymous access type
984 -- must be inserted before a context-dependent node.
986 if Present (Ins_Node) then
987 Push_Scope (Encl_Scope);
989 -- Treat use clauses as declarations and insert directly in front
992 if Nkind_In (Ins_Node, N_Use_Package_Clause,
995 Insert_List_Before_And_Analyze (Ins_Node, Actions);
997 Insert_Actions (Ins_Node, Actions);
1002 elsif Ekind (Typ) = E_Access_Subtype
1003 or else (Ekind (Desig_Typ) = E_Incomplete_Type
1004 and then Has_Completion_In_Body (Desig_Typ))
1006 Insert_Actions (Parent (Typ), Actions);
1008 -- If the designated type is not yet frozen, then append the actions
1009 -- to that type's freeze actions. The actions need to be appended to
1010 -- whichever type is frozen later, similarly to what Freeze_Type does
1011 -- for appending the storage pool declaration for an access type.
1012 -- Otherwise, the call to Set_Storage_Pool_Ptr might reference the
1013 -- pool object before it's declared. However, it's not clear that
1014 -- this is exactly the right test to accomplish that here. ???
1016 elsif Present (Freeze_Node (Desig_Typ))
1017 and then not Analyzed (Freeze_Node (Desig_Typ))
1019 Append_Freeze_Actions (Desig_Typ, Actions);
1021 elsif Present (Freeze_Node (Typ))
1022 and then not Analyzed (Freeze_Node (Typ))
1024 Append_Freeze_Actions (Typ, Actions);
1026 -- If there's a pool created locally for the access type, then we
1027 -- need to ensure that the collection gets created after the pool
1028 -- object, because otherwise we can have a forward reference, so
1029 -- we force the collection actions to be inserted and analyzed after
1030 -- the pool entity. Note that both the access type and its designated
1031 -- type may have already been frozen and had their freezing actions
1032 -- analyzed at this point. (This seems a little unclean.???)
1034 elsif VM_Target = No_VM
1035 and then Scope (Pool_Id) = Scope (Typ)
1037 Insert_List_After_And_Analyze (Parent (Pool_Id), Actions);
1040 Insert_Actions (Parent (Typ), Actions);
1043 end Build_Finalization_Collection;
1045 ---------------------
1046 -- Build_Finalizer --
1047 ---------------------
1049 procedure Build_Finalizer
1051 Clean_Stmts : List_Id;
1052 Mark_Id : Entity_Id;
1053 Top_Decls : List_Id;
1054 Defer_Abort : Boolean;
1055 Fin_Id : out Entity_Id)
1057 Acts_As_Clean : constant Boolean :=
1060 (Present (Clean_Stmts)
1061 and then Is_Non_Empty_List (Clean_Stmts));
1062 Exceptions_OK : constant Boolean :=
1063 not Restriction_Active (No_Exception_Propagation);
1064 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1065 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1066 For_Package : constant Boolean :=
1067 For_Package_Body or else For_Package_Spec;
1068 Loc : constant Source_Ptr := Sloc (N);
1070 -- NOTE: Local variable declarations are conservative and do not create
1071 -- structures right from the start. Entities and lists are created once
1072 -- it has been established that N has at least one controlled object.
1074 Abort_Id : Entity_Id := Empty;
1075 -- Entity of local flag. The flag is set when finalization is triggered
1078 Components_Built : Boolean := False;
1079 -- A flag used to avoid double initialization of entities and lists. If
1080 -- the flag is set then the following variables have been initialized:
1090 Counter_Id : Entity_Id := Empty;
1091 Counter_Val : Int := 0;
1092 -- Name and value of the state counter
1094 Decls : List_Id := No_List;
1095 -- Declarative region of N (if available). If N is a package declaration
1096 -- Decls denotes the visible declarations.
1098 E_Id : Entity_Id := Empty;
1099 -- Entity of the local exception occurence. The first exception which
1100 -- occurred during finalization is stored in E_Id and later reraised.
1102 Finalizer_Decls : List_Id := No_List;
1103 -- Local variable declarations. This list holds the label declarations
1104 -- of all jump block alternatives as well as the declaration of the
1105 -- local exception occurence and the raised flag.
1107 -- E : Exception_Occurrence;
1108 -- Raised : Boolean := False;
1109 -- L<counter value> : label;
1111 Finalizer_Insert_Nod : Node_Id := Empty;
1112 -- Insertion point for the finalizer body. Depending on the context
1113 -- (Nkind of N) and the individual grouping of controlled objects, this
1114 -- node may denote a package declaration or body, package instantiation,
1115 -- block statement or a counter update statement.
1117 Finalizer_Stmts : List_Id := No_List;
1118 -- The statement list of the finalizer body. It contains the following:
1120 -- Abort_Defer; -- Added if abort is allowed
1121 -- <call to Prev_At_End> -- Added if exists
1122 -- <cleanup statements> -- Added if Acts_As_Clean
1123 -- <jump block> -- Added if Has_Ctrl_Objs
1124 -- <finalization statements> -- Added if Has_Ctrl_Objs
1125 -- <stack release> -- Added if Mark_Id exists
1126 -- Abort_Undefer; -- Added if abort is allowed
1128 Has_Ctrl_Objs : Boolean := False;
1129 -- A general flag which denotes whether N has at least one controlled
1132 Has_Tagged_Types : Boolean := False;
1133 -- A general flag which indicates whether N has at least one library-
1134 -- level tagged type declaration.
1136 HSS : Node_Id := Empty;
1137 -- The sequence of statements of N (if available)
1139 Jump_Alts : List_Id := No_List;
1140 -- Jump block alternatives. Depending on the value of the state counter,
1141 -- the control flow jumps to a sequence of finalization statments. This
1142 -- list contains the following:
1144 -- when <counter value> =>
1145 -- goto L<counter value>;
1147 Jump_Block_Insert_Nod : Node_Id := Empty;
1148 -- Specific point in the finalizer statements where the jump block is
1151 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1152 -- The last controlled construct encountered when processing the top
1153 -- level lists of N. This can be a nested package, an instantiation or
1154 -- an object declaration.
1156 Prev_At_End : Entity_Id := Empty;
1157 -- The previous at end procedure of the handled statements block of N
1159 Priv_Decls : List_Id := No_List;
1160 -- The private declarations of N if N is a package declaration
1162 Raised_Id : Entity_Id := Empty;
1163 -- Entity for the raised flag. Along with E_Id, the flag is used in the
1164 -- propagation of exceptions which occur during finalization.
1166 Spec_Id : Entity_Id := Empty;
1167 Spec_Decls : List_Id := Top_Decls;
1168 Stmts : List_Id := No_List;
1170 Tagged_Type_Stmts : List_Id := No_List;
1171 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1172 -- tagged types found in N.
1174 -----------------------
1175 -- Local subprograms --
1176 -----------------------
1178 procedure Build_Components;
1179 -- Create all entites and initialize all lists used in the creation of
1182 procedure Create_Finalizer;
1183 -- Create the spec and body of the finalizer and insert them in the
1184 -- proper place in the tree depending on the context.
1186 procedure Process_Declarations
1188 Preprocess : Boolean := False;
1189 Top_Level : Boolean := False);
1190 -- Inspect a list of declarations or statements which may contain
1191 -- objects that need finalization. When flag Preprocess is set, the
1192 -- routine will simply count the total number of controlled objects in
1193 -- Decls. Flag Top_Level denotes whether the processing is done for
1194 -- objects in nested package declarations or instances.
1196 procedure Process_Object_Declaration
1198 Has_No_Init : Boolean := False;
1199 Is_Protected : Boolean := False);
1200 -- Generate all the machinery associated with the finalization of a
1201 -- single object. Flag Has_No_Init is used to denote certain contexts
1202 -- where Decl does not have initialization call(s). Flag Is_Protected
1203 -- is set when Decl denotes a simple protected object.
1205 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1206 -- Generate all the code necessary to unregister the external tag of a
1209 ----------------------
1210 -- Build_Components --
1211 ----------------------
1213 procedure Build_Components is
1214 Counter_Decl : Node_Id;
1215 Counter_Typ : Entity_Id;
1216 Counter_Typ_Decl : Node_Id;
1219 pragma Assert (Present (Decls));
1221 -- This routine might be invoked several times when dealing with
1222 -- constructs that have two lists (either two declarative regions
1223 -- or declarations and statements). Avoid double initialization.
1225 if Components_Built then
1229 Components_Built := True;
1231 if Has_Ctrl_Objs then
1233 -- Create entities for the counter, its type, the local exception
1234 -- and the raised flag.
1236 Counter_Id := Make_Temporary (Loc, 'C');
1237 Counter_Typ := Make_Temporary (Loc, 'T');
1239 if Exceptions_OK then
1240 Abort_Id := Make_Temporary (Loc, 'A');
1241 E_Id := Make_Temporary (Loc, 'E');
1242 Raised_Id := Make_Temporary (Loc, 'R');
1245 -- Since the total number of controlled objects is always known,
1246 -- build a subtype of Natural with precise bounds. This allows
1247 -- the backend to optimize the case statement. Generate:
1249 -- subtype Tnn is Natural range 0 .. Counter_Val;
1252 Make_Subtype_Declaration (Loc,
1253 Defining_Identifier => Counter_Typ,
1254 Subtype_Indication =>
1255 Make_Subtype_Indication (Loc,
1256 Subtype_Mark => New_Reference_To (Standard_Natural, Loc),
1258 Make_Range_Constraint (Loc,
1262 Make_Integer_Literal (Loc, Uint_0),
1264 Make_Integer_Literal (Loc, Counter_Val)))));
1266 -- Generate the declaration of the counter itself:
1268 -- Counter : Integer := 0;
1271 Make_Object_Declaration (Loc,
1272 Defining_Identifier => Counter_Id,
1273 Object_Definition => New_Reference_To (Counter_Typ, Loc),
1274 Expression => Make_Integer_Literal (Loc, 0));
1276 -- Set the type of the counter explicitly to prevent errors when
1277 -- examining object declarations later on.
1279 Set_Etype (Counter_Id, Counter_Typ);
1281 -- The counter and its type are inserted before the source
1282 -- declarations of N.
1284 Prepend_To (Decls, Counter_Decl);
1285 Prepend_To (Decls, Counter_Typ_Decl);
1287 -- The counter and its associated type must be manually analized
1288 -- since N has already been analyzed. Use the scope of the spec
1289 -- when inserting in a package.
1292 Push_Scope (Spec_Id);
1293 Analyze (Counter_Typ_Decl);
1294 Analyze (Counter_Decl);
1298 Analyze (Counter_Typ_Decl);
1299 Analyze (Counter_Decl);
1302 Finalizer_Decls := New_List;
1303 Jump_Alts := New_List;
1306 -- If the context requires additional clean up, the finalization
1307 -- machinery is added after the clean up code.
1309 if Acts_As_Clean then
1310 Finalizer_Stmts := Clean_Stmts;
1311 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1313 Finalizer_Stmts := New_List;
1316 if Has_Tagged_Types then
1317 Tagged_Type_Stmts := New_List;
1319 end Build_Components;
1321 ----------------------
1322 -- Create_Finalizer --
1323 ----------------------
1325 procedure Create_Finalizer is
1326 Body_Id : Entity_Id;
1329 Jump_Block : Node_Id;
1331 Label_Id : Entity_Id;
1333 function New_Finalizer_Name return Name_Id;
1334 -- Create a fully qualified name of a package spec or body finalizer.
1335 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1337 ------------------------
1338 -- New_Finalizer_Name --
1339 ------------------------
1341 function New_Finalizer_Name return Name_Id is
1342 procedure New_Finalizer_Name (Id : Entity_Id);
1343 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1344 -- has a non-standard scope, process the scope first.
1346 ------------------------
1347 -- New_Finalizer_Name --
1348 ------------------------
1350 procedure New_Finalizer_Name (Id : Entity_Id) is
1352 if Scope (Id) = Standard_Standard then
1353 Get_Name_String (Chars (Id));
1356 New_Finalizer_Name (Scope (Id));
1357 Add_Str_To_Name_Buffer ("__");
1358 Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1360 end New_Finalizer_Name;
1362 -- Start of processing for New_Finalizer_Name
1365 -- Create the fully qualified name of the enclosing scope
1367 New_Finalizer_Name (Spec_Id);
1370 -- __finalize_[spec|body]
1372 Add_Str_To_Name_Buffer ("__finalize_");
1374 if For_Package_Spec then
1375 Add_Str_To_Name_Buffer ("spec");
1377 Add_Str_To_Name_Buffer ("body");
1381 end New_Finalizer_Name;
1383 -- Start of processing for Create_Finalizer
1386 -- Step 1: Creation of the finalizer name
1388 -- Packages must use a distinct name for their finalizers since the
1389 -- binder will have to generate calls to them by name. The name is
1390 -- of the following form:
1392 -- xx__yy__finalize_[spec|body]
1395 Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1396 Set_Has_Qualified_Name (Fin_Id);
1397 Set_Has_Fully_Qualified_Name (Fin_Id);
1399 -- The default name is _finalizer
1403 Make_Defining_Identifier (Loc,
1404 Chars => New_External_Name (Name_uFinalizer));
1407 -- Step 2: Creation of the finalizer specification
1410 -- procedure Fin_Id;
1413 Make_Subprogram_Declaration (Loc,
1415 Make_Procedure_Specification (Loc,
1416 Defining_Unit_Name => Fin_Id));
1418 -- Step 3: Creation of the finalizer body
1420 if Has_Ctrl_Objs then
1422 -- Add L0, the default destination to the jump block
1424 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1425 Set_Entity (Label_Id,
1426 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1427 Label := Make_Label (Loc, Label_Id);
1432 Prepend_To (Finalizer_Decls,
1433 Make_Implicit_Label_Declaration (Loc,
1434 Defining_Identifier => Entity (Label_Id),
1435 Label_Construct => Label));
1441 Append_To (Jump_Alts,
1442 Make_Case_Statement_Alternative (Loc,
1443 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1444 Statements => New_List (
1445 Make_Goto_Statement (Loc,
1446 Name => New_Reference_To (Entity (Label_Id), Loc)))));
1451 Append_To (Finalizer_Stmts, Label);
1453 -- The local exception does not need to be reraised for library-
1454 -- level finalizers. Generate:
1457 -- Raise_From_Controlled_Operation (E, Abort);
1461 and then Exceptions_OK
1463 Append_To (Finalizer_Stmts,
1464 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
1467 -- Create the jump block which controls the finalization flow
1468 -- depending on the value of the state counter.
1471 Make_Case_Statement (Loc,
1472 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
1473 Alternatives => Jump_Alts);
1476 and then Present (Jump_Block_Insert_Nod)
1478 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1480 Prepend_To (Finalizer_Stmts, Jump_Block);
1484 -- Add the library-level tagged type unregistration machinery before
1485 -- the jump block circuitry. This ensures that external tags will be
1486 -- removed even if a finalization exception occurs at some point.
1488 if Has_Tagged_Types then
1489 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1492 -- Add a call to the previous At_End handler if it exists. The call
1493 -- must always precede the jump block.
1495 if Present (Prev_At_End) then
1496 Prepend_To (Finalizer_Stmts,
1497 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1499 -- Clear the At_End handler since we have already generated the
1500 -- proper replacement call for it.
1502 Set_At_End_Proc (HSS, Empty);
1505 -- Release the secondary stack mark
1507 if Present (Mark_Id) then
1508 Append_To (Finalizer_Stmts,
1509 Make_Procedure_Call_Statement (Loc,
1511 New_Reference_To (RTE (RE_SS_Release), Loc),
1512 Parameter_Associations => New_List (
1513 New_Reference_To (Mark_Id, Loc))));
1516 -- Protect the statements with abort defer/undefer. This is only when
1517 -- aborts are allowed and the clean up statements require deferral or
1518 -- there are controlled objects to be finalized.
1522 (Defer_Abort or else Has_Ctrl_Objs)
1524 Prepend_To (Finalizer_Stmts,
1525 Make_Procedure_Call_Statement (Loc,
1526 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc)));
1528 Append_To (Finalizer_Stmts,
1529 Make_Procedure_Call_Statement (Loc,
1530 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
1534 -- procedure Fin_Id is
1535 -- Abort : constant Boolean :=
1536 -- Exception_Occurrence (Get_Current_Excep.all.all) =
1537 -- Standard'Abort_Signal'Identity;
1539 -- Abort : constant Boolean := False; -- no abort
1541 -- E : Exception_Occurrence; -- All added if flag
1542 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1548 -- Abort_Defer; -- Added if abort is allowed
1549 -- <call to Prev_At_End> -- Added if exists
1550 -- <cleanup statements> -- Added if Acts_As_Clean
1551 -- <jump block> -- Added if Has_Ctrl_Objs
1552 -- <finalization statements> -- Added if Has_Ctrl_Objs
1553 -- <stack release> -- Added if Mark_Id exists
1554 -- Abort_Undefer; -- Added if abort is allowed
1558 and then Exceptions_OK
1560 Prepend_List_To (Finalizer_Decls,
1561 Build_Object_Declarations
1562 (Loc, Abort_Id, E_Id, Raised_Id, For_Package));
1565 -- Create the body of the finalizer
1567 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1570 Set_Has_Qualified_Name (Body_Id);
1571 Set_Has_Fully_Qualified_Name (Body_Id);
1575 Make_Subprogram_Body (Loc,
1577 Make_Procedure_Specification (Loc,
1578 Defining_Unit_Name => Body_Id),
1580 Declarations => Finalizer_Decls,
1582 Handled_Statement_Sequence =>
1583 Make_Handled_Sequence_Of_Statements (Loc, Finalizer_Stmts));
1585 -- Step 4: Spec and body insertion, analysis
1589 -- If the package spec has private declarations, the finalizer
1590 -- body must be added to the end of the list in order to have
1591 -- visibility of all private controlled objects.
1593 if For_Package_Spec then
1594 if Present (Priv_Decls) then
1595 Append_To (Priv_Decls, Fin_Spec);
1596 Append_To (Priv_Decls, Fin_Body);
1598 Append_To (Decls, Fin_Spec);
1599 Append_To (Decls, Fin_Body);
1602 -- For package bodies, both the finalizer spec and body are
1603 -- inserted at the end of the package declarations.
1606 Append_To (Decls, Fin_Spec);
1607 Append_To (Decls, Fin_Body);
1610 -- Push the name of the package
1612 Push_Scope (Spec_Id);
1620 -- Create the spec for the finalizer. The At_End handler must be
1621 -- able to call the body which resides in a nested structure.
1625 -- procedure Fin_Id; -- Spec
1627 -- <objects and possibly statements>
1628 -- procedure Fin_Id is ... -- Body
1631 -- Fin_Id; -- At_End handler
1634 pragma Assert (Present (Spec_Decls));
1636 Append_To (Spec_Decls, Fin_Spec);
1639 -- When the finalizer acts solely as a clean up routine, the body
1640 -- is inserted right after the spec.
1643 and then not Has_Ctrl_Objs
1645 Insert_After (Fin_Spec, Fin_Body);
1647 -- In all other cases the body is inserted after either:
1649 -- 1) The counter update statement of the last controlled object
1650 -- 2) The last top level nested controlled package
1651 -- 3) The last top level controlled instantiation
1654 -- Manually freeze the spec. This is somewhat of a hack because
1655 -- a subprogram is frozen when its body is seen and the freeze
1656 -- node appears right before the body. However, in this case,
1657 -- the spec must be frozen earlier since the At_End handler
1658 -- must be able to call it.
1661 -- procedure Fin_Id; -- Spec
1662 -- [Fin_Id] -- Freeze node
1666 -- Fin_Id; -- At_End handler
1669 Ensure_Freeze_Node (Fin_Id);
1670 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1671 Set_Is_Frozen (Fin_Id);
1673 -- In the case where the last construct to contain a controlled
1674 -- object is either a nested package, an instantiation or a
1675 -- freeze node, the body must be inserted directly after the
1678 if Nkind_In (Last_Top_Level_Ctrl_Construct,
1680 N_Package_Declaration,
1683 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1686 Insert_After (Finalizer_Insert_Nod, Fin_Body);
1691 end Create_Finalizer;
1693 --------------------------
1694 -- Process_Declarations --
1695 --------------------------
1697 procedure Process_Declarations
1699 Preprocess : Boolean := False;
1700 Top_Level : Boolean := False)
1705 Obj_Typ : Entity_Id;
1706 Pack_Id : Entity_Id;
1710 Old_Counter_Val : Int;
1711 -- This variable is used to determine whether a nested package or
1712 -- instance contains at least one controlled object.
1714 procedure Processing_Actions
1715 (Has_No_Init : Boolean := False;
1716 Is_Protected : Boolean := False);
1717 -- Depending on the mode of operation of Process_Declarations, either
1718 -- increment the controlled object counter, set the controlled object
1719 -- flag and store the last top level construct or process the current
1720 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1721 -- the current declaration may not have initialization proc(s). Flag
1722 -- Is_Protected should be set when the current declaration denotes a
1723 -- simple protected object.
1725 ------------------------
1726 -- Processing_Actions --
1727 ------------------------
1729 procedure Processing_Actions
1730 (Has_No_Init : Boolean := False;
1731 Is_Protected : Boolean := False)
1734 -- Library-level tagged type
1736 if Nkind (Decl) = N_Full_Type_Declaration then
1738 Has_Tagged_Types := True;
1741 and then No (Last_Top_Level_Ctrl_Construct)
1743 Last_Top_Level_Ctrl_Construct := Decl;
1747 Process_Tagged_Type_Declaration (Decl);
1750 -- Controlled object declaration
1754 Counter_Val := Counter_Val + 1;
1755 Has_Ctrl_Objs := True;
1758 and then No (Last_Top_Level_Ctrl_Construct)
1760 Last_Top_Level_Ctrl_Construct := Decl;
1764 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
1767 end Processing_Actions;
1769 -- Start of processing for Process_Declarations
1772 if No (Decls) or else Is_Empty_List (Decls) then
1776 -- Process all declarations in reverse order
1778 Decl := Last_Non_Pragma (Decls);
1779 while Present (Decl) loop
1781 -- Library-level tagged types
1783 if Nkind (Decl) = N_Full_Type_Declaration then
1784 Typ := Defining_Identifier (Decl);
1786 if Is_Tagged_Type (Typ)
1787 and then Is_Library_Level_Entity (Typ)
1788 and then Convention (Typ) = Convention_Ada
1789 and then Present (Access_Disp_Table (Typ))
1790 and then RTE_Available (RE_Register_Tag)
1791 and then not No_Run_Time_Mode
1792 and then not Is_Abstract_Type (Typ)
1797 -- Regular object declarations
1799 elsif Nkind (Decl) = N_Object_Declaration then
1800 Obj_Id := Defining_Identifier (Decl);
1801 Obj_Typ := Base_Type (Etype (Obj_Id));
1802 Expr := Expression (Decl);
1804 -- Bypass any form of processing for objects which have their
1805 -- finalization disabled. This applies only to objects at the
1809 and then Finalize_Storage_Only (Obj_Typ)
1813 -- Transient variables are treated separately in order to
1814 -- minimize the size of the generated code. See Process_
1815 -- Transient_Objects.
1817 elsif Is_Processed_Transient (Obj_Id) then
1820 -- The object is of the form:
1821 -- Obj : Typ [:= Expr];
1823 -- Do not process the incomplete view of a deferred constant.
1824 -- Do not consider tag-to-class-wide conversions.
1826 elsif not Is_Imported (Obj_Id)
1827 and then Needs_Finalization (Obj_Typ)
1828 and then not (Ekind (Obj_Id) = E_Constant
1829 and then not Has_Completion (Obj_Id))
1830 and then not Is_Tag_To_CW_Conversion (Obj_Id)
1834 -- The object is of the form:
1835 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1837 -- Obj : Access_Typ :=
1838 -- BIP_Function_Call
1839 -- (..., BIPaccess => null, ...)'reference;
1841 elsif Is_Access_Type (Obj_Typ)
1842 and then Needs_Finalization
1843 (Available_View (Designated_Type (Obj_Typ)))
1844 and then Present (Expr)
1846 (Is_Null_Access_BIP_Func_Call (Expr)
1847 or else (Is_Non_BIP_Func_Call (Expr)
1849 Is_Related_To_Func_Return (Obj_Id)))
1851 Processing_Actions (Has_No_Init => True);
1853 -- Processing for "hook" objects generated for controlled
1854 -- transients declared inside an Expression_With_Actions.
1856 elsif Is_Access_Type (Obj_Typ)
1857 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1858 and then Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
1859 N_Object_Declaration
1860 and then Is_Finalizable_Transient
1861 (Return_Flag_Or_Transient_Decl (Obj_Id), Decl)
1863 Processing_Actions (Has_No_Init => True);
1865 -- Simple protected objects which use type System.Tasking.
1866 -- Protected_Objects.Protection to manage their locks should
1867 -- be treated as controlled since they require manual cleanup.
1868 -- The only exception is illustrated in the following example:
1871 -- type Ctrl is new Controlled ...
1872 -- procedure Finalize (Obj : in out Ctrl);
1876 -- package body Pkg is
1877 -- protected Prot is
1878 -- procedure Do_Something (Obj : in out Ctrl);
1881 -- protected body Prot is
1882 -- procedure Do_Something (Obj : in out Ctrl) is ...
1885 -- procedure Finalize (Obj : in out Ctrl) is
1887 -- Prot.Do_Something (Obj);
1891 -- Since for the most part entities in package bodies depend on
1892 -- those in package specs, Prot's lock should be cleaned up
1893 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1894 -- This act however attempts to invoke Do_Something and fails
1895 -- because the lock has disappeared.
1897 elsif Ekind (Obj_Id) = E_Variable
1898 and then not In_Library_Level_Package_Body (Obj_Id)
1900 (Is_Simple_Protected_Type (Obj_Typ)
1901 or else Has_Simple_Protected_Object (Obj_Typ))
1903 Processing_Actions (Is_Protected => True);
1906 -- Specific cases of object renamings
1908 elsif Nkind (Decl) = N_Object_Renaming_Declaration
1909 and then Nkind (Name (Decl)) = N_Explicit_Dereference
1910 and then Nkind (Prefix (Name (Decl))) = N_Identifier
1912 Obj_Id := Defining_Identifier (Decl);
1913 Obj_Typ := Base_Type (Etype (Obj_Id));
1915 -- Bypass any form of processing for objects which have their
1916 -- finalization disabled. This applies only to objects at the
1920 and then Finalize_Storage_Only (Obj_Typ)
1924 -- Return object of a build-in-place function. This case is
1925 -- recognized and marked by the expansion of an extended return
1926 -- statement (see Expand_N_Extended_Return_Statement).
1928 elsif Needs_Finalization (Obj_Typ)
1929 and then Is_Return_Object (Obj_Id)
1930 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1932 Processing_Actions (Has_No_Init => True);
1935 -- Inspect the freeze node of an access-to-controlled type and
1936 -- look for a delayed finalization collection. This case arises
1937 -- when the freeze actions are inserted at a later time than the
1938 -- expansion of the context. Since Build_Finalizer is never called
1939 -- on a single construct twice, the collection will be ultimately
1940 -- left out and never finalized. This is also needed for freeze
1941 -- actions of designated types themselves, since in some cases the
1942 -- finalization collection is associated with a designated type's
1943 -- freeze node rather than that of the access type (see handling
1944 -- for freeze actions in Build_Finalization_Collection).
1946 elsif Nkind (Decl) = N_Freeze_Entity
1947 and then Present (Actions (Decl))
1949 Typ := Entity (Decl);
1951 if (Is_Access_Type (Typ)
1952 and then not Is_Access_Subprogram_Type (Typ)
1953 and then Needs_Finalization
1954 (Available_View (Designated_Type (Typ))))
1955 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
1957 Old_Counter_Val := Counter_Val;
1959 -- Freeze nodes are considered to be identical to packages
1960 -- and blocks in terms of nesting. The difference is that
1961 -- a finalization collection created inside the freeze node
1962 -- is at the same nesting level as the node itself.
1964 Process_Declarations (Actions (Decl), Preprocess);
1966 -- The freeze node contains a finalization collection
1970 and then No (Last_Top_Level_Ctrl_Construct)
1971 and then Counter_Val > Old_Counter_Val
1973 Last_Top_Level_Ctrl_Construct := Decl;
1977 -- Nested package declarations, avoid generics
1979 elsif Nkind (Decl) = N_Package_Declaration then
1980 Spec := Specification (Decl);
1981 Pack_Id := Defining_Unit_Name (Spec);
1983 if Nkind (Pack_Id) = N_Defining_Program_Unit_Name then
1984 Pack_Id := Defining_Identifier (Pack_Id);
1987 if Ekind (Pack_Id) /= E_Generic_Package then
1988 Old_Counter_Val := Counter_Val;
1989 Process_Declarations
1990 (Private_Declarations (Spec), Preprocess);
1991 Process_Declarations
1992 (Visible_Declarations (Spec), Preprocess);
1994 -- Either the visible or the private declarations contain a
1995 -- controlled object. The nested package declaration is the
1996 -- last such construct.
2000 and then No (Last_Top_Level_Ctrl_Construct)
2001 and then Counter_Val > Old_Counter_Val
2003 Last_Top_Level_Ctrl_Construct := Decl;
2007 -- Nested package bodies, avoid generics
2009 elsif Nkind (Decl) = N_Package_Body then
2010 Spec := Corresponding_Spec (Decl);
2012 if Ekind (Spec) /= E_Generic_Package then
2013 Old_Counter_Val := Counter_Val;
2014 Process_Declarations (Declarations (Decl), Preprocess);
2016 -- The nested package body is the last construct to contain
2017 -- a controlled object.
2021 and then No (Last_Top_Level_Ctrl_Construct)
2022 and then Counter_Val > Old_Counter_Val
2024 Last_Top_Level_Ctrl_Construct := Decl;
2028 -- Handle a rare case caused by a controlled transient variable
2029 -- created as part of a record init proc. The variable is wrapped
2030 -- in a block, but the block is not associated with a transient
2033 elsif Nkind (Decl) = N_Block_Statement
2034 and then Inside_Init_Proc
2036 Old_Counter_Val := Counter_Val;
2038 if Present (Handled_Statement_Sequence (Decl)) then
2039 Process_Declarations
2040 (Statements (Handled_Statement_Sequence (Decl)),
2044 Process_Declarations (Declarations (Decl), Preprocess);
2046 -- Either the declaration or statement list of the block has a
2047 -- controlled object.
2051 and then No (Last_Top_Level_Ctrl_Construct)
2052 and then Counter_Val > Old_Counter_Val
2054 Last_Top_Level_Ctrl_Construct := Decl;
2058 Prev_Non_Pragma (Decl);
2060 end Process_Declarations;
2062 --------------------------------
2063 -- Process_Object_Declaration --
2064 --------------------------------
2066 procedure Process_Object_Declaration
2068 Has_No_Init : Boolean := False;
2069 Is_Protected : Boolean := False)
2071 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2072 Loc : constant Source_Ptr := Sloc (Decl);
2074 Count_Ins : Node_Id;
2076 Fin_Stmts : List_Id;
2079 Label_Id : Entity_Id;
2081 Obj_Typ : Entity_Id;
2083 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2084 -- Once it has been established that the current object is in fact a
2085 -- return object of build-in-place function Func_Id, generate the
2086 -- following cleanup code:
2088 -- if BIPallocfrom > Secondary_Stack'Pos
2089 -- and then BIPcollection /= null
2092 -- type Ptr_Typ is access Obj_Typ;
2093 -- for Ptr_Typ'Storage_Pool use Base_Pool (BIPcollection);
2096 -- Free (Ptr_Typ (Temp));
2100 -- Obj_Typ is the type of the current object, Temp is the original
2101 -- allocation which Obj_Id renames.
2103 procedure Find_Last_Init
2106 Last_Init : out Node_Id;
2107 Body_Insert : out Node_Id);
2108 -- An object declaration has at least one and at most two init calls:
2109 -- that of the type and the user-defined initialize. Given an object
2110 -- declaration, Last_Init denotes the last initialization call which
2111 -- follows the declaration. Body_Insert denotes the place where the
2112 -- finalizer body could be potentially inserted.
2114 -----------------------------
2115 -- Build_BIP_Cleanup_Stmts --
2116 -----------------------------
2118 function Build_BIP_Cleanup_Stmts
2119 (Func_Id : Entity_Id) return Node_Id
2121 Collect : constant Entity_Id :=
2122 Build_In_Place_Formal (Func_Id, BIP_Collection);
2123 Decls : constant List_Id := New_List;
2124 Obj_Typ : constant Entity_Id := Etype (Func_Id);
2125 Temp_Id : constant Entity_Id :=
2126 Entity (Prefix (Name (Parent (Obj_Id))));
2130 Free_Stmt : Node_Id;
2131 Pool_Id : Entity_Id;
2132 Ptr_Typ : Entity_Id;
2136 -- Pool_Id renames Base_Pool (BIPcollection.all).all;
2138 Pool_Id := Make_Temporary (Loc, 'P');
2141 Make_Object_Renaming_Declaration (Loc,
2142 Defining_Identifier => Pool_Id,
2144 New_Reference_To (RTE (RE_Root_Storage_Pool), Loc),
2146 Make_Explicit_Dereference (Loc,
2148 Make_Function_Call (Loc,
2150 New_Reference_To (RTE (RE_Base_Pool), Loc),
2151 Parameter_Associations => New_List (
2152 Make_Explicit_Dereference (Loc,
2153 Prefix => New_Reference_To (Collect, Loc)))))));
2155 -- Create an access type which uses the storage pool of the
2156 -- caller's collection.
2159 -- type Ptr_Typ is access Obj_Typ;
2161 Ptr_Typ := Make_Temporary (Loc, 'P');
2164 Make_Full_Type_Declaration (Loc,
2165 Defining_Identifier => Ptr_Typ,
2167 Make_Access_To_Object_Definition (Loc,
2168 Subtype_Indication => New_Reference_To (Obj_Typ, Loc))));
2170 -- Perform minor decoration in order to set the collection and the
2171 -- storage pool attributes.
2173 Set_Ekind (Ptr_Typ, E_Access_Type);
2174 Set_Associated_Collection (Ptr_Typ, Collect);
2175 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2177 -- Create an explicit free statement. Note that the free uses the
2178 -- caller's pool expressed as a renaming.
2181 Make_Free_Statement (Loc,
2183 Unchecked_Convert_To (Ptr_Typ,
2184 New_Reference_To (Temp_Id, Loc)));
2186 Set_Storage_Pool (Free_Stmt, Pool_Id);
2188 -- Create a block to house the dummy type and the instantiation as
2189 -- well as to perform the cleanup the temporary.
2195 -- Free (Ptr_Typ (Temp_Id));
2199 Make_Block_Statement (Loc,
2200 Declarations => Decls,
2201 Handled_Statement_Sequence =>
2202 Make_Handled_Sequence_Of_Statements (Loc,
2203 Statements => New_List (Free_Stmt)));
2206 -- if BIPcollection /= null then
2210 Left_Opnd => New_Reference_To (Collect, Loc),
2211 Right_Opnd => Make_Null (Loc));
2213 -- For constrained or tagged results escalate the condition to
2214 -- include the allocation format. Generate:
2216 -- if BIPallocform > Secondary_Stack'Pos
2217 -- and then BIPcollection /= null
2220 if not Is_Constrained (Obj_Typ)
2221 or else Is_Tagged_Type (Obj_Typ)
2224 Alloc : constant Entity_Id :=
2225 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2231 Left_Opnd => New_Reference_To (Alloc, Loc),
2233 Make_Integer_Literal (Loc,
2235 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2237 Right_Opnd => Cond);
2247 Make_If_Statement (Loc,
2249 Then_Statements => New_List (Free_Blk));
2250 end Build_BIP_Cleanup_Stmts;
2252 --------------------
2253 -- Find_Last_Init --
2254 --------------------
2256 procedure Find_Last_Init
2259 Last_Init : out Node_Id;
2260 Body_Insert : out Node_Id)
2262 Nod_1 : Node_Id := Empty;
2263 Nod_2 : Node_Id := Empty;
2266 function Is_Init_Call
2268 Typ : Entity_Id) return Boolean;
2269 -- Given an arbitrary node, determine whether N is a procedure
2270 -- call and if it is, try to match the name of the call with the
2271 -- [Deep_]Initialize proc of Typ.
2277 function Is_Init_Call
2279 Typ : Entity_Id) return Boolean
2282 -- A call to [Deep_]Initialize is always direct
2284 if Nkind (N) = N_Procedure_Call_Statement
2285 and then Nkind (Name (N)) = N_Identifier
2288 Call_Nam : constant Name_Id := Chars (Entity (Name (N)));
2289 Deep_Init : constant Entity_Id :=
2290 TSS (Typ, TSS_Deep_Initialize);
2291 Init : Entity_Id := Empty;
2294 -- A type may have controlled components but not be
2297 if Is_Controlled (Typ) then
2298 Init := Find_Prim_Op (Typ, Name_Initialize);
2302 (Present (Deep_Init)
2303 and then Chars (Deep_Init) = Call_Nam)
2306 and then Chars (Init) = Call_Nam);
2313 -- Start of processing for Find_Last_Init
2317 Body_Insert := Empty;
2319 -- Object renamings and objects associated with controlled
2320 -- function results do not have initialization calls.
2326 if Is_Concurrent_Type (Typ) then
2327 Utyp := Corresponding_Record_Type (Typ);
2332 -- The init procedures are arranged as follows:
2334 -- Object : Controlled_Type;
2335 -- Controlled_TypeIP (Object);
2336 -- [[Deep_]Initialize (Object);]
2338 -- where the user-defined initialize may be optional or may appear
2339 -- inside a block when abort deferral is needed.
2341 Nod_1 := Next (Decl);
2342 if Present (Nod_1) then
2343 Nod_2 := Next (Nod_1);
2345 -- The statement following an object declaration is always a
2346 -- call to the type init proc.
2351 -- Optional user-defined init or deep init processing
2353 if Present (Nod_2) then
2355 -- The statement following the type init proc may be a block
2356 -- statement in cases where abort deferral is required.
2358 if Nkind (Nod_2) = N_Block_Statement then
2360 HSS : constant Node_Id :=
2361 Handled_Statement_Sequence (Nod_2);
2366 and then Present (Statements (HSS))
2368 Stmt := First (Statements (HSS));
2370 -- Examine individual block statements and locate the
2371 -- call to [Deep_]Initialze.
2373 while Present (Stmt) loop
2374 if Is_Init_Call (Stmt, Utyp) then
2376 Body_Insert := Nod_2;
2386 elsif Is_Init_Call (Nod_2, Utyp) then
2392 -- Start of processing for Process_Object_Declaration
2395 Obj_Ref := New_Reference_To (Obj_Id, Loc);
2396 Obj_Typ := Base_Type (Etype (Obj_Id));
2398 -- Handle access types
2400 if Is_Access_Type (Obj_Typ) then
2401 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2402 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2405 Set_Etype (Obj_Ref, Obj_Typ);
2407 -- Set a new value for the state counter and insert the statement
2408 -- after the object declaration. Generate:
2410 -- Counter := <value>;
2413 Make_Assignment_Statement (Loc,
2414 Name => New_Reference_To (Counter_Id, Loc),
2415 Expression => Make_Integer_Literal (Loc, Counter_Val));
2417 -- Insert the counter after all initialization has been done. The
2418 -- place of insertion depends on the context. When dealing with a
2419 -- controlled function, the counter is inserted directly after the
2420 -- declaration because such objects lack init calls.
2422 Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
2424 Insert_After (Count_Ins, Inc_Decl);
2427 -- If the current declaration is the last in the list, the finalizer
2428 -- body needs to be inserted after the set counter statement for the
2429 -- current object declaration. This is complicated by the fact that
2430 -- the set counter statement may appear in abort deferred block. In
2431 -- that case, the proper insertion place is after the block.
2433 if No (Finalizer_Insert_Nod) then
2435 -- Insertion after an abort deffered block
2437 if Present (Body_Ins) then
2438 Finalizer_Insert_Nod := Body_Ins;
2440 Finalizer_Insert_Nod := Inc_Decl;
2444 -- Create the associated label with this object, generate:
2446 -- L<counter> : label;
2449 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2450 Set_Entity (Label_Id,
2451 Make_Defining_Identifier (Loc, Chars (Label_Id)));
2452 Label := Make_Label (Loc, Label_Id);
2454 Prepend_To (Finalizer_Decls,
2455 Make_Implicit_Label_Declaration (Loc,
2456 Defining_Identifier => Entity (Label_Id),
2457 Label_Construct => Label));
2459 -- Create the associated jump with this object, generate:
2461 -- when <counter> =>
2464 Prepend_To (Jump_Alts,
2465 Make_Case_Statement_Alternative (Loc,
2466 Discrete_Choices => New_List (
2467 Make_Integer_Literal (Loc, Counter_Val)),
2468 Statements => New_List (
2469 Make_Goto_Statement (Loc,
2470 Name => New_Reference_To (Entity (Label_Id), Loc)))));
2472 -- Insert the jump destination, generate:
2476 Append_To (Finalizer_Stmts, Label);
2478 -- Processing for simple protected objects. Such objects require
2479 -- manual finalization of their lock managers.
2481 if Is_Protected then
2482 Fin_Stmts := No_List;
2484 if Is_Simple_Protected_Type (Obj_Typ) then
2485 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
2486 if Present (Fin_Call) then
2487 Fin_Stmts := New_List (Fin_Call);
2490 elsif Has_Simple_Protected_Object (Obj_Typ) then
2491 if Is_Record_Type (Obj_Typ) then
2492 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2494 elsif Is_Array_Type (Obj_Typ) then
2495 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2501 -- System.Tasking.Protected_Objects.Finalize_Protection
2509 if Present (Fin_Stmts) then
2510 Append_To (Finalizer_Stmts,
2511 Make_Block_Statement (Loc,
2512 Handled_Statement_Sequence =>
2513 Make_Handled_Sequence_Of_Statements (Loc,
2514 Statements => Fin_Stmts,
2516 Exception_Handlers => New_List (
2517 Make_Exception_Handler (Loc,
2518 Exception_Choices => New_List (
2519 Make_Others_Choice (Loc)),
2521 Statements => New_List (
2522 Make_Null_Statement (Loc)))))));
2525 -- Processing for regular controlled objects
2529 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2531 -- begin -- Exception handlers allowed
2532 -- [Deep_]Finalize (Obj);
2535 -- when Id : others =>
2536 -- if not Raised then
2538 -- Save_Occurrence (E, Id);
2547 if Exceptions_OK then
2548 Fin_Stmts := New_List (
2549 Make_Block_Statement (Loc,
2550 Handled_Statement_Sequence =>
2551 Make_Handled_Sequence_Of_Statements (Loc,
2552 Statements => New_List (Fin_Call),
2554 Exception_Handlers => New_List (
2555 Build_Exception_Handler
2556 (Loc, E_Id, Raised_Id, For_Package)))));
2558 -- When exception handlers are prohibited, the finalization call
2559 -- appears unprotected. Any exception raised during finalization
2560 -- will bypass the circuitry which ensures the cleanup of all
2561 -- remaining objects.
2564 Fin_Stmts := New_List (Fin_Call);
2567 -- If we are dealing with a return object of a build-in-place
2568 -- function, generate the following cleanup statements:
2570 -- if BIPallocfrom > Secondary_Stack'Pos then
2572 -- type Ptr_Typ is access Obj_Typ;
2573 -- for Ptr_Typ'Storage_Pool use
2574 -- Base_Pool (BIPcollection.all).all;
2577 -- Free (Ptr_Typ (Temp));
2581 -- The generated code effectively detaches the temporary from the
2582 -- caller finalization chain and deallocates the object. This is
2583 -- disabled on .NET/JVM because pools are not supported.
2585 -- H505-021 This needs to be revisited on .NET/JVM
2587 if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2589 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2591 if Is_Build_In_Place_Function (Func_Id)
2592 and then Needs_BIP_Collection (Func_Id)
2594 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2599 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2600 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
2602 -- Return objects use a flag to aid their potential
2603 -- finalization when the enclosing function fails to return
2604 -- properly. Generate:
2607 -- <object finalization statements>
2610 if Is_Return_Object (Obj_Id) then
2611 Fin_Stmts := New_List (
2612 Make_If_Statement (Loc,
2617 (Return_Flag_Or_Transient_Decl (Obj_Id), Loc)),
2619 Then_Statements => Fin_Stmts));
2621 -- Temporaries created for the purpose of "exporting" a
2622 -- controlled transient out of an Expression_With_Actions (EWA)
2623 -- need guards. The following illustrates the usage of such
2626 -- Access_Typ : access [all] Obj_Typ;
2627 -- Temp : Access_Typ := null;
2628 -- <Counter> := ...;
2631 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2632 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2634 -- Temp := Ctrl_Trans'Unchecked_Access;
2637 -- The finalization machinery does not process EWA nodes as
2638 -- this may lead to premature finalization of expressions. Note
2639 -- that Temp is marked as being properly initialized regardless
2640 -- of whether the initialization of Ctrl_Trans succeeded. Since
2641 -- a failed initialization may leave Temp with a value of null,
2642 -- add a guard to handle this case:
2644 -- if Obj /= null then
2645 -- <object finalization statements>
2650 (Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
2651 N_Object_Declaration);
2653 Fin_Stmts := New_List (
2654 Make_If_Statement (Loc,
2657 Left_Opnd => New_Reference_To (Obj_Id, Loc),
2658 Right_Opnd => Make_Null (Loc)),
2660 Then_Statements => Fin_Stmts));
2665 Append_List_To (Finalizer_Stmts, Fin_Stmts);
2667 -- Since the declarations are examined in reverse, the state counter
2668 -- must be decremented in order to keep with the true position of
2671 Counter_Val := Counter_Val - 1;
2672 end Process_Object_Declaration;
2674 -------------------------------------
2675 -- Process_Tagged_Type_Declaration --
2676 -------------------------------------
2678 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2679 Typ : constant Entity_Id := Defining_Identifier (Decl);
2680 DT_Ptr : constant Entity_Id :=
2681 Node (First_Elmt (Access_Disp_Table (Typ)));
2684 -- Ada.Tags.Unregister_Tag (<Typ>P);
2686 Append_To (Tagged_Type_Stmts,
2687 Make_Procedure_Call_Statement (Loc,
2689 New_Reference_To (RTE (RE_Unregister_Tag), Loc),
2690 Parameter_Associations => New_List (
2691 New_Reference_To (DT_Ptr, Loc))));
2692 end Process_Tagged_Type_Declaration;
2694 -- Start of processing for Build_Finalizer
2699 -- Step 1: Extract all lists which may contain controlled objects or
2700 -- library-level tagged types.
2702 if For_Package_Spec then
2703 Decls := Visible_Declarations (Specification (N));
2704 Priv_Decls := Private_Declarations (Specification (N));
2706 -- Retrieve the package spec id
2708 Spec_Id := Defining_Unit_Name (Specification (N));
2710 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2711 Spec_Id := Defining_Identifier (Spec_Id);
2714 -- Accept statement, block, entry body, package body, protected body,
2715 -- subprogram body or task body.
2718 Decls := Declarations (N);
2719 HSS := Handled_Statement_Sequence (N);
2721 if Present (HSS) then
2722 if Present (Statements (HSS)) then
2723 Stmts := Statements (HSS);
2726 if Present (At_End_Proc (HSS)) then
2727 Prev_At_End := At_End_Proc (HSS);
2731 -- Retrieve the package spec id for package bodies
2733 if For_Package_Body then
2734 Spec_Id := Corresponding_Spec (N);
2738 -- Do not process nested packages since those are handled by the
2739 -- enclosing scope's finalizer. Do not process non-expanded package
2740 -- instantiations since those will be re-analyzed and re-expanded.
2744 (not Is_Library_Level_Entity (Spec_Id)
2746 -- Nested packages are considered to be library level entities,
2747 -- but do not need to be processed separately. True library level
2748 -- packages have a scope value of 1.
2750 or else Scope_Depth_Value (Spec_Id) /= Uint_1
2751 or else (Is_Generic_Instance (Spec_Id)
2752 and then Package_Instantiation (Spec_Id) /= N))
2757 -- Step 2: Object [pre]processing
2761 -- Preprocess the visible declarations now in order to obtain the
2762 -- correct number of controlled object by the time the private
2763 -- declarations are processed.
2765 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2767 -- From all the possible contexts, only package specifications may
2768 -- have private declarations.
2770 if For_Package_Spec then
2771 Process_Declarations
2772 (Priv_Decls, Preprocess => True, Top_Level => True);
2775 -- The current context may lack controlled objects, but require some
2776 -- other form of completion (task termination for instance). In such
2777 -- cases, the finalizer must be created and carry the additional
2780 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2784 -- The preprocessing has determined that the context has controlled
2785 -- objects or library-level tagged types.
2787 if Has_Ctrl_Objs or Has_Tagged_Types then
2789 -- Private declarations are processed first in order to preserve
2790 -- possible dependencies between public and private objects.
2792 if For_Package_Spec then
2793 Process_Declarations (Priv_Decls);
2796 Process_Declarations (Decls);
2802 -- Preprocess both declarations and statements
2804 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2805 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
2807 -- At this point it is known that N has controlled objects. Ensure
2808 -- that N has a declarative list since the finalizer spec will be
2811 if Has_Ctrl_Objs and then No (Decls) then
2812 Set_Declarations (N, New_List);
2813 Decls := Declarations (N);
2814 Spec_Decls := Decls;
2817 -- The current context may lack controlled objects, but require some
2818 -- other form of completion (task termination for instance). In such
2819 -- cases, the finalizer must be created and carry the additional
2822 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2826 if Has_Ctrl_Objs or Has_Tagged_Types then
2827 Process_Declarations (Stmts);
2828 Process_Declarations (Decls);
2832 -- Step 3: Finalizer creation
2834 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2837 end Build_Finalizer;
2839 --------------------------
2840 -- Build_Finalizer_Call --
2841 --------------------------
2843 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
2844 Loc : constant Source_Ptr := Sloc (N);
2845 HSS : Node_Id := Handled_Statement_Sequence (N);
2847 Is_Prot_Body : constant Boolean :=
2848 Nkind (N) = N_Subprogram_Body
2849 and then Is_Protected_Subprogram_Body (N);
2850 -- Determine whether N denotes the protected version of a subprogram
2851 -- which belongs to a protected type.
2854 -- The At_End handler should have been assimilated by the finalizer
2856 pragma Assert (No (At_End_Proc (HSS)));
2858 -- If the construct to be cleaned up is a protected subprogram body, the
2859 -- finalizer call needs to be associated with the block which wraps the
2860 -- unprotected version of the subprogram. The following illustrates this
2863 -- procedure Prot_SubpP is
2864 -- procedure finalizer is
2866 -- Service_Entries (Prot_Obj);
2873 -- Prot_SubpN (Prot_Obj);
2879 if Is_Prot_Body then
2880 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
2882 -- An At_End handler and regular exception handlers cannot coexist in
2883 -- the same statement sequence. Wrap the original statements in a block.
2885 elsif Present (Exception_Handlers (HSS)) then
2887 End_Lab : constant Node_Id := End_Label (HSS);
2892 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
2894 Set_Handled_Statement_Sequence (N,
2895 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
2897 HSS := Handled_Statement_Sequence (N);
2898 Set_End_Label (HSS, End_Lab);
2902 Set_At_End_Proc (HSS, New_Reference_To (Fin_Id, Loc));
2904 Analyze (At_End_Proc (HSS));
2905 Expand_At_End_Handler (HSS, Empty);
2906 end Build_Finalizer_Call;
2908 ---------------------
2909 -- Build_Late_Proc --
2910 ---------------------
2912 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
2914 for Final_Prim in Name_Of'Range loop
2915 if Name_Of (Final_Prim) = Nam then
2918 (Prim => Final_Prim,
2920 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
2923 end Build_Late_Proc;
2925 -------------------------------
2926 -- Build_Object_Declarations --
2927 -------------------------------
2929 function Build_Object_Declarations
2931 Abort_Id : Entity_Id;
2933 Raised_Id : Entity_Id;
2934 For_Package : Boolean := False) return List_Id
2941 if Restriction_Active (No_Exception_Propagation) then
2945 pragma Assert (Present (Abort_Id));
2946 pragma Assert (Present (E_Id));
2947 pragma Assert (Present (Raised_Id));
2951 -- In certain scenarios, finalization can be triggered by an abort. If
2952 -- the finalization itself fails and raises an exception, the resulting
2953 -- Program_Error must be supressed and replaced by an abort signal. In
2954 -- order to detect this scenario, save the state of entry into the
2955 -- finalization code.
2957 -- No need to do this for VM case, since VM version of Ada.Exceptions
2958 -- does not include routine Raise_From_Controlled_Operation which is the
2959 -- the sole user of flag Abort.
2961 -- This is not needed for library-level finalizers as they are called
2962 -- by the environment task and cannot be aborted.
2965 and then VM_Target = No_VM
2966 and then not For_Package
2969 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'E');
2973 -- Temp : constant Exception_Occurrence_Access :=
2974 -- Get_Current_Excep.all;
2977 Make_Object_Declaration (Loc,
2978 Defining_Identifier => Temp_Id,
2979 Constant_Present => True,
2980 Object_Definition =>
2981 New_Reference_To (RTE (RE_Exception_Occurrence_Access), Loc),
2983 Make_Function_Call (Loc,
2985 Make_Explicit_Dereference (Loc,
2988 (RTE (RE_Get_Current_Excep), Loc)))));
2992 -- and then Exception_Identity (Temp.all) =
2993 -- Standard'Abort_Signal'Identity;
2999 Left_Opnd => New_Reference_To (Temp_Id, Loc),
3000 Right_Opnd => Make_Null (Loc)),
3005 Make_Function_Call (Loc,
3007 New_Reference_To (RTE (RE_Exception_Identity), Loc),
3008 Parameter_Associations => New_List (
3009 Make_Explicit_Dereference (Loc,
3010 Prefix => New_Reference_To (Temp_Id, Loc)))),
3013 Make_Attribute_Reference (Loc,
3015 New_Reference_To (Stand.Abort_Signal, Loc),
3016 Attribute_Name => Name_Identity)));
3019 -- No abort or .NET/JVM
3022 A_Expr := New_Reference_To (Standard_False, Loc);
3026 -- Abort_Id : constant Boolean := <A_Expr>;
3029 Make_Object_Declaration (Loc,
3030 Defining_Identifier => Abort_Id,
3031 Constant_Present => True,
3032 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3033 Expression => A_Expr));
3036 -- E_Id : Exception_Occurrence;
3039 Make_Object_Declaration (Loc,
3040 Defining_Identifier => E_Id,
3041 Object_Definition =>
3042 New_Reference_To (RTE (RE_Exception_Occurrence), Loc));
3043 Set_No_Initialization (E_Decl);
3045 Append_To (Result, E_Decl);
3048 -- Raised_Id : Boolean := False;
3051 Make_Object_Declaration (Loc,
3052 Defining_Identifier => Raised_Id,
3053 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3054 Expression => New_Reference_To (Standard_False, Loc)));
3057 end Build_Object_Declarations;
3059 ---------------------------
3060 -- Build_Raise_Statement --
3061 ---------------------------
3063 function Build_Raise_Statement
3065 Abort_Id : Entity_Id;
3067 Raised_Id : Entity_Id) return Node_Id
3070 Proc_Id : Entity_Id;
3073 -- The default parameter is the local exception occurrence
3075 Params := New_List (New_Reference_To (E_Id, Loc));
3077 -- Standard run-time, .NET/JVM targets, this case handles finalization
3078 -- exceptions raised during an abort.
3080 if RTE_Available (RE_Raise_From_Controlled_Operation) then
3081 Proc_Id := RTE (RE_Raise_From_Controlled_Operation);
3082 Append_To (Params, New_Reference_To (Abort_Id, Loc));
3084 -- Restricted runtime: exception messages are not supported and hence
3085 -- Raise_From_Controlled_Operation is not supported.
3088 Proc_Id := RTE (RE_Reraise_Occurrence);
3092 -- if Raised_Id then
3093 -- <Proc_Id> (<Params>);
3097 Make_If_Statement (Loc,
3098 Condition => New_Reference_To (Raised_Id, Loc),
3099 Then_Statements => New_List (
3100 Make_Procedure_Call_Statement (Loc,
3101 Name => New_Reference_To (Proc_Id, Loc),
3102 Parameter_Associations => Params)));
3103 end Build_Raise_Statement;
3105 -----------------------------
3106 -- Build_Record_Deep_Procs --
3107 -----------------------------
3109 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3113 (Prim => Initialize_Case,
3115 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3117 if not Is_Immutably_Limited_Type (Typ) then
3120 (Prim => Adjust_Case,
3122 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3127 (Prim => Finalize_Case,
3129 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3131 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3132 -- .NET do not support address arithmetic and unchecked conversions.
3134 if VM_Target = No_VM then
3137 (Prim => Address_Case,
3139 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3141 end Build_Record_Deep_Procs;
3147 function Cleanup_Array
3150 Typ : Entity_Id) return List_Id
3152 Loc : constant Source_Ptr := Sloc (N);
3153 Index_List : constant List_Id := New_List;
3155 function Free_Component return List_Id;
3156 -- Generate the code to finalize the task or protected subcomponents
3157 -- of a single component of the array.
3159 function Free_One_Dimension (Dim : Int) return List_Id;
3160 -- Generate a loop over one dimension of the array
3162 --------------------
3163 -- Free_Component --
3164 --------------------
3166 function Free_Component return List_Id is
3167 Stmts : List_Id := New_List;
3169 C_Typ : constant Entity_Id := Component_Type (Typ);
3172 -- Component type is known to contain tasks or protected objects
3175 Make_Indexed_Component (Loc,
3176 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3177 Expressions => Index_List);
3179 Set_Etype (Tsk, C_Typ);
3181 if Is_Task_Type (C_Typ) then
3182 Append_To (Stmts, Cleanup_Task (N, Tsk));
3184 elsif Is_Simple_Protected_Type (C_Typ) then
3185 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3187 elsif Is_Record_Type (C_Typ) then
3188 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3190 elsif Is_Array_Type (C_Typ) then
3191 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3197 ------------------------
3198 -- Free_One_Dimension --
3199 ------------------------
3201 function Free_One_Dimension (Dim : Int) return List_Id is
3205 if Dim > Number_Dimensions (Typ) then
3206 return Free_Component;
3208 -- Here we generate the required loop
3211 Index := Make_Temporary (Loc, 'J');
3212 Append (New_Reference_To (Index, Loc), Index_List);
3215 Make_Implicit_Loop_Statement (N,
3216 Identifier => Empty,
3218 Make_Iteration_Scheme (Loc,
3219 Loop_Parameter_Specification =>
3220 Make_Loop_Parameter_Specification (Loc,
3221 Defining_Identifier => Index,
3222 Discrete_Subtype_Definition =>
3223 Make_Attribute_Reference (Loc,
3224 Prefix => Duplicate_Subexpr (Obj),
3225 Attribute_Name => Name_Range,
3226 Expressions => New_List (
3227 Make_Integer_Literal (Loc, Dim))))),
3228 Statements => Free_One_Dimension (Dim + 1)));
3230 end Free_One_Dimension;
3232 -- Start of processing for Cleanup_Array
3235 return Free_One_Dimension (1);
3238 --------------------
3239 -- Cleanup_Record --
3240 --------------------
3242 function Cleanup_Record
3245 Typ : Entity_Id) return List_Id
3247 Loc : constant Source_Ptr := Sloc (N);
3250 Stmts : constant List_Id := New_List;
3251 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3254 if Has_Discriminants (U_Typ)
3255 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3257 Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3260 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3262 -- For now, do not attempt to free a component that may appear in a
3263 -- variant, and instead issue a warning. Doing this "properly" would
3264 -- require building a case statement and would be quite a mess. Note
3265 -- that the RM only requires that free "work" for the case of a task
3266 -- access value, so already we go way beyond this in that we deal
3267 -- with the array case and non-discriminated record cases.
3270 ("task/protected object in variant record will not be freed?", N);
3271 return New_List (Make_Null_Statement (Loc));
3274 Comp := First_Component (Typ);
3275 while Present (Comp) loop
3276 if Has_Task (Etype (Comp))
3277 or else Has_Simple_Protected_Object (Etype (Comp))
3280 Make_Selected_Component (Loc,
3281 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3282 Selector_Name => New_Occurrence_Of (Comp, Loc));
3283 Set_Etype (Tsk, Etype (Comp));
3285 if Is_Task_Type (Etype (Comp)) then
3286 Append_To (Stmts, Cleanup_Task (N, Tsk));
3288 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3289 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3291 elsif Is_Record_Type (Etype (Comp)) then
3293 -- Recurse, by generating the prefix of the argument to
3294 -- the eventual cleanup call.
3296 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3298 elsif Is_Array_Type (Etype (Comp)) then
3299 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3303 Next_Component (Comp);
3309 ------------------------------
3310 -- Cleanup_Protected_Object --
3311 ------------------------------
3313 function Cleanup_Protected_Object
3315 Ref : Node_Id) return Node_Id
3317 Loc : constant Source_Ptr := Sloc (N);
3320 -- For restricted run-time libraries (Ravenscar), tasks are
3321 -- non-terminating, and protected objects can only appear at library
3322 -- level, so we do not want finalization of protected objects.
3324 if Restricted_Profile then
3329 Make_Procedure_Call_Statement (Loc,
3331 New_Reference_To (RTE (RE_Finalize_Protection), Loc),
3332 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3334 end Cleanup_Protected_Object;
3340 function Cleanup_Task
3342 Ref : Node_Id) return Node_Id
3344 Loc : constant Source_Ptr := Sloc (N);
3347 -- For restricted run-time libraries (Ravenscar), tasks are
3348 -- non-terminating and they can only appear at library level, so we do
3349 -- not want finalization of task objects.
3351 if Restricted_Profile then
3356 Make_Procedure_Call_Statement (Loc,
3358 New_Reference_To (RTE (RE_Free_Task), Loc),
3359 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3363 ------------------------------
3364 -- Check_Visibly_Controlled --
3365 ------------------------------
3367 procedure Check_Visibly_Controlled
3368 (Prim : Final_Primitives;
3370 E : in out Entity_Id;
3371 Cref : in out Node_Id)
3373 Parent_Type : Entity_Id;
3377 if Is_Derived_Type (Typ)
3378 and then Comes_From_Source (E)
3379 and then not Present (Overridden_Operation (E))
3381 -- We know that the explicit operation on the type does not override
3382 -- the inherited operation of the parent, and that the derivation
3383 -- is from a private type that is not visibly controlled.
3385 Parent_Type := Etype (Typ);
3386 Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3388 if Present (Op) then
3391 -- Wrap the object to be initialized into the proper
3392 -- unchecked conversion, to be compatible with the operation
3395 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3396 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3398 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3402 end Check_Visibly_Controlled;
3404 -------------------------------
3405 -- CW_Or_Has_Controlled_Part --
3406 -------------------------------
3408 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3410 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3411 end CW_Or_Has_Controlled_Part;
3417 function Convert_View
3420 Ind : Pos := 1) return Node_Id
3422 Fent : Entity_Id := First_Entity (Proc);
3427 for J in 2 .. Ind loop
3431 Ftyp := Etype (Fent);
3433 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3434 Atyp := Entity (Subtype_Mark (Arg));
3436 Atyp := Etype (Arg);
3439 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3440 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3443 and then Present (Atyp)
3444 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3445 and then Base_Type (Underlying_Type (Atyp)) =
3446 Base_Type (Underlying_Type (Ftyp))
3448 return Unchecked_Convert_To (Ftyp, Arg);
3450 -- If the argument is already a conversion, as generated by
3451 -- Make_Init_Call, set the target type to the type of the formal
3452 -- directly, to avoid spurious typing problems.
3454 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3455 and then not Is_Class_Wide_Type (Atyp)
3457 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3458 Set_Etype (Arg, Ftyp);
3466 ------------------------
3467 -- Enclosing_Function --
3468 ------------------------
3470 function Enclosing_Function (E : Entity_Id) return Entity_Id is
3471 Func_Id : Entity_Id;
3475 while Present (Func_Id)
3476 and then Func_Id /= Standard_Standard
3478 if Ekind (Func_Id) = E_Function then
3482 Func_Id := Scope (Func_Id);
3486 end Enclosing_Function;
3488 -------------------------------
3489 -- Establish_Transient_Scope --
3490 -------------------------------
3492 -- This procedure is called each time a transient block has to be inserted
3493 -- that is to say for each call to a function with unconstrained or tagged
3494 -- result. It creates a new scope on the stack scope in order to enclose
3495 -- all transient variables generated
3497 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3498 Loc : constant Source_Ptr := Sloc (N);
3499 Wrap_Node : Node_Id;
3502 -- Do not create a transient scope if we are already inside one
3504 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3505 if Scope_Stack.Table (S).Is_Transient then
3507 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3512 -- If we have encountered Standard there are no enclosing
3513 -- transient scopes.
3515 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3520 Wrap_Node := Find_Node_To_Be_Wrapped (N);
3522 -- Case of no wrap node, false alert, no transient scope needed
3524 if No (Wrap_Node) then
3527 -- If the node to wrap is an iteration_scheme, the expression is
3528 -- one of the bounds, and the expansion will make an explicit
3529 -- declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3530 -- so do not apply any transformations here.
3532 elsif Nkind (Wrap_Node) = N_Iteration_Scheme then
3535 -- In formal verification mode, if the node to wrap is a pragma check,
3536 -- this node and enclosed expression are not expanded, so do not apply
3537 -- any transformations here.
3540 and then Nkind (Wrap_Node) = N_Pragma
3541 and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
3546 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3547 Set_Scope_Is_Transient;
3550 Set_Uses_Sec_Stack (Current_Scope);
3551 Check_Restriction (No_Secondary_Stack, N);
3554 Set_Etype (Current_Scope, Standard_Void_Type);
3555 Set_Node_To_Be_Wrapped (Wrap_Node);
3557 if Debug_Flag_W then
3558 Write_Str (" <Transient>");
3562 end Establish_Transient_Scope;
3564 ----------------------------
3565 -- Expand_Cleanup_Actions --
3566 ----------------------------
3568 procedure Expand_Cleanup_Actions (N : Node_Id) is
3569 Scop : constant Entity_Id := Current_Scope;
3571 Is_Asynchronous_Call : constant Boolean :=
3572 Nkind (N) = N_Block_Statement
3573 and then Is_Asynchronous_Call_Block (N);
3574 Is_Master : constant Boolean :=
3575 Nkind (N) /= N_Entry_Body
3576 and then Is_Task_Master (N);
3577 Is_Protected_Body : constant Boolean :=
3578 Nkind (N) = N_Subprogram_Body
3579 and then Is_Protected_Subprogram_Body (N);
3580 Is_Task_Allocation : constant Boolean :=
3581 Nkind (N) = N_Block_Statement
3582 and then Is_Task_Allocation_Block (N);
3583 Is_Task_Body : constant Boolean :=
3584 Nkind (Original_Node (N)) = N_Task_Body;
3585 Needs_Sec_Stack_Mark : constant Boolean :=
3586 Uses_Sec_Stack (Scop)
3588 not Sec_Stack_Needed_For_Return (Scop)
3589 and then VM_Target = No_VM;
3591 Actions_Required : constant Boolean :=
3592 Requires_Cleanup_Actions (N)
3593 or else Is_Asynchronous_Call
3595 or else Is_Protected_Body
3596 or else Is_Task_Allocation
3597 or else Is_Task_Body
3598 or else Needs_Sec_Stack_Mark;
3600 HSS : Node_Id := Handled_Statement_Sequence (N);
3603 procedure Wrap_HSS_In_Block;
3604 -- Move HSS inside a new block along with the original exception
3605 -- handlers. Make the newly generated block the sole statement of HSS.
3607 -----------------------
3608 -- Wrap_HSS_In_Block --
3609 -----------------------
3611 procedure Wrap_HSS_In_Block is
3616 -- Preserve end label to provide proper cross-reference information
3618 End_Lab := End_Label (HSS);
3620 Make_Block_Statement (Loc,
3621 Handled_Statement_Sequence => HSS);
3623 Set_Handled_Statement_Sequence (N,
3624 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3625 HSS := Handled_Statement_Sequence (N);
3627 Set_First_Real_Statement (HSS, Block);
3628 Set_End_Label (HSS, End_Lab);
3630 -- Comment needed here, see RH for 1.306 ???
3632 if Nkind (N) = N_Subprogram_Body then
3633 Set_Has_Nested_Block_With_Handler (Scop);
3635 end Wrap_HSS_In_Block;
3637 -- Start of processing for Expand_Cleanup_Actions
3640 -- The current construct does not need any form of servicing
3642 if not Actions_Required then
3645 -- If the current node is a rewritten task body and the descriptors have
3646 -- not been delayed (due to some nested instantiations), do not generate
3647 -- redundant cleanup actions.
3650 and then Nkind (N) = N_Subprogram_Body
3651 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3657 Decls : List_Id := Declarations (N);
3659 Mark : Entity_Id := Empty;
3660 New_Decls : List_Id;
3664 -- If we are generating expanded code for debugging purposes, use the
3665 -- Sloc of the point of insertion for the cleanup code. The Sloc will
3666 -- be updated subsequently to reference the proper line in .dg files.
3667 -- If we are not debugging generated code, use No_Location instead,
3668 -- so that no debug information is generated for the cleanup code.
3669 -- This makes the behavior of the NEXT command in GDB monotonic, and
3670 -- makes the placement of breakpoints more accurate.
3672 if Debug_Generated_Code then
3678 -- Set polling off. The finalization and cleanup code is executed
3679 -- with aborts deferred.
3681 Old_Poll := Polling_Required;
3682 Polling_Required := False;
3684 -- A task activation call has already been built for a task
3685 -- allocation block.
3687 if not Is_Task_Allocation then
3688 Build_Task_Activation_Call (N);
3692 Establish_Task_Master (N);
3695 New_Decls := New_List;
3697 -- If secondary stack is in use, generate:
3699 -- Mnn : constant Mark_Id := SS_Mark;
3701 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3702 -- secondary stack is never used on a VM.
3704 if Needs_Sec_Stack_Mark then
3705 Mark := Make_Temporary (Loc, 'M');
3707 Append_To (New_Decls,
3708 Make_Object_Declaration (Loc,
3709 Defining_Identifier => Mark,
3710 Object_Definition =>
3711 New_Reference_To (RTE (RE_Mark_Id), Loc),
3713 Make_Function_Call (Loc,
3714 Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
3716 Set_Uses_Sec_Stack (Scop, False);
3719 -- If exception handlers are present, wrap the sequence of statements
3720 -- in a block since it is not possible to have exception handlers and
3721 -- an At_End handler in the same construct.
3723 if Present (Exception_Handlers (HSS)) then
3726 -- Ensure that the First_Real_Statement field is set
3728 elsif No (First_Real_Statement (HSS)) then
3729 Set_First_Real_Statement (HSS, First (Statements (HSS)));
3732 -- Do not move the Activation_Chain declaration in the context of
3733 -- task allocation blocks. Task allocation blocks use _chain in their
3734 -- cleanup handlers and gigi complains if it is declared in the
3735 -- sequence of statements of the scope that declares the handler.
3737 if Is_Task_Allocation then
3739 Chain : constant Entity_Id := Activation_Chain_Entity (N);
3743 Decl := First (Decls);
3744 while Nkind (Decl) /= N_Object_Declaration
3745 or else Defining_Identifier (Decl) /= Chain
3749 -- A task allocation block should always include a _chain
3752 pragma Assert (Present (Decl));
3756 Prepend_To (New_Decls, Decl);
3760 -- Ensure the presence of a declaration list in order to successfully
3761 -- append all original statements to it.
3764 Set_Declarations (N, New_List);
3765 Decls := Declarations (N);
3768 -- Move the declarations into the sequence of statements in order to
3769 -- have them protected by the At_End handler. It may seem weird to
3770 -- put declarations in the sequence of statement but in fact nothing
3771 -- forbids that at the tree level.
3773 Append_List_To (Decls, Statements (HSS));
3774 Set_Statements (HSS, Decls);
3776 -- Reset the Sloc of the handled statement sequence to properly
3777 -- reflect the new initial "statement" in the sequence.
3779 Set_Sloc (HSS, Sloc (First (Decls)));
3781 -- The declarations of finalizer spec and auxiliary variables replace
3782 -- the old declarations that have been moved inward.
3784 Set_Declarations (N, New_Decls);
3785 Analyze_Declarations (New_Decls);
3787 -- Generate finalization calls for all controlled objects appearing
3788 -- in the statements of N. Add context specific cleanup for various
3793 Clean_Stmts => Build_Cleanup_Statements (N),
3795 Top_Decls => New_Decls,
3796 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
3800 if Present (Fin_Id) then
3801 Build_Finalizer_Call (N, Fin_Id);
3804 -- Restore saved polling mode
3806 Polling_Required := Old_Poll;
3808 end Expand_Cleanup_Actions;
3810 ---------------------------
3811 -- Expand_N_Package_Body --
3812 ---------------------------
3814 -- Add call to Activate_Tasks if body is an activator (actual processing
3815 -- is in chapter 9).
3817 -- Generate subprogram descriptor for elaboration routine
3819 -- Encode entity names in package body
3821 procedure Expand_N_Package_Body (N : Node_Id) is
3822 Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
3826 -- This is done only for non-generic packages
3828 if Ekind (Spec_Ent) = E_Package then
3829 Push_Scope (Corresponding_Spec (N));
3831 -- Build dispatch tables of library level tagged types
3833 if Tagged_Type_Expansion
3834 and then Is_Library_Level_Entity (Spec_Ent)
3836 Build_Static_Dispatch_Tables (N);
3839 Build_Task_Activation_Call (N);
3843 Set_Elaboration_Flag (N, Corresponding_Spec (N));
3844 Set_In_Package_Body (Spec_Ent, False);
3846 -- Set to encode entity names in package body before gigi is called
3848 Qualify_Entity_Names (N);
3850 if Ekind (Spec_Ent) /= E_Generic_Package then
3853 Clean_Stmts => No_List,
3855 Top_Decls => No_List,
3856 Defer_Abort => False,
3859 if Present (Fin_Id) then
3861 Body_Ent : Node_Id := Defining_Unit_Name (N);
3864 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
3865 Body_Ent := Defining_Identifier (Body_Ent);
3868 Set_Finalizer (Body_Ent, Fin_Id);
3872 end Expand_N_Package_Body;
3874 ----------------------------------
3875 -- Expand_N_Package_Declaration --
3876 ----------------------------------
3878 -- Add call to Activate_Tasks if there are tasks declared and the package
3879 -- has no body. Note that in Ada83, this may result in premature activation
3880 -- of some tasks, given that we cannot tell whether a body will eventually
3883 procedure Expand_N_Package_Declaration (N : Node_Id) is
3884 Id : constant Entity_Id := Defining_Entity (N);
3885 Spec : constant Node_Id := Specification (N);
3889 No_Body : Boolean := False;
3890 -- True in the case of a package declaration that is a compilation
3891 -- unit and for which no associated body will be compiled in this
3895 -- Case of a package declaration other than a compilation unit
3897 if Nkind (Parent (N)) /= N_Compilation_Unit then
3900 -- Case of a compilation unit that does not require a body
3902 elsif not Body_Required (Parent (N))
3903 and then not Unit_Requires_Body (Id)
3907 -- Special case of generating calling stubs for a remote call interface
3908 -- package: even though the package declaration requires one, the body
3909 -- won't be processed in this compilation (so any stubs for RACWs
3910 -- declared in the package must be generated here, along with the spec).
3912 elsif Parent (N) = Cunit (Main_Unit)
3913 and then Is_Remote_Call_Interface (Id)
3914 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
3919 -- For a package declaration that implies no associated body, generate
3920 -- task activation call and RACW supporting bodies now (since we won't
3921 -- have a specific separate compilation unit for that).
3926 if Has_RACW (Id) then
3928 -- Generate RACW subprogram bodies
3930 Decls := Private_Declarations (Spec);
3933 Decls := Visible_Declarations (Spec);
3938 Set_Visible_Declarations (Spec, Decls);
3941 Append_RACW_Bodies (Decls, Id);
3942 Analyze_List (Decls);
3945 if Present (Activation_Chain_Entity (N)) then
3947 -- Generate task activation call as last step of elaboration
3949 Build_Task_Activation_Call (N);
3955 -- Build dispatch tables of library level tagged types
3957 if Tagged_Type_Expansion
3958 and then (Is_Compilation_Unit (Id)
3959 or else (Is_Generic_Instance (Id)
3960 and then Is_Library_Level_Entity (Id)))
3962 Build_Static_Dispatch_Tables (N);
3965 -- Note: it is not necessary to worry about generating a subprogram
3966 -- descriptor, since the only way to get exception handlers into a
3967 -- package spec is to include instantiations, and that would cause
3968 -- generation of subprogram descriptors to be delayed in any case.
3970 -- Set to encode entity names in package spec before gigi is called
3972 Qualify_Entity_Names (N);
3974 if Ekind (Id) /= E_Generic_Package then
3977 Clean_Stmts => No_List,
3979 Top_Decls => No_List,
3980 Defer_Abort => False,
3983 Set_Finalizer (Id, Fin_Id);
3985 end Expand_N_Package_Declaration;
3987 -----------------------------
3988 -- Find_Node_To_Be_Wrapped --
3989 -----------------------------
3991 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
3993 The_Parent : Node_Id;
3999 pragma Assert (P /= Empty);
4000 The_Parent := Parent (P);
4002 case Nkind (The_Parent) is
4004 -- Simple statement can be wrapped
4009 -- Usually assignments are good candidate for wrapping
4010 -- except when they have been generated as part of a
4011 -- controlled aggregate where the wrapping should take
4012 -- place more globally.
4014 when N_Assignment_Statement =>
4015 if No_Ctrl_Actions (The_Parent) then
4021 -- An entry call statement is a special case if it occurs in
4022 -- the context of a Timed_Entry_Call. In this case we wrap
4023 -- the entire timed entry call.
4025 when N_Entry_Call_Statement |
4026 N_Procedure_Call_Statement =>
4027 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
4028 and then Nkind_In (Parent (Parent (The_Parent)),
4030 N_Conditional_Entry_Call)
4032 return Parent (Parent (The_Parent));
4037 -- Object declarations are also a boundary for the transient scope
4038 -- even if they are not really wrapped
4039 -- (see Wrap_Transient_Declaration)
4041 when N_Object_Declaration |
4042 N_Object_Renaming_Declaration |
4043 N_Subtype_Declaration =>
4046 -- The expression itself is to be wrapped if its parent is a
4047 -- compound statement or any other statement where the expression
4048 -- is known to be scalar
4050 when N_Accept_Alternative |
4051 N_Attribute_Definition_Clause |
4054 N_Delay_Alternative |
4055 N_Delay_Until_Statement |
4056 N_Delay_Relative_Statement |
4057 N_Discriminant_Association |
4059 N_Entry_Body_Formal_Part |
4062 N_Iteration_Scheme |
4063 N_Terminate_Alternative =>
4066 when N_Attribute_Reference =>
4068 if Is_Procedure_Attribute_Name
4069 (Attribute_Name (The_Parent))
4074 -- A raise statement can be wrapped. This will arise when the
4075 -- expression in a raise_with_expression uses the secondary
4076 -- stack, for example.
4078 when N_Raise_Statement =>
4081 -- If the expression is within the iteration scheme of a loop,
4082 -- we must create a declaration for it, followed by an assignment
4083 -- in order to have a usable statement to wrap.
4085 when N_Loop_Parameter_Specification =>
4086 return Parent (The_Parent);
4088 -- The following nodes contains "dummy calls" which don't
4089 -- need to be wrapped.
4091 when N_Parameter_Specification |
4092 N_Discriminant_Specification |
4093 N_Component_Declaration =>
4096 -- The return statement is not to be wrapped when the function
4097 -- itself needs wrapping at the outer-level
4099 when N_Simple_Return_Statement =>
4101 Applies_To : constant Entity_Id :=
4103 (Return_Statement_Entity (The_Parent));
4104 Return_Type : constant Entity_Id := Etype (Applies_To);
4106 if Requires_Transient_Scope (Return_Type) then
4113 -- If we leave a scope without having been able to find a node to
4114 -- wrap, something is going wrong but this can happen in error
4115 -- situation that are not detected yet (such as a dynamic string
4116 -- in a pragma export)
4118 when N_Subprogram_Body |
4119 N_Package_Declaration |
4121 N_Block_Statement =>
4124 -- otherwise continue the search
4130 end Find_Node_To_Be_Wrapped;
4132 -------------------------------------
4133 -- Get_Global_Pool_For_Access_Type --
4134 -------------------------------------
4136 function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id is
4138 -- Access types whose size is smaller than System.Address size can
4139 -- exist only on VMS. We can't use the usual global pool which returns
4140 -- an object of type Address as truncation will make it invalid.
4141 -- To handle this case, VMS has a dedicated global pool that returns
4142 -- addresses that fit into 32 bit accesses.
4144 if Opt.True_VMS_Target and then Esize (T) = 32 then
4145 return RTE (RE_Global_Pool_32_Object);
4147 return RTE (RE_Global_Pool_Object);
4149 end Get_Global_Pool_For_Access_Type;
4151 ----------------------------------
4152 -- Has_New_Controlled_Component --
4153 ----------------------------------
4155 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4159 if not Is_Tagged_Type (E) then
4160 return Has_Controlled_Component (E);
4161 elsif not Is_Derived_Type (E) then
4162 return Has_Controlled_Component (E);
4165 Comp := First_Component (E);
4166 while Present (Comp) loop
4167 if Chars (Comp) = Name_uParent then
4170 elsif Scope (Original_Record_Component (Comp)) = E
4171 and then Needs_Finalization (Etype (Comp))
4176 Next_Component (Comp);
4180 end Has_New_Controlled_Component;
4182 ---------------------------------
4183 -- Has_Simple_Protected_Object --
4184 ---------------------------------
4186 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4188 if Has_Task (T) then
4191 elsif Is_Simple_Protected_Type (T) then
4194 elsif Is_Array_Type (T) then
4195 return Has_Simple_Protected_Object (Component_Type (T));
4197 elsif Is_Record_Type (T) then
4202 Comp := First_Component (T);
4203 while Present (Comp) loop
4204 if Has_Simple_Protected_Object (Etype (Comp)) then
4208 Next_Component (Comp);
4217 end Has_Simple_Protected_Object;
4219 ------------------------------------
4220 -- Insert_Actions_In_Scope_Around --
4221 ------------------------------------
4223 procedure Insert_Actions_In_Scope_Around (N : Node_Id) is
4224 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
4225 After : List_Id renames SE.Actions_To_Be_Wrapped_After;
4226 Before : List_Id renames SE.Actions_To_Be_Wrapped_Before;
4228 procedure Process_Transient_Objects
4229 (First_Object : Node_Id;
4230 Last_Object : Node_Id;
4231 Related_Node : Node_Id);
4232 -- First_Object and Last_Object define a list which contains potential
4233 -- controlled transient objects. Finalization flags are inserted before
4234 -- First_Object and finalization calls are inserted after Last_Object.
4235 -- Related_Node is the node for which transient objects have been
4238 -------------------------------
4239 -- Process_Transient_Objects --
4240 -------------------------------
4242 procedure Process_Transient_Objects
4243 (First_Object : Node_Id;
4244 Last_Object : Node_Id;
4245 Related_Node : Node_Id)
4247 Abort_Id : Entity_Id;
4248 Built : Boolean := False;
4251 Fin_Block : Node_Id;
4252 Last_Fin : Node_Id := Empty;
4256 Obj_Typ : Entity_Id;
4257 Raised_Id : Entity_Id;
4261 -- Examine all objects in the list First_Object .. Last_Object
4263 Stmt := First_Object;
4264 while Present (Stmt) loop
4265 if Nkind (Stmt) = N_Object_Declaration
4266 and then Analyzed (Stmt)
4267 and then Is_Finalizable_Transient (Stmt, N)
4269 -- Do not process the node to be wrapped since it will be
4270 -- handled by the enclosing finalizer.
4272 and then Stmt /= Related_Node
4275 Obj_Id := Defining_Identifier (Stmt);
4276 Obj_Typ := Base_Type (Etype (Obj_Id));
4279 Set_Is_Processed_Transient (Obj_Id);
4281 -- Handle access types
4283 if Is_Access_Type (Desig) then
4284 Desig := Available_View (Designated_Type (Desig));
4287 -- Create the necessary entities and declarations the first
4291 Abort_Id := Make_Temporary (Loc, 'A');
4292 E_Id := Make_Temporary (Loc, 'E');
4293 Raised_Id := Make_Temporary (Loc, 'R');
4295 Insert_List_Before_And_Analyze (First_Object,
4296 Build_Object_Declarations
4297 (Loc, Abort_Id, E_Id, Raised_Id));
4304 -- [Deep_]Finalize (Obj_Ref);
4311 -- (Enn, Get_Current_Excep.all.all);
4315 Obj_Ref := New_Reference_To (Obj_Id, Loc);
4317 if Is_Access_Type (Obj_Typ) then
4318 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4322 Make_Block_Statement (Loc,
4323 Handled_Statement_Sequence =>
4324 Make_Handled_Sequence_Of_Statements (Loc,
4325 Statements => New_List (
4327 (Obj_Ref => Obj_Ref,
4330 Exception_Handlers => New_List (
4331 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4332 Insert_After_And_Analyze (Last_Object, Fin_Block);
4334 -- The raise statement must be inserted after all the
4335 -- finalization blocks.
4337 if No (Last_Fin) then
4338 Last_Fin := Fin_Block;
4341 -- When the associated node is an array object, the expander may
4342 -- sometimes generate a loop and create transient objects inside
4345 elsif Nkind (Related_Node) = N_Object_Declaration
4346 and then Is_Array_Type (Base_Type
4347 (Etype (Defining_Identifier (Related_Node))))
4348 and then Nkind (Stmt) = N_Loop_Statement
4351 Block_HSS : Node_Id := First (Statements (Stmt));
4354 -- The loop statements may have been wrapped in a block by
4355 -- Process_Statements_For_Controlled_Objects, inspect the
4356 -- handled sequence of statements.
4358 if Nkind (Block_HSS) = N_Block_Statement
4359 and then No (Next (Block_HSS))
4361 Block_HSS := Handled_Statement_Sequence (Block_HSS);
4363 Process_Transient_Objects
4364 (First_Object => First (Statements (Block_HSS)),
4365 Last_Object => Last (Statements (Block_HSS)),
4366 Related_Node => Related_Node);
4368 -- Inspect the statements of the loop
4371 Process_Transient_Objects
4372 (First_Object => First (Statements (Stmt)),
4373 Last_Object => Last (Statements (Stmt)),
4374 Related_Node => Related_Node);
4378 -- Terminate the scan after the last object has been processed
4380 elsif Stmt = Last_Object then
4389 -- Raise_From_Controlled_Operation (E, Abort);
4393 and then Present (Last_Fin)
4395 Insert_After_And_Analyze (Last_Fin,
4396 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4398 end Process_Transient_Objects;
4400 -- Start of processing for Insert_Actions_In_Scope_Around
4403 if No (Before) and then No (After) then
4408 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
4409 First_Obj : Node_Id;
4414 -- If the node to be wrapped is the trigger of an asynchronous
4415 -- select, it is not part of a statement list. The actions must be
4416 -- inserted before the select itself, which is part of some list of
4417 -- statements. Note that the triggering alternative includes the
4418 -- triggering statement and an optional statement list. If the node
4419 -- to be wrapped is part of that list, the normal insertion applies.
4421 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4422 and then not Is_List_Member (Node_To_Wrap)
4424 Target := Parent (Parent (Node_To_Wrap));
4429 First_Obj := Target;
4432 -- Add all actions associated with a transient scope into the main
4433 -- tree. There are several scenarios here:
4435 -- +--- Before ----+ +----- After ---+
4436 -- 1) First_Obj ....... Target ........ Last_Obj
4438 -- 2) First_Obj ....... Target
4440 -- 3) Target ........ Last_Obj
4442 if Present (Before) then
4444 -- Flag declarations are inserted before the first object
4446 First_Obj := First (Before);
4448 Insert_List_Before (Target, Before);
4451 if Present (After) then
4453 -- Finalization calls are inserted after the last object
4455 Last_Obj := Last (After);
4457 Insert_List_After (Target, After);
4460 -- Check for transient controlled objects associated with Target and
4461 -- generate the appropriate finalization actions for them.
4463 Process_Transient_Objects
4464 (First_Object => First_Obj,
4465 Last_Object => Last_Obj,
4466 Related_Node => Target);
4468 -- Reset the action lists
4470 if Present (Before) then
4474 if Present (After) then
4478 end Insert_Actions_In_Scope_Around;
4480 ------------------------------
4481 -- Is_Simple_Protected_Type --
4482 ------------------------------
4484 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
4487 Is_Protected_Type (T)
4488 and then not Has_Entries (T)
4489 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
4490 end Is_Simple_Protected_Type;
4492 -----------------------
4493 -- Make_Adjust_Call --
4494 -----------------------
4496 function Make_Adjust_Call
4499 For_Parent : Boolean := False) return Node_Id
4501 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4502 Adj_Id : Entity_Id := Empty;
4503 Ref : Node_Id := Obj_Ref;
4507 -- Recover the proper type which contains Deep_Adjust
4509 if Is_Class_Wide_Type (Typ) then
4510 Utyp := Root_Type (Typ);
4515 Utyp := Underlying_Type (Base_Type (Utyp));
4516 Set_Assignment_OK (Ref);
4518 -- Deal with non-tagged derivation of private views
4520 if Is_Untagged_Derivation (Typ) then
4521 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
4522 Ref := Unchecked_Convert_To (Utyp, Ref);
4523 Set_Assignment_OK (Ref);
4526 -- When dealing with the completion of a private type, use the base
4529 if Utyp /= Base_Type (Utyp) then
4530 pragma Assert (Is_Private_Type (Typ));
4532 Utyp := Base_Type (Utyp);
4533 Ref := Unchecked_Convert_To (Utyp, Ref);
4536 -- Select the appropriate version of adjust
4539 if Has_Controlled_Component (Utyp) then
4540 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4543 -- For types that are both controlled and have controlled components,
4544 -- generate a call to Deep_Adjust.
4546 elsif Is_Controlled (Utyp)
4547 and then Has_Controlled_Component (Utyp)
4549 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4551 -- For types that are not controlled themselves, but contain controlled
4552 -- components or can be extended by types with controlled components,
4553 -- create a call to Deep_Adjust.
4555 elsif Is_Class_Wide_Type (Typ)
4556 or else Has_Controlled_Component (Utyp)
4558 if Is_Tagged_Type (Utyp) then
4559 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4561 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
4564 -- For types that are derived from Controlled and do not have controlled
4565 -- components, build a call to Adjust.
4568 Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
4571 if Present (Adj_Id) then
4573 -- If the object is unanalyzed, set its expected type for use in
4574 -- Convert_View in case an additional conversion is needed.
4577 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
4579 Set_Etype (Ref, Typ);
4582 -- The object reference may need another conversion depending on the
4583 -- type of the formal and that of the actual.
4585 if not Is_Class_Wide_Type (Typ) then
4586 Ref := Convert_View (Adj_Id, Ref);
4589 return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent);
4593 end Make_Adjust_Call;
4595 ----------------------
4596 -- Make_Attach_Call --
4597 ----------------------
4599 function Make_Attach_Call
4601 Ptr_Typ : Entity_Id) return Node_Id
4603 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4606 Make_Procedure_Call_Statement (Loc,
4608 New_Reference_To (RTE (RE_Attach), Loc),
4609 Parameter_Associations => New_List (
4610 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
4611 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4612 end Make_Attach_Call;
4614 ----------------------
4615 -- Make_Detach_Call --
4616 ----------------------
4618 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
4619 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4623 Make_Procedure_Call_Statement (Loc,
4625 New_Reference_To (RTE (RE_Detach), Loc),
4626 Parameter_Associations => New_List (
4627 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4628 end Make_Detach_Call;
4636 Proc_Id : Entity_Id;
4638 For_Parent : Boolean := False) return Node_Id
4640 Params : constant List_Id := New_List (Param);
4643 -- When creating a call to Deep_Finalize for a _parent field of a
4644 -- derived type, disable the invocation of the nested Finalize by giving
4645 -- the corresponding flag a False value.
4648 Append_To (Params, New_Reference_To (Standard_False, Loc));
4652 Make_Procedure_Call_Statement (Loc,
4653 Name => New_Reference_To (Proc_Id, Loc),
4654 Parameter_Associations => Params);
4657 --------------------------
4658 -- Make_Deep_Array_Body --
4659 --------------------------
4661 function Make_Deep_Array_Body
4662 (Prim : Final_Primitives;
4663 Typ : Entity_Id) return List_Id
4665 function Build_Adjust_Or_Finalize_Statements
4666 (Typ : Entity_Id) return List_Id;
4667 -- Create the statements necessary to adjust or finalize an array of
4668 -- controlled elements. Generate:
4671 -- Temp : constant Exception_Occurrence_Access :=
4672 -- Get_Current_Excep.all;
4673 -- Abort : constant Boolean :=
4675 -- and then Exception_Identity (Temp_Id.all) =
4676 -- Standard'Abort_Signal'Identity;
4678 -- Abort : constant Boolean := False; -- no abort
4680 -- E : Exception_Occurrence;
4681 -- Raised : Boolean := False;
4684 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
4685 -- ^-- in the finalization case
4687 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
4689 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
4693 -- if not Raised then
4695 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4703 -- Raise_From_Controlled_Operation (E, Abort);
4707 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
4708 -- Create the statements necessary to initialize an array of controlled
4709 -- elements. Include a mechanism to carry out partial finalization if an
4710 -- exception occurs. Generate:
4713 -- Counter : Integer := 0;
4716 -- for J1 in V'Range (1) loop
4718 -- for JN in V'Range (N) loop
4720 -- [Deep_]Initialize (V (J1, ..., JN));
4722 -- Counter := Counter + 1;
4727 -- Temp : constant Exception_Occurrence_Access :=
4728 -- Get_Current_Excep.all;
4729 -- Abort : constant Boolean :=
4731 -- and then Exception_Identity (Temp_Id.all) =
4732 -- Standard'Abort_Signal'Identity;
4734 -- Abort : constant Boolean := False; -- no abort
4735 -- E : Exception_Occurence;
4736 -- Raised : Boolean := False;
4743 -- V'Length (N) - Counter;
4745 -- for F1 in reverse V'Range (1) loop
4747 -- for FN in reverse V'Range (N) loop
4748 -- if Counter > 0 then
4749 -- Counter := Counter - 1;
4752 -- [Deep_]Finalize (V (F1, ..., FN));
4756 -- if not Raised then
4758 -- Save_Occurrence (E,
4759 -- Get_Current_Excep.all.all);
4769 -- Raise_From_Controlled_Operation (E, Abort);
4778 function New_References_To
4780 Loc : Source_Ptr) return List_Id;
4781 -- Given a list of defining identifiers, return a list of references to
4782 -- the original identifiers, in the same order as they appear.
4784 -----------------------------------------
4785 -- Build_Adjust_Or_Finalize_Statements --
4786 -----------------------------------------
4788 function Build_Adjust_Or_Finalize_Statements
4789 (Typ : Entity_Id) return List_Id
4791 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4792 Index_List : constant List_Id := New_List;
4793 Loc : constant Source_Ptr := Sloc (Typ);
4794 Num_Dims : constant Int := Number_Dimensions (Typ);
4795 Abort_Id : Entity_Id := Empty;
4798 Core_Loop : Node_Id;
4800 E_Id : Entity_Id := Empty;
4802 Loop_Id : Entity_Id;
4803 Raised_Id : Entity_Id := Empty;
4806 Exceptions_OK : constant Boolean :=
4807 not Restriction_Active (No_Exception_Propagation);
4809 procedure Build_Indices;
4810 -- Generate the indices used in the dimension loops
4816 procedure Build_Indices is
4818 -- Generate the following identifiers:
4819 -- Jnn - for initialization
4821 for Dim in 1 .. Num_Dims loop
4822 Append_To (Index_List,
4823 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4827 -- Start of processing for Build_Adjust_Or_Finalize_Statements
4832 if Exceptions_OK then
4833 Abort_Id := Make_Temporary (Loc, 'A');
4834 E_Id := Make_Temporary (Loc, 'E');
4835 Raised_Id := Make_Temporary (Loc, 'R');
4839 Make_Indexed_Component (Loc,
4840 Prefix => Make_Identifier (Loc, Name_V),
4841 Expressions => New_References_To (Index_List, Loc));
4842 Set_Etype (Comp_Ref, Comp_Typ);
4845 -- [Deep_]Adjust (V (J1, ..., JN))
4847 if Prim = Adjust_Case then
4848 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4851 -- [Deep_]Finalize (V (J1, ..., JN))
4853 else pragma Assert (Prim = Finalize_Case);
4854 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4857 -- Generate the block which houses the adjust or finalize call:
4859 -- <adjust or finalize call>; -- No_Exception_Propagation
4861 -- begin -- Exception handlers allowed
4862 -- <adjust or finalize call>
4866 -- if not Raised then
4868 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4872 if Exceptions_OK then
4874 Make_Block_Statement (Loc,
4875 Handled_Statement_Sequence =>
4876 Make_Handled_Sequence_Of_Statements (Loc,
4877 Statements => New_List (Call),
4878 Exception_Handlers => New_List (
4879 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4884 -- Generate the dimension loops starting from the innermost one
4886 -- for Jnn in [reverse] V'Range (Dim) loop
4890 J := Last (Index_List);
4892 while Present (J) and then Dim > 0 loop
4898 Make_Loop_Statement (Loc,
4900 Make_Iteration_Scheme (Loc,
4901 Loop_Parameter_Specification =>
4902 Make_Loop_Parameter_Specification (Loc,
4903 Defining_Identifier => Loop_Id,
4904 Discrete_Subtype_Definition =>
4905 Make_Attribute_Reference (Loc,
4906 Prefix => Make_Identifier (Loc, Name_V),
4907 Attribute_Name => Name_Range,
4908 Expressions => New_List (
4909 Make_Integer_Literal (Loc, Dim))),
4911 Reverse_Present => Prim = Finalize_Case)),
4913 Statements => New_List (Core_Loop),
4914 End_Label => Empty);
4919 -- Generate the block which contains the core loop, the declarations
4920 -- of the abort flag, the exception occurrence, the raised flag and
4921 -- the conditional raise:
4924 -- Abort : constant Boolean :=
4925 -- Exception_Occurrence (Get_Current_Excep.all.all) =
4926 -- Standard'Abort_Signal'Identity;
4928 -- Abort : constant Boolean := False; -- no abort
4930 -- E : Exception_Occurrence;
4931 -- Raised : Boolean := False;
4936 -- if Raised then -- Expection handlers allowed
4937 -- Raise_From_Controlled_Operation (E, Abort);
4941 Stmts := New_List (Core_Loop);
4943 if Exceptions_OK then
4945 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4950 Make_Block_Statement (Loc,
4952 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
4953 Handled_Statement_Sequence =>
4954 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4955 end Build_Adjust_Or_Finalize_Statements;
4957 ---------------------------------
4958 -- Build_Initialize_Statements --
4959 ---------------------------------
4961 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
4962 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4963 Final_List : constant List_Id := New_List;
4964 Index_List : constant List_Id := New_List;
4965 Loc : constant Source_Ptr := Sloc (Typ);
4966 Num_Dims : constant Int := Number_Dimensions (Typ);
4967 Abort_Id : Entity_Id;
4968 Counter_Id : Entity_Id;
4970 E_Id : Entity_Id := Empty;
4973 Final_Block : Node_Id;
4974 Final_Loop : Node_Id;
4975 Init_Loop : Node_Id;
4978 Raised_Id : Entity_Id := Empty;
4981 Exceptions_OK : constant Boolean :=
4982 not Restriction_Active (No_Exception_Propagation);
4984 function Build_Counter_Assignment return Node_Id;
4985 -- Generate the following assignment:
4986 -- Counter := V'Length (1) *
4988 -- V'Length (N) - Counter;
4990 function Build_Finalization_Call return Node_Id;
4991 -- Generate a deep finalization call for an array element
4993 procedure Build_Indices;
4994 -- Generate the initialization and finalization indices used in the
4997 function Build_Initialization_Call return Node_Id;
4998 -- Generate a deep initialization call for an array element
5000 ------------------------------
5001 -- Build_Counter_Assignment --
5002 ------------------------------
5004 function Build_Counter_Assignment return Node_Id is
5009 -- Start from the first dimension and generate:
5014 Make_Attribute_Reference (Loc,
5015 Prefix => Make_Identifier (Loc, Name_V),
5016 Attribute_Name => Name_Length,
5017 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
5019 -- Process the rest of the dimensions, generate:
5020 -- Expr * V'Length (N)
5023 while Dim <= Num_Dims loop
5025 Make_Op_Multiply (Loc,
5028 Make_Attribute_Reference (Loc,
5029 Prefix => Make_Identifier (Loc, Name_V),
5030 Attribute_Name => Name_Length,
5031 Expressions => New_List (
5032 Make_Integer_Literal (Loc, Dim))));
5038 -- Counter := Expr - Counter;
5041 Make_Assignment_Statement (Loc,
5042 Name => New_Reference_To (Counter_Id, Loc),
5044 Make_Op_Subtract (Loc,
5046 Right_Opnd => New_Reference_To (Counter_Id, Loc)));
5047 end Build_Counter_Assignment;
5049 -----------------------------
5050 -- Build_Finalization_Call --
5051 -----------------------------
5053 function Build_Finalization_Call return Node_Id is
5054 Comp_Ref : constant Node_Id :=
5055 Make_Indexed_Component (Loc,
5056 Prefix => Make_Identifier (Loc, Name_V),
5057 Expressions => New_References_To (Final_List, Loc));
5060 Set_Etype (Comp_Ref, Comp_Typ);
5063 -- [Deep_]Finalize (V);
5065 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5066 end Build_Finalization_Call;
5072 procedure Build_Indices is
5074 -- Generate the following identifiers:
5075 -- Jnn - for initialization
5076 -- Fnn - for finalization
5078 for Dim in 1 .. Num_Dims loop
5079 Append_To (Index_List,
5080 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5082 Append_To (Final_List,
5083 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5087 -------------------------------
5088 -- Build_Initialization_Call --
5089 -------------------------------
5091 function Build_Initialization_Call return Node_Id is
5092 Comp_Ref : constant Node_Id :=
5093 Make_Indexed_Component (Loc,
5094 Prefix => Make_Identifier (Loc, Name_V),
5095 Expressions => New_References_To (Index_List, Loc));
5098 Set_Etype (Comp_Ref, Comp_Typ);
5101 -- [Deep_]Initialize (V (J1, ..., JN));
5103 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5104 end Build_Initialization_Call;
5106 -- Start of processing for Build_Initialize_Statements
5111 Counter_Id := Make_Temporary (Loc, 'C');
5113 if Exceptions_OK then
5114 Abort_Id := Make_Temporary (Loc, 'A');
5115 E_Id := Make_Temporary (Loc, 'E');
5116 Raised_Id := Make_Temporary (Loc, 'R');
5119 -- Generate the block which houses the finalization call, the index
5120 -- guard and the handler which triggers Program_Error later on.
5122 -- if Counter > 0 then
5123 -- Counter := Counter - 1;
5125 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5127 -- begin -- Exceptions allowed
5128 -- [Deep_]Finalize (V (F1, ..., FN));
5131 -- if not Raised then
5133 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5138 if Exceptions_OK then
5140 Make_Block_Statement (Loc,
5141 Handled_Statement_Sequence =>
5142 Make_Handled_Sequence_Of_Statements (Loc,
5143 Statements => New_List (Build_Finalization_Call),
5144 Exception_Handlers => New_List (
5145 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5147 Fin_Stmt := Build_Finalization_Call;
5150 -- This is the core of the loop, the dimension iterators are added
5151 -- one by one in reverse.
5154 Make_If_Statement (Loc,
5157 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5158 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5160 Then_Statements => New_List (
5161 Make_Assignment_Statement (Loc,
5162 Name => New_Reference_To (Counter_Id, Loc),
5164 Make_Op_Subtract (Loc,
5165 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5166 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5168 Else_Statements => New_List (Fin_Stmt));
5170 -- Generate all finalization loops starting from the innermost
5173 -- for Fnn in reverse V'Range (Dim) loop
5177 F := Last (Final_List);
5179 while Present (F) and then Dim > 0 loop
5185 Make_Loop_Statement (Loc,
5187 Make_Iteration_Scheme (Loc,
5188 Loop_Parameter_Specification =>
5189 Make_Loop_Parameter_Specification (Loc,
5190 Defining_Identifier => Loop_Id,
5191 Discrete_Subtype_Definition =>
5192 Make_Attribute_Reference (Loc,
5193 Prefix => Make_Identifier (Loc, Name_V),
5194 Attribute_Name => Name_Range,
5195 Expressions => New_List (
5196 Make_Integer_Literal (Loc, Dim))),
5198 Reverse_Present => True)),
5200 Statements => New_List (Final_Loop),
5201 End_Label => Empty);
5206 -- Generate the block which contains the finalization loops, the
5207 -- declarations of the abort flag, the exception occurrence, the
5208 -- raised flag and the conditional raise.
5211 -- Abort : constant Boolean :=
5212 -- Exception_Occurrence (Get_Current_Excep.all.all) =
5213 -- Standard'Abort_Signal'Identity;
5215 -- Abort : constant Boolean := False; -- no abort
5217 -- E : Exception_Occurrence;
5218 -- Raised : Boolean := False;
5224 -- V'Length (N) - Counter;
5228 -- if Raised then -- Exception handlers allowed
5229 -- Raise_From_Controlled_Operation (E, Abort);
5232 -- raise; -- Exception handlers allowed
5235 Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5237 if Exceptions_OK then
5239 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
5240 Append_To (Stmts, Make_Raise_Statement (Loc));
5244 Make_Block_Statement (Loc,
5246 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
5247 Handled_Statement_Sequence =>
5248 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5250 -- Generate the block which contains the initialization call and
5251 -- the partial finalization code.
5254 -- [Deep_]Initialize (V (J1, ..., JN));
5256 -- Counter := Counter + 1;
5260 -- <finalization code>
5264 Make_Block_Statement (Loc,
5265 Handled_Statement_Sequence =>
5266 Make_Handled_Sequence_Of_Statements (Loc,
5267 Statements => New_List (Build_Initialization_Call),
5268 Exception_Handlers => New_List (
5269 Make_Exception_Handler (Loc,
5270 Exception_Choices => New_List (Make_Others_Choice (Loc)),
5271 Statements => New_List (Final_Block)))));
5273 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5274 Make_Assignment_Statement (Loc,
5275 Name => New_Reference_To (Counter_Id, Loc),
5278 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5279 Right_Opnd => Make_Integer_Literal (Loc, 1))));
5281 -- Generate all initialization loops starting from the innermost
5284 -- for Jnn in V'Range (Dim) loop
5288 J := Last (Index_List);
5290 while Present (J) and then Dim > 0 loop
5296 Make_Loop_Statement (Loc,
5298 Make_Iteration_Scheme (Loc,
5299 Loop_Parameter_Specification =>
5300 Make_Loop_Parameter_Specification (Loc,
5301 Defining_Identifier => Loop_Id,
5302 Discrete_Subtype_Definition =>
5303 Make_Attribute_Reference (Loc,
5304 Prefix => Make_Identifier (Loc, Name_V),
5305 Attribute_Name => Name_Range,
5306 Expressions => New_List (
5307 Make_Integer_Literal (Loc, Dim))))),
5309 Statements => New_List (Init_Loop),
5310 End_Label => Empty);
5315 -- Generate the block which contains the counter variable and the
5316 -- initialization loops.
5319 -- Counter : Integer := 0;
5326 Make_Block_Statement (Loc,
5327 Declarations => New_List (
5328 Make_Object_Declaration (Loc,
5329 Defining_Identifier => Counter_Id,
5330 Object_Definition =>
5331 New_Reference_To (Standard_Integer, Loc),
5332 Expression => Make_Integer_Literal (Loc, 0))),
5334 Handled_Statement_Sequence =>
5335 Make_Handled_Sequence_Of_Statements (Loc,
5336 Statements => New_List (Init_Loop))));
5337 end Build_Initialize_Statements;
5339 -----------------------
5340 -- New_References_To --
5341 -----------------------
5343 function New_References_To
5345 Loc : Source_Ptr) return List_Id
5347 Refs : constant List_Id := New_List;
5352 while Present (Id) loop
5353 Append_To (Refs, New_Reference_To (Id, Loc));
5358 end New_References_To;
5360 -- Start of processing for Make_Deep_Array_Body
5364 when Address_Case =>
5365 return Make_Finalize_Address_Stmts (Typ);
5369 return Build_Adjust_Or_Finalize_Statements (Typ);
5371 when Initialize_Case =>
5372 return Build_Initialize_Statements (Typ);
5374 end Make_Deep_Array_Body;
5376 --------------------
5377 -- Make_Deep_Proc --
5378 --------------------
5380 function Make_Deep_Proc
5381 (Prim : Final_Primitives;
5383 Stmts : List_Id) return Entity_Id
5385 Loc : constant Source_Ptr := Sloc (Typ);
5387 Proc_Id : Entity_Id;
5390 -- Create the object formal, generate:
5391 -- V : System.Address
5393 if Prim = Address_Case then
5394 Formals := New_List (
5395 Make_Parameter_Specification (Loc,
5396 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5397 Parameter_Type => New_Reference_To (RTE (RE_Address), Loc)));
5404 Formals := New_List (
5405 Make_Parameter_Specification (Loc,
5406 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5408 Out_Present => True,
5409 Parameter_Type => New_Reference_To (Typ, Loc)));
5411 -- F : Boolean := True
5413 if Prim = Adjust_Case
5414 or else Prim = Finalize_Case
5417 Make_Parameter_Specification (Loc,
5418 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5420 New_Reference_To (Standard_Boolean, Loc),
5422 New_Reference_To (Standard_True, Loc)));
5427 Make_Defining_Identifier (Loc,
5428 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5431 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5434 -- exception -- Finalize and Adjust cases only
5435 -- raise Program_Error;
5436 -- end Deep_Initialize / Adjust / Finalize;
5440 -- procedure Finalize_Address (V : System.Address) is
5443 -- end Finalize_Address;
5446 Make_Subprogram_Body (Loc,
5448 Make_Procedure_Specification (Loc,
5449 Defining_Unit_Name => Proc_Id,
5450 Parameter_Specifications => Formals),
5452 Declarations => Empty_List,
5454 Handled_Statement_Sequence =>
5455 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
5460 ---------------------------
5461 -- Make_Deep_Record_Body --
5462 ---------------------------
5464 function Make_Deep_Record_Body
5465 (Prim : Final_Primitives;
5467 Is_Local : Boolean := False) return List_Id
5469 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
5470 -- Build the statements necessary to adjust a record type. The type may
5471 -- have discriminants and contain variant parts. Generate:
5474 -- Root_Controlled (V).Finalized := False;
5477 -- [Deep_]Adjust (V.Comp_1);
5479 -- when Id : others =>
5480 -- if not Raised then
5482 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5487 -- [Deep_]Adjust (V.Comp_N);
5489 -- when Id : others =>
5490 -- if not Raised then
5492 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5497 -- Deep_Adjust (V._parent, False); -- If applicable
5499 -- when Id : others =>
5500 -- if not Raised then
5502 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5508 -- Adjust (V); -- If applicable
5511 -- if not Raised then
5513 -- Save_Occurence (E, Get_Current_Excep.all.all);
5519 -- Raise_From_Controlled_Object (E, Abort);
5523 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
5524 -- Build the statements necessary to finalize a record type. The type
5525 -- may have discriminants and contain variant parts. Generate:
5528 -- Temp : constant Exception_Occurrence_Access :=
5529 -- Get_Current_Excep.all;
5530 -- Abort : constant Boolean :=
5532 -- and then Exception_Identity (Temp_Id.all) =
5533 -- Standard'Abort_Signal'Identity;
5535 -- Abort : constant Boolean := False; -- no abort
5536 -- E : Exception_Occurence;
5537 -- Raised : Boolean := False;
5540 -- if Root_Controlled (V).Finalized then
5546 -- Finalize (V); -- If applicable
5549 -- if not Raised then
5551 -- Save_Occurence (E, Get_Current_Excep.all.all);
5556 -- case Variant_1 is
5558 -- case State_Counter_N => -- If Is_Local is enabled
5568 -- <<LN>> -- If Is_Local is enabled
5570 -- [Deep_]Finalize (V.Comp_N);
5573 -- if not Raised then
5575 -- Save_Occurence (E, Get_Current_Excep.all.all);
5581 -- [Deep_]Finalize (V.Comp_1);
5584 -- if not Raised then
5586 -- Save_Occurence (E, Get_Current_Excep.all.all);
5592 -- case State_Counter_1 => -- If Is_Local is enabled
5598 -- Deep_Finalize (V._parent, False); -- If applicable
5600 -- when Id : others =>
5601 -- if not Raised then
5603 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5607 -- Root_Controlled (V).Finalized := True;
5610 -- Raise_From_Controlled_Object (E, Abort);
5614 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
5615 -- Given a derived tagged type Typ, traverse all components, find field
5616 -- _parent and return its type.
5618 procedure Preprocess_Components
5620 Num_Comps : out Int;
5621 Has_POC : out Boolean);
5622 -- Examine all components in component list Comps, count all controlled
5623 -- components and determine whether at least one of them is per-object
5624 -- constrained. Component _parent is always skipped.
5626 -----------------------------
5627 -- Build_Adjust_Statements --
5628 -----------------------------
5630 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
5631 Loc : constant Source_Ptr := Sloc (Typ);
5632 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
5633 Abort_Id : Entity_Id := Empty;
5634 Bod_Stmts : List_Id;
5635 E_Id : Entity_Id := Empty;
5636 Raised_Id : Entity_Id := Empty;
5640 Exceptions_OK : constant Boolean :=
5641 not Restriction_Active (No_Exception_Propagation);
5643 function Process_Component_List_For_Adjust
5644 (Comps : Node_Id) return List_Id;
5645 -- Build all necessary adjust statements for a single component list
5647 ---------------------------------------
5648 -- Process_Component_List_For_Adjust --
5649 ---------------------------------------
5651 function Process_Component_List_For_Adjust
5652 (Comps : Node_Id) return List_Id
5654 Stmts : constant List_Id := New_List;
5656 Decl_Id : Entity_Id;
5657 Decl_Typ : Entity_Id;
5661 procedure Process_Component_For_Adjust (Decl : Node_Id);
5662 -- Process the declaration of a single controlled component
5664 ----------------------------------
5665 -- Process_Component_For_Adjust --
5666 ----------------------------------
5668 procedure Process_Component_For_Adjust (Decl : Node_Id) is
5669 Id : constant Entity_Id := Defining_Identifier (Decl);
5670 Typ : constant Entity_Id := Etype (Id);
5675 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
5677 -- begin -- Exception handlers allowed
5678 -- [Deep_]Adjust (V.Id);
5681 -- if not Raised then
5683 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5690 Make_Selected_Component (Loc,
5691 Prefix => Make_Identifier (Loc, Name_V),
5692 Selector_Name => Make_Identifier (Loc, Chars (Id))),
5695 if Exceptions_OK then
5697 Make_Block_Statement (Loc,
5698 Handled_Statement_Sequence =>
5699 Make_Handled_Sequence_Of_Statements (Loc,
5700 Statements => New_List (Adj_Stmt),
5701 Exception_Handlers => New_List (
5702 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5705 Append_To (Stmts, Adj_Stmt);
5706 end Process_Component_For_Adjust;
5708 -- Start of processing for Process_Component_List_For_Adjust
5711 -- Perform an initial check, determine the number of controlled
5712 -- components in the current list and whether at least one of them
5713 -- is per-object constrained.
5715 Preprocess_Components (Comps, Num_Comps, Has_POC);
5717 -- The processing in this routine is done in the following order:
5718 -- 1) Regular components
5719 -- 2) Per-object constrained components
5722 if Num_Comps > 0 then
5724 -- Process all regular components in order of declarations
5726 Decl := First_Non_Pragma (Component_Items (Comps));
5727 while Present (Decl) loop
5728 Decl_Id := Defining_Identifier (Decl);
5729 Decl_Typ := Etype (Decl_Id);
5731 -- Skip _parent as well as per-object constrained components
5733 if Chars (Decl_Id) /= Name_uParent
5734 and then Needs_Finalization (Decl_Typ)
5736 if Has_Access_Constraint (Decl_Id)
5737 and then No (Expression (Decl))
5741 Process_Component_For_Adjust (Decl);
5745 Next_Non_Pragma (Decl);
5748 -- Process all per-object constrained components in order of
5752 Decl := First_Non_Pragma (Component_Items (Comps));
5753 while Present (Decl) loop
5754 Decl_Id := Defining_Identifier (Decl);
5755 Decl_Typ := Etype (Decl_Id);
5759 if Chars (Decl_Id) /= Name_uParent
5760 and then Needs_Finalization (Decl_Typ)
5761 and then Has_Access_Constraint (Decl_Id)
5762 and then No (Expression (Decl))
5764 Process_Component_For_Adjust (Decl);
5767 Next_Non_Pragma (Decl);
5772 -- Process all variants, if any
5775 if Present (Variant_Part (Comps)) then
5777 Var_Alts : constant List_Id := New_List;
5781 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
5782 while Present (Var) loop
5785 -- when <discrete choices> =>
5786 -- <adjust statements>
5788 Append_To (Var_Alts,
5789 Make_Case_Statement_Alternative (Loc,
5791 New_Copy_List (Discrete_Choices (Var)),
5793 Process_Component_List_For_Adjust (
5794 Component_List (Var))));
5796 Next_Non_Pragma (Var);
5800 -- case V.<discriminant> is
5801 -- when <discrete choices 1> =>
5802 -- <adjust statements 1>
5804 -- when <discrete choices N> =>
5805 -- <adjust statements N>
5809 Make_Case_Statement (Loc,
5811 Make_Selected_Component (Loc,
5812 Prefix => Make_Identifier (Loc, Name_V),
5814 Make_Identifier (Loc,
5815 Chars => Chars (Name (Variant_Part (Comps))))),
5816 Alternatives => Var_Alts);
5820 -- Add the variant case statement to the list of statements
5822 if Present (Var_Case) then
5823 Append_To (Stmts, Var_Case);
5826 -- If the component list did not have any controlled components
5827 -- nor variants, return null.
5829 if Is_Empty_List (Stmts) then
5830 Append_To (Stmts, Make_Null_Statement (Loc));
5834 end Process_Component_List_For_Adjust;
5836 -- Start of processing for Build_Adjust_Statements
5839 if Exceptions_OK then
5840 Abort_Id := Make_Temporary (Loc, 'A');
5841 E_Id := Make_Temporary (Loc, 'E');
5842 Raised_Id := Make_Temporary (Loc, 'R');
5845 if Nkind (Typ_Def) = N_Derived_Type_Definition then
5846 Rec_Def := Record_Extension_Part (Typ_Def);
5851 -- Create an adjust sequence for all record components
5853 if Present (Component_List (Rec_Def)) then
5855 Process_Component_List_For_Adjust (Component_List (Rec_Def));
5858 -- A derived record type must adjust all inherited components. This
5859 -- action poses the following problem:
5861 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
5866 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
5868 -- Deep_Adjust (Obj._parent);
5873 -- Adjusting the derived type will invoke Adjust of the parent and
5874 -- then that of the derived type. This is undesirable because both
5875 -- routines may modify shared components. Only the Adjust of the
5876 -- derived type should be invoked.
5878 -- To prevent this double adjustment of shared components,
5879 -- Deep_Adjust uses a flag to control the invocation of Adjust:
5881 -- procedure Deep_Adjust
5882 -- (Obj : in out Some_Type;
5883 -- Flag : Boolean := True)
5891 -- When Deep_Adjust is invokes for field _parent, a value of False is
5892 -- provided for the flag:
5894 -- Deep_Adjust (Obj._parent, False);
5896 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
5898 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
5903 if Needs_Finalization (Par_Typ) then
5907 Make_Selected_Component (Loc,
5908 Prefix => Make_Identifier (Loc, Name_V),
5910 Make_Identifier (Loc, Name_uParent)),
5912 For_Parent => True);
5915 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
5917 -- begin -- Exceptions OK
5918 -- Deep_Adjust (V._parent, False);
5920 -- when Id : others =>
5921 -- if not Raised then
5923 -- Save_Occurrence (E,
5924 -- Get_Current_Excep.all.all);
5928 if Present (Call) then
5931 if Exceptions_OK then
5933 Make_Block_Statement (Loc,
5934 Handled_Statement_Sequence =>
5935 Make_Handled_Sequence_Of_Statements (Loc,
5936 Statements => New_List (Adj_Stmt),
5937 Exception_Handlers => New_List (
5938 Build_Exception_Handler
5939 (Loc, E_Id, Raised_Id))));
5942 Prepend_To (Bod_Stmts, Adj_Stmt);
5948 -- Adjust the object. This action must be performed last after all
5949 -- components have been adjusted.
5951 if Is_Controlled (Typ) then
5957 Proc := Find_Prim_Op (Typ, Name_Adjust);
5961 -- Adjust (V); -- No_Exception_Propagation
5963 -- begin -- Exception handlers allowed
5967 -- if not Raised then
5969 -- Save_Occurrence (E,
5970 -- Get_Current_Excep.all.all);
5975 if Present (Proc) then
5977 Make_Procedure_Call_Statement (Loc,
5978 Name => New_Reference_To (Proc, Loc),
5979 Parameter_Associations => New_List (
5980 Make_Identifier (Loc, Name_V)));
5982 if Exceptions_OK then
5984 Make_Block_Statement (Loc,
5985 Handled_Statement_Sequence =>
5986 Make_Handled_Sequence_Of_Statements (Loc,
5987 Statements => New_List (Adj_Stmt),
5988 Exception_Handlers => New_List (
5989 Build_Exception_Handler
5990 (Loc, E_Id, Raised_Id))));
5993 Append_To (Bod_Stmts,
5994 Make_If_Statement (Loc,
5995 Condition => Make_Identifier (Loc, Name_F),
5996 Then_Statements => New_List (Adj_Stmt)));
6001 -- At this point either all adjustment statements have been generated
6002 -- or the type is not controlled.
6004 if Is_Empty_List (Bod_Stmts) then
6005 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6011 -- Abort : constant Boolean :=
6012 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6013 -- Standard'Abort_Signal'Identity;
6015 -- Abort : constant Boolean := False; -- no abort
6017 -- E : Exception_Occurence;
6018 -- Raised : Boolean := False;
6021 -- Root_Controlled (V).Finalized := False;
6023 -- <adjust statements>
6026 -- Raise_From_Controlled_Operation (E, Abort);
6031 if Exceptions_OK then
6032 Append_To (Bod_Stmts,
6033 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6038 Make_Block_Statement (Loc,
6040 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6041 Handled_Statement_Sequence =>
6042 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6044 end Build_Adjust_Statements;
6046 -------------------------------
6047 -- Build_Finalize_Statements --
6048 -------------------------------
6050 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6051 Loc : constant Source_Ptr := Sloc (Typ);
6052 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6053 Abort_Id : Entity_Id := Empty;
6054 Bod_Stmts : List_Id;
6056 E_Id : Entity_Id := Empty;
6057 Raised_Id : Entity_Id := Empty;
6061 Exceptions_OK : constant Boolean :=
6062 not Restriction_Active (No_Exception_Propagation);
6064 function Process_Component_List_For_Finalize
6065 (Comps : Node_Id) return List_Id;
6066 -- Build all necessary finalization statements for a single component
6067 -- list. The statements may include a jump circuitry if flag Is_Local
6070 -----------------------------------------
6071 -- Process_Component_List_For_Finalize --
6072 -----------------------------------------
6074 function Process_Component_List_For_Finalize
6075 (Comps : Node_Id) return List_Id
6078 Counter_Id : Entity_Id;
6080 Decl_Id : Entity_Id;
6081 Decl_Typ : Entity_Id;
6084 Jump_Block : Node_Id;
6086 Label_Id : Entity_Id;
6090 procedure Process_Component_For_Finalize
6095 -- Process the declaration of a single controlled component. If
6096 -- flag Is_Local is enabled, create the corresponding label and
6097 -- jump circuitry. Alts is the list of case alternatives, Decls
6098 -- is the top level declaration list where labels are declared
6099 -- and Stmts is the list of finalization actions.
6101 ------------------------------------
6102 -- Process_Component_For_Finalize --
6103 ------------------------------------
6105 procedure Process_Component_For_Finalize
6111 Id : constant Entity_Id := Defining_Identifier (Decl);
6112 Typ : constant Entity_Id := Etype (Id);
6119 Label_Id : Entity_Id;
6126 Make_Identifier (Loc,
6127 Chars => New_External_Name ('L', Num_Comps));
6128 Set_Entity (Label_Id,
6129 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6130 Label := Make_Label (Loc, Label_Id);
6133 Make_Implicit_Label_Declaration (Loc,
6134 Defining_Identifier => Entity (Label_Id),
6135 Label_Construct => Label));
6142 Make_Case_Statement_Alternative (Loc,
6143 Discrete_Choices => New_List (
6144 Make_Integer_Literal (Loc, Num_Comps)),
6146 Statements => New_List (
6147 Make_Goto_Statement (Loc,
6149 New_Reference_To (Entity (Label_Id), Loc)))));
6154 Append_To (Stmts, Label);
6156 -- Decrease the number of components to be processed.
6157 -- This action yields a new Label_Id in future calls.
6159 Num_Comps := Num_Comps - 1;
6164 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6166 -- begin -- Exception handlers allowed
6167 -- [Deep_]Finalize (V.Id);
6170 -- if not Raised then
6172 -- Save_Occurrence (E,
6173 -- Get_Current_Excep.all.all);
6180 Make_Selected_Component (Loc,
6181 Prefix => Make_Identifier (Loc, Name_V),
6182 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6185 if not Restriction_Active (No_Exception_Propagation) then
6187 Make_Block_Statement (Loc,
6188 Handled_Statement_Sequence =>
6189 Make_Handled_Sequence_Of_Statements (Loc,
6190 Statements => New_List (Fin_Stmt),
6191 Exception_Handlers => New_List (
6192 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
6195 Append_To (Stmts, Fin_Stmt);
6196 end Process_Component_For_Finalize;
6198 -- Start of processing for Process_Component_List_For_Finalize
6201 -- Perform an initial check, look for controlled and per-object
6202 -- constrained components.
6204 Preprocess_Components (Comps, Num_Comps, Has_POC);
6206 -- Create a state counter to service the current component list.
6207 -- This step is performed before the variants are inspected in
6208 -- order to generate the same state counter names as those from
6209 -- Build_Initialize_Statements.
6214 Counter := Counter + 1;
6217 Make_Defining_Identifier (Loc,
6218 Chars => New_External_Name ('C', Counter));
6221 -- Process the component in the following order:
6223 -- 2) Per-object constrained components
6224 -- 3) Regular components
6226 -- Start with the variant parts
6229 if Present (Variant_Part (Comps)) then
6231 Var_Alts : constant List_Id := New_List;
6235 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6236 while Present (Var) loop
6239 -- when <discrete choices> =>
6240 -- <finalize statements>
6242 Append_To (Var_Alts,
6243 Make_Case_Statement_Alternative (Loc,
6245 New_Copy_List (Discrete_Choices (Var)),
6247 Process_Component_List_For_Finalize (
6248 Component_List (Var))));
6250 Next_Non_Pragma (Var);
6254 -- case V.<discriminant> is
6255 -- when <discrete choices 1> =>
6256 -- <finalize statements 1>
6258 -- when <discrete choices N> =>
6259 -- <finalize statements N>
6263 Make_Case_Statement (Loc,
6265 Make_Selected_Component (Loc,
6266 Prefix => Make_Identifier (Loc, Name_V),
6268 Make_Identifier (Loc,
6269 Chars => Chars (Name (Variant_Part (Comps))))),
6270 Alternatives => Var_Alts);
6274 -- The current component list does not have a single controlled
6275 -- component, however it may contain variants. Return the case
6276 -- statement for the variants or nothing.
6278 if Num_Comps = 0 then
6279 if Present (Var_Case) then
6280 return New_List (Var_Case);
6282 return New_List (Make_Null_Statement (Loc));
6286 -- Prepare all lists
6292 -- Process all per-object constrained components in reverse order
6295 Decl := Last_Non_Pragma (Component_Items (Comps));
6296 while Present (Decl) loop
6297 Decl_Id := Defining_Identifier (Decl);
6298 Decl_Typ := Etype (Decl_Id);
6302 if Chars (Decl_Id) /= Name_uParent
6303 and then Needs_Finalization (Decl_Typ)
6304 and then Has_Access_Constraint (Decl_Id)
6305 and then No (Expression (Decl))
6307 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6310 Prev_Non_Pragma (Decl);
6314 -- Process the rest of the components in reverse order
6316 Decl := Last_Non_Pragma (Component_Items (Comps));
6317 while Present (Decl) loop
6318 Decl_Id := Defining_Identifier (Decl);
6319 Decl_Typ := Etype (Decl_Id);
6323 if Chars (Decl_Id) /= Name_uParent
6324 and then Needs_Finalization (Decl_Typ)
6326 -- Skip per-object constrained components since they were
6327 -- handled in the above step.
6329 if Has_Access_Constraint (Decl_Id)
6330 and then No (Expression (Decl))
6334 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6338 Prev_Non_Pragma (Decl);
6343 -- LN : label; -- If Is_Local is enabled
6348 -- case CounterX is .
6358 -- <<LN>> -- If Is_Local is enabled
6360 -- [Deep_]Finalize (V.CompY);
6362 -- when Id : others =>
6363 -- if not Raised then
6365 -- Save_Occurrence (E,
6366 -- Get_Current_Excep.all.all);
6370 -- <<L0>> -- If Is_Local is enabled
6375 -- Add the declaration of default jump location L0, its
6376 -- corresponding alternative and its place in the statements.
6378 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6379 Set_Entity (Label_Id,
6380 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6381 Label := Make_Label (Loc, Label_Id);
6383 Append_To (Decls, -- declaration
6384 Make_Implicit_Label_Declaration (Loc,
6385 Defining_Identifier => Entity (Label_Id),
6386 Label_Construct => Label));
6388 Append_To (Alts, -- alternative
6389 Make_Case_Statement_Alternative (Loc,
6390 Discrete_Choices => New_List (
6391 Make_Others_Choice (Loc)),
6393 Statements => New_List (
6394 Make_Goto_Statement (Loc,
6395 Name => New_Reference_To (Entity (Label_Id), Loc)))));
6397 Append_To (Stmts, Label); -- statement
6399 -- Create the jump block
6402 Make_Case_Statement (Loc,
6403 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
6404 Alternatives => Alts));
6408 Make_Block_Statement (Loc,
6409 Declarations => Decls,
6410 Handled_Statement_Sequence =>
6411 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6413 if Present (Var_Case) then
6414 return New_List (Var_Case, Jump_Block);
6416 return New_List (Jump_Block);
6418 end Process_Component_List_For_Finalize;
6420 -- Start of processing for Build_Finalize_Statements
6423 if Exceptions_OK then
6424 Abort_Id := Make_Temporary (Loc, 'A');
6425 E_Id := Make_Temporary (Loc, 'E');
6426 Raised_Id := Make_Temporary (Loc, 'R');
6429 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6430 Rec_Def := Record_Extension_Part (Typ_Def);
6435 -- Create a finalization sequence for all record components
6437 if Present (Component_List (Rec_Def)) then
6439 Process_Component_List_For_Finalize (Component_List (Rec_Def));
6442 -- A derived record type must finalize all inherited components. This
6443 -- action poses the following problem:
6445 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6450 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6452 -- Deep_Finalize (Obj._parent);
6457 -- Finalizing the derived type will invoke Finalize of the parent and
6458 -- then that of the derived type. This is undesirable because both
6459 -- routines may modify shared components. Only the Finalize of the
6460 -- derived type should be invoked.
6462 -- To prevent this double adjustment of shared components,
6463 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6465 -- procedure Deep_Finalize
6466 -- (Obj : in out Some_Type;
6467 -- Flag : Boolean := True)
6475 -- When Deep_Finalize is invokes for field _parent, a value of False
6476 -- is provided for the flag:
6478 -- Deep_Finalize (Obj._parent, False);
6480 if Is_Tagged_Type (Typ)
6481 and then Is_Derived_Type (Typ)
6484 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6489 if Needs_Finalization (Par_Typ) then
6493 Make_Selected_Component (Loc,
6494 Prefix => Make_Identifier (Loc, Name_V),
6496 Make_Identifier (Loc, Name_uParent)),
6498 For_Parent => True);
6501 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
6503 -- begin -- Exceptions OK
6504 -- Deep_Finalize (V._parent, False);
6506 -- when Id : others =>
6507 -- if not Raised then
6509 -- Save_Occurrence (E,
6510 -- Get_Current_Excep.all.all);
6514 if Present (Call) then
6517 if Exceptions_OK then
6519 Make_Block_Statement (Loc,
6520 Handled_Statement_Sequence =>
6521 Make_Handled_Sequence_Of_Statements (Loc,
6522 Statements => New_List (Fin_Stmt),
6523 Exception_Handlers => New_List (
6524 Build_Exception_Handler
6525 (Loc, E_Id, Raised_Id))));
6528 Append_To (Bod_Stmts, Fin_Stmt);
6534 -- Finalize the object. This action must be performed first before
6535 -- all components have been finalized.
6537 if Is_Controlled (Typ)
6538 and then not Is_Local
6545 Proc := Find_Prim_Op (Typ, Name_Finalize);
6549 -- Finalize (V); -- No_Exception_Propagation
6555 -- if not Raised then
6557 -- Save_Occurrence (E,
6558 -- Get_Current_Excep.all.all);
6563 if Present (Proc) then
6565 Make_Procedure_Call_Statement (Loc,
6566 Name => New_Reference_To (Proc, Loc),
6567 Parameter_Associations => New_List (
6568 Make_Identifier (Loc, Name_V)));
6570 if Exceptions_OK then
6572 Make_Block_Statement (Loc,
6573 Handled_Statement_Sequence =>
6574 Make_Handled_Sequence_Of_Statements (Loc,
6575 Statements => New_List (Fin_Stmt),
6576 Exception_Handlers => New_List (
6577 Build_Exception_Handler
6578 (Loc, E_Id, Raised_Id))));
6581 Prepend_To (Bod_Stmts,
6582 Make_If_Statement (Loc,
6583 Condition => Make_Identifier (Loc, Name_F),
6584 Then_Statements => New_List (Fin_Stmt)));
6589 -- At this point either all finalization statements have been
6590 -- generated or the type is not controlled.
6592 if No (Bod_Stmts) then
6593 return New_List (Make_Null_Statement (Loc));
6597 -- Abort : constant Boolean :=
6598 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6599 -- Standard'Abort_Signal'Identity;
6601 -- Abort : constant Boolean := False; -- no abort
6603 -- E : Exception_Occurence;
6604 -- Raised : Boolean := False;
6607 -- if V.Finalized then
6611 -- <finalize statements>
6612 -- V.Finalized := True;
6615 -- Raise_From_Controlled_Operation (E, Abort);
6620 if Exceptions_OK then
6621 Append_To (Bod_Stmts,
6622 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6627 Make_Block_Statement (Loc,
6629 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6630 Handled_Statement_Sequence =>
6631 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6633 end Build_Finalize_Statements;
6635 -----------------------
6636 -- Parent_Field_Type --
6637 -----------------------
6639 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
6643 Field := First_Entity (Typ);
6644 while Present (Field) loop
6645 if Chars (Field) = Name_uParent then
6646 return Etype (Field);
6649 Next_Entity (Field);
6652 -- A derived tagged type should always have a parent field
6654 raise Program_Error;
6655 end Parent_Field_Type;
6657 ---------------------------
6658 -- Preprocess_Components --
6659 ---------------------------
6661 procedure Preprocess_Components
6663 Num_Comps : out Int;
6664 Has_POC : out Boolean)
6674 Decl := First_Non_Pragma (Component_Items (Comps));
6675 while Present (Decl) loop
6676 Id := Defining_Identifier (Decl);
6679 -- Skip field _parent
6681 if Chars (Id) /= Name_uParent
6682 and then Needs_Finalization (Typ)
6684 Num_Comps := Num_Comps + 1;
6686 if Has_Access_Constraint (Id)
6687 and then No (Expression (Decl))
6693 Next_Non_Pragma (Decl);
6695 end Preprocess_Components;
6697 -- Start of processing for Make_Deep_Record_Body
6701 when Address_Case =>
6702 return Make_Finalize_Address_Stmts (Typ);
6705 return Build_Adjust_Statements (Typ);
6707 when Finalize_Case =>
6708 return Build_Finalize_Statements (Typ);
6710 when Initialize_Case =>
6712 Loc : constant Source_Ptr := Sloc (Typ);
6715 if Is_Controlled (Typ) then
6717 Make_Procedure_Call_Statement (Loc,
6720 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
6721 Parameter_Associations => New_List (
6722 Make_Identifier (Loc, Name_V))));
6728 end Make_Deep_Record_Body;
6730 ----------------------
6731 -- Make_Final_Call --
6732 ----------------------
6734 function Make_Final_Call
6737 For_Parent : Boolean := False) return Node_Id
6739 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6741 Fin_Id : Entity_Id := Empty;
6746 -- Recover the proper type which contains [Deep_]Finalize
6748 if Is_Class_Wide_Type (Typ) then
6749 Utyp := Root_Type (Typ);
6753 elsif Is_Concurrent_Type (Typ) then
6754 Utyp := Corresponding_Record_Type (Typ);
6756 Ref := Convert_Concurrent (Obj_Ref, Typ);
6758 elsif Is_Private_Type (Typ)
6759 and then Present (Full_View (Typ))
6760 and then Is_Concurrent_Type (Full_View (Typ))
6762 Utyp := Corresponding_Record_Type (Full_View (Typ));
6764 Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ));
6772 Utyp := Underlying_Type (Base_Type (Utyp));
6773 Set_Assignment_OK (Ref);
6775 -- Deal with non-tagged derivation of private views. If the parent type
6776 -- is a protected type, Deep_Finalize is found on the corresponding
6777 -- record of the ancestor.
6779 if Is_Untagged_Derivation (Typ) then
6780 if Is_Protected_Type (Typ) then
6781 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
6783 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6785 if Is_Protected_Type (Utyp) then
6786 Utyp := Corresponding_Record_Type (Utyp);
6790 Ref := Unchecked_Convert_To (Utyp, Ref);
6791 Set_Assignment_OK (Ref);
6794 -- Deal with derived private types which do not inherit primitives from
6795 -- their parents. In this case, [Deep_]Finalize can be found in the full
6796 -- view of the parent type.
6798 if Is_Tagged_Type (Utyp)
6799 and then Is_Derived_Type (Utyp)
6800 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
6801 and then Is_Private_Type (Etype (Utyp))
6802 and then Present (Full_View (Etype (Utyp)))
6804 Utyp := Full_View (Etype (Utyp));
6805 Ref := Unchecked_Convert_To (Utyp, Ref);
6806 Set_Assignment_OK (Ref);
6809 -- When dealing with the completion of a private type, use the base type
6812 if Utyp /= Base_Type (Utyp) then
6813 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
6815 Utyp := Base_Type (Utyp);
6816 Ref := Unchecked_Convert_To (Utyp, Ref);
6817 Set_Assignment_OK (Ref);
6820 -- Select the appropriate version of finalize
6823 if Has_Controlled_Component (Utyp) then
6824 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6827 -- For types that are both controlled and have controlled components,
6828 -- generate a call to Deep_Finalize.
6830 elsif Is_Controlled (Utyp)
6831 and then Has_Controlled_Component (Utyp)
6833 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6835 -- For types that are not controlled themselves, but contain controlled
6836 -- components or can be extended by types with controlled components,
6837 -- create a call to Deep_Finalize.
6839 elsif Is_Class_Wide_Type (Typ)
6840 or else Is_Interface (Typ)
6841 or else Has_Controlled_Component (Utyp)
6843 if Is_Tagged_Type (Utyp) then
6844 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6846 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
6849 -- For types that are derived from Controlled and do not have controlled
6850 -- components, build a call to Finalize.
6853 Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
6856 if Present (Fin_Id) then
6858 -- When finalizing a class-wide object, do not convert to the root
6859 -- type in order to produce a dispatching call.
6861 if Is_Class_Wide_Type (Typ) then
6864 -- Ensure that a finalization routine is at least decorated in order
6865 -- to inspect the object parameter.
6867 elsif Analyzed (Fin_Id)
6868 or else Ekind (Fin_Id) = E_Procedure
6870 -- In certain cases, such as the creation of Stream_Read, the
6871 -- visible entity of the type is its full view. Since Stream_Read
6872 -- will have to create an object of type Typ, the local object
6873 -- will be finalzed by the scope finalizer generated later on. The
6874 -- object parameter of Deep_Finalize will always use the private
6875 -- view of the type. To avoid such a clash between a private and a
6876 -- full view, perform an unchecked conversion of the object
6877 -- reference to the private view.
6880 Formal_Typ : constant Entity_Id :=
6881 Etype (First_Formal (Fin_Id));
6883 if Is_Private_Type (Formal_Typ)
6884 and then Present (Full_View (Formal_Typ))
6885 and then Full_View (Formal_Typ) = Utyp
6887 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
6891 Ref := Convert_View (Fin_Id, Ref);
6894 return Make_Call (Loc, Fin_Id, New_Copy_Tree (Ref), For_Parent);
6898 end Make_Final_Call;
6900 --------------------------------
6901 -- Make_Finalize_Address_Body --
6902 --------------------------------
6904 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
6906 -- Nothing to do if the type is not controlled or it already has a
6907 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
6908 -- come from source. These are usually generated for completeness and
6909 -- do not need the Finalize_Address primitive.
6911 if not Needs_Finalization (Typ)
6912 or else Present (TSS (Typ, TSS_Finalize_Address))
6914 (Is_Class_Wide_Type (Typ)
6915 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
6916 and then not Comes_From_Source (Root_Type (Typ)))
6922 Loc : constant Source_Ptr := Sloc (Typ);
6923 Proc_Id : Entity_Id;
6927 Make_Defining_Identifier (Loc,
6928 Make_TSS_Name (Typ, TSS_Finalize_Address));
6931 -- procedure TypFD (V : System.Address) is
6934 -- type Pnn is access all Typ;
6935 -- for Pnn'Storage_Size use 0;
6937 -- [Deep_]Finalize (Pnn (V).all);
6942 Make_Subprogram_Body (Loc,
6944 Make_Procedure_Specification (Loc,
6945 Defining_Unit_Name => Proc_Id,
6947 Parameter_Specifications => New_List (
6948 Make_Parameter_Specification (Loc,
6949 Defining_Identifier =>
6950 Make_Defining_Identifier (Loc, Name_V),
6952 New_Reference_To (RTE (RE_Address), Loc)))),
6954 Declarations => No_List,
6956 Handled_Statement_Sequence =>
6957 Make_Handled_Sequence_Of_Statements (Loc,
6959 Make_Finalize_Address_Stmts (Typ))));
6961 Set_TSS (Typ, Proc_Id);
6963 end Make_Finalize_Address_Body;
6965 ---------------------------------
6966 -- Make_Finalize_Address_Stmts --
6967 ---------------------------------
6969 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
6970 Loc : constant Source_Ptr := Sloc (Typ);
6971 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
6973 Desg_Typ : Entity_Id;
6976 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
6977 -- Subsidiary routine, generate the following attribute reference:
6979 -- Some_Typ'Alignment
6981 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
6982 -- Subsidiary routine, generate the following expression:
6984 -- 2 * Some_Typ'Alignment
6990 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
6993 Make_Attribute_Reference (Loc,
6994 Prefix => New_Reference_To (Some_Typ, Loc),
6995 Attribute_Name => Name_Alignment);
6998 -------------------------
6999 -- Double_Alignment_Of --
7000 -------------------------
7002 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
7005 Make_Op_Multiply (Loc,
7006 Left_Opnd => Make_Integer_Literal (Loc, 2),
7007 Right_Opnd => Alignment_Of (Some_Typ));
7008 end Double_Alignment_Of;
7010 -- Start of processing for Make_Finalize_Address_Stmts
7013 if Is_Array_Type (Typ) then
7014 if Is_Constrained (First_Subtype (Typ)) then
7015 Desg_Typ := First_Subtype (Typ);
7017 Desg_Typ := Base_Type (Typ);
7020 -- Class-wide types of constrained root types
7022 elsif Is_Class_Wide_Type (Typ)
7023 and then Has_Discriminants (Root_Type (Typ))
7025 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7028 Parent_Typ : Entity_Id := Root_Type (Typ);
7031 -- Climb the parent type chain looking for a non-constrained type
7033 while Parent_Typ /= Etype (Parent_Typ)
7034 and then Has_Discriminants (Parent_Typ)
7036 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7038 Parent_Typ := Etype (Parent_Typ);
7041 -- Handle views created for tagged types with unknown
7044 if Is_Underlying_Record_View (Parent_Typ) then
7045 Parent_Typ := Underlying_Record_View (Parent_Typ);
7048 Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
7058 -- type Ptr_Typ is access all Typ;
7059 -- for Ptr_Typ'Storage_Size use 0;
7062 Make_Full_Type_Declaration (Loc,
7063 Defining_Identifier => Ptr_Typ,
7065 Make_Access_To_Object_Definition (Loc,
7066 All_Present => True,
7067 Subtype_Indication => New_Reference_To (Desg_Typ, Loc))),
7069 Make_Attribute_Definition_Clause (Loc,
7070 Name => New_Reference_To (Ptr_Typ, Loc),
7071 Chars => Name_Storage_Size,
7072 Expression => Make_Integer_Literal (Loc, 0)));
7074 Obj_Expr := Make_Identifier (Loc, Name_V);
7076 -- Unconstrained arrays require special processing in order to retrieve
7077 -- the elements. To achieve this, we have to skip the dope vector which
7078 -- lays in front of the elements and then use a thin pointer to perform
7079 -- the address-to-access conversion.
7081 if Is_Array_Type (Typ)
7082 and then not Is_Constrained (First_Subtype (Typ))
7085 Dope_Expr : Node_Id;
7086 Dope_Id : Entity_Id;
7087 For_First : Boolean := True;
7089 Index_Typ : Entity_Id;
7092 -- Ensure that Ptr_Typ a thin pointer, generate:
7094 -- for Ptr_Typ'Size use System.Address'Size;
7097 Make_Attribute_Definition_Clause (Loc,
7098 Name => New_Reference_To (Ptr_Typ, Loc),
7101 Make_Integer_Literal (Loc, System_Address_Size)));
7103 -- For unconstrained arrays, create the expression which computes
7104 -- the size of the dope vector.
7106 Index := First_Index (Typ);
7107 while Present (Index) loop
7108 Index_Typ := Etype (Index);
7110 -- Each bound has two values and a potential hole added to
7111 -- compensate for alignment differences.
7117 -- 2 * Index_Typ'Alignment
7119 Dope_Expr := Double_Alignment_Of (Index_Typ);
7123 -- Dope_Expr + 2 * Index_Typ'Alignment
7127 Left_Opnd => Dope_Expr,
7128 Right_Opnd => Double_Alignment_Of (Index_Typ));
7134 -- Round the cumulative alignment to the next higher multiple of
7135 -- the array alignment. Generate:
7137 -- ((Dope_Expr + Typ'Alignment - 1) / Typ'Alignment)
7141 Make_Op_Multiply (Loc,
7143 Make_Op_Divide (Loc,
7146 Left_Opnd => Dope_Expr,
7148 Make_Op_Subtract (Loc,
7149 Left_Opnd => Alignment_Of (Typ),
7150 Right_Opnd => Make_Integer_Literal (Loc, 1))),
7151 Right_Opnd => Alignment_Of (Typ)),
7152 Right_Opnd => Alignment_Of (Typ));
7155 -- Dnn : Storage_Offset := Dope_Expr;
7157 Dope_Id := Make_Temporary (Loc, 'D');
7160 Make_Object_Declaration (Loc,
7161 Defining_Identifier => Dope_Id,
7162 Constant_Present => True,
7163 Object_Definition =>
7164 New_Reference_To (RTE (RE_Storage_Offset), Loc),
7165 Expression => Dope_Expr));
7167 -- Shift the address from the start of the dope vector to the
7168 -- start of the elements:
7172 -- Note that this is done through a wrapper routine since RTSfind
7173 -- cannot retrieve operations with string names of the form "+".
7176 Make_Function_Call (Loc,
7178 New_Reference_To (RTE (RE_Add_Offset_To_Address), Loc),
7179 Parameter_Associations => New_List (
7181 New_Reference_To (Dope_Id, Loc)));
7185 -- Create the block and the finalization call
7188 Make_Block_Statement (Loc,
7189 Declarations => Decls,
7191 Handled_Statement_Sequence =>
7192 Make_Handled_Sequence_Of_Statements (Loc,
7193 Statements => New_List (
7196 Make_Explicit_Dereference (Loc,
7197 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7198 Typ => Desg_Typ)))));
7199 end Make_Finalize_Address_Stmts;
7201 -------------------------------------
7202 -- Make_Handler_For_Ctrl_Operation --
7203 -------------------------------------
7207 -- when E : others =>
7208 -- Raise_From_Controlled_Operation (E, False);
7213 -- raise Program_Error [finalize raised exception];
7215 -- depending on whether Raise_From_Controlled_Operation is available
7217 function Make_Handler_For_Ctrl_Operation
7218 (Loc : Source_Ptr) return Node_Id
7221 -- Choice parameter (for the first case above)
7223 Raise_Node : Node_Id;
7224 -- Procedure call or raise statement
7227 -- Standard runtime, .NET/JVM targets: add choice parameter E and pass
7228 -- it to Raise_From_Controlled_Operation so that the original exception
7229 -- name and message can be recorded in the exception message for
7232 if RTE_Available (RE_Raise_From_Controlled_Operation) then
7233 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7235 Make_Procedure_Call_Statement (Loc,
7238 (RTE (RE_Raise_From_Controlled_Operation), Loc),
7239 Parameter_Associations => New_List (
7240 New_Reference_To (E_Occ, Loc),
7241 New_Reference_To (Standard_False, Loc)));
7243 -- Restricted runtime: exception messages are not supported
7248 Make_Raise_Program_Error (Loc,
7249 Reason => PE_Finalize_Raised_Exception);
7253 Make_Implicit_Exception_Handler (Loc,
7254 Exception_Choices => New_List (Make_Others_Choice (Loc)),
7255 Choice_Parameter => E_Occ,
7256 Statements => New_List (Raise_Node));
7257 end Make_Handler_For_Ctrl_Operation;
7259 --------------------
7260 -- Make_Init_Call --
7261 --------------------
7263 function Make_Init_Call
7265 Typ : Entity_Id) return Node_Id
7267 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7274 -- Deal with the type and object reference. Depending on the context, an
7275 -- object reference may need several conversions.
7277 if Is_Concurrent_Type (Typ) then
7279 Utyp := Corresponding_Record_Type (Typ);
7280 Ref := Convert_Concurrent (Obj_Ref, Typ);
7282 elsif Is_Private_Type (Typ)
7283 and then Present (Full_View (Typ))
7284 and then Is_Concurrent_Type (Underlying_Type (Typ))
7287 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7288 Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7296 Set_Assignment_OK (Ref);
7298 Utyp := Underlying_Type (Base_Type (Utyp));
7300 -- Deal with non-tagged derivation of private views
7302 if Is_Untagged_Derivation (Typ)
7303 and then not Is_Conc
7305 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7306 Ref := Unchecked_Convert_To (Utyp, Ref);
7308 -- The following is to prevent problems with UC see 1.156 RH ???
7310 Set_Assignment_OK (Ref);
7313 -- If the underlying_type is a subtype, then we are dealing with the
7314 -- completion of a private type. We need to access the base type and
7315 -- generate a conversion to it.
7317 if Utyp /= Base_Type (Utyp) then
7318 pragma Assert (Is_Private_Type (Typ));
7319 Utyp := Base_Type (Utyp);
7320 Ref := Unchecked_Convert_To (Utyp, Ref);
7323 -- Select the appropriate version of initialize
7325 if Has_Controlled_Component (Utyp) then
7326 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7328 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7329 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7332 -- The object reference may need another conversion depending on the
7333 -- type of the formal and that of the actual.
7335 Ref := Convert_View (Proc, Ref);
7338 -- [Deep_]Initialize (Ref);
7341 Make_Procedure_Call_Statement (Loc,
7343 New_Reference_To (Proc, Loc),
7344 Parameter_Associations => New_List (Ref));
7347 ------------------------------
7348 -- Make_Local_Deep_Finalize --
7349 ------------------------------
7351 function Make_Local_Deep_Finalize
7353 Nam : Entity_Id) return Node_Id
7355 Loc : constant Source_Ptr := Sloc (Typ);
7359 Formals := New_List (
7363 Make_Parameter_Specification (Loc,
7364 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7366 Out_Present => True,
7367 Parameter_Type => New_Reference_To (Typ, Loc)),
7369 -- F : Boolean := True
7371 Make_Parameter_Specification (Loc,
7372 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7373 Parameter_Type => New_Reference_To (Standard_Boolean, Loc),
7374 Expression => New_Reference_To (Standard_True, Loc)));
7376 -- Add the necessary number of counters to represent the initialization
7377 -- state of an object.
7380 Make_Subprogram_Body (Loc,
7382 Make_Procedure_Specification (Loc,
7383 Defining_Unit_Name => Nam,
7384 Parameter_Specifications => Formals),
7386 Declarations => No_List,
7388 Handled_Statement_Sequence =>
7389 Make_Handled_Sequence_Of_Statements (Loc,
7390 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7391 end Make_Local_Deep_Finalize;
7393 ----------------------------------------
7394 -- Make_Set_Finalize_Address_Ptr_Call --
7395 ----------------------------------------
7397 function Make_Set_Finalize_Address_Ptr_Call
7400 Ptr_Typ : Entity_Id) return Node_Id
7402 Desig_Typ : constant Entity_Id :=
7403 Available_View (Designated_Type (Ptr_Typ));
7407 -- If the context is a class-wide allocator, we use the class-wide type
7408 -- to obtain the proper Finalize_Address routine.
7410 if Is_Class_Wide_Type (Desig_Typ) then
7416 if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
7417 Utyp := Full_View (Utyp);
7420 if Is_Concurrent_Type (Utyp) then
7421 Utyp := Corresponding_Record_Type (Utyp);
7425 Utyp := Underlying_Type (Base_Type (Utyp));
7427 -- Deal with non-tagged derivation of private views. If the parent is
7428 -- now known to be protected, the finalization routine is the one
7429 -- defined on the corresponding record of the ancestor (corresponding
7430 -- records do not automatically inherit operations, but maybe they
7433 if Is_Untagged_Derivation (Typ) then
7434 if Is_Protected_Type (Typ) then
7435 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7437 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7439 if Is_Protected_Type (Utyp) then
7440 Utyp := Corresponding_Record_Type (Utyp);
7445 -- If the underlying_type is a subtype, we are dealing with the
7446 -- completion of a private type. We need to access the base type and
7447 -- generate a conversion to it.
7449 if Utyp /= Base_Type (Utyp) then
7450 pragma Assert (Is_Private_Type (Typ));
7452 Utyp := Base_Type (Utyp);
7456 -- Set_Finalize_Address_Ptr
7457 -- (<Ptr_Typ>FC, <Utyp>FD'Unrestricted_Access);
7460 Make_Procedure_Call_Statement (Loc,
7462 New_Reference_To (RTE (RE_Set_Finalize_Address_Ptr), Loc),
7464 Parameter_Associations => New_List (
7465 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
7467 Make_Attribute_Reference (Loc,
7469 New_Reference_To (TSS (Utyp, TSS_Finalize_Address), Loc),
7470 Attribute_Name => Name_Unrestricted_Access)));
7471 end Make_Set_Finalize_Address_Ptr_Call;
7473 --------------------------
7474 -- Make_Transient_Block --
7475 --------------------------
7477 function Make_Transient_Block
7480 Par : Node_Id) return Node_Id
7482 Decls : constant List_Id := New_List;
7483 Instrs : constant List_Id := New_List (Action);
7488 -- Case where only secondary stack use is involved
7490 if VM_Target = No_VM
7491 and then Uses_Sec_Stack (Current_Scope)
7492 and then Nkind (Action) /= N_Simple_Return_Statement
7493 and then Nkind (Par) /= N_Exception_Handler
7499 S := Scope (Current_Scope);
7501 -- At the outer level, no need to release the sec stack
7503 if S = Standard_Standard then
7504 Set_Uses_Sec_Stack (Current_Scope, False);
7507 -- In a function, only release the sec stack if the
7508 -- function does not return on the sec stack otherwise
7509 -- the result may be lost. The caller is responsible for
7512 elsif Ekind (S) = E_Function then
7513 Set_Uses_Sec_Stack (Current_Scope, False);
7515 if not Requires_Transient_Scope (Etype (S)) then
7516 Set_Uses_Sec_Stack (S, True);
7517 Check_Restriction (No_Secondary_Stack, Action);
7522 -- In a loop or entry we should install a block encompassing
7523 -- all the construct. For now just release right away.
7525 elsif Ekind_In (S, E_Entry, E_Loop) then
7528 -- In a procedure or a block, we release on exit of the
7529 -- procedure or block. ??? memory leak can be created by
7532 elsif Ekind_In (S, E_Block, E_Procedure) then
7533 Set_Uses_Sec_Stack (S, True);
7534 Check_Restriction (No_Secondary_Stack, Action);
7535 Set_Uses_Sec_Stack (Current_Scope, False);
7545 -- Create the transient block. Set the parent now since the block itself
7546 -- is not part of the tree.
7549 Make_Block_Statement (Loc,
7550 Identifier => New_Reference_To (Current_Scope, Loc),
7551 Declarations => Decls,
7552 Handled_Statement_Sequence =>
7553 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7554 Has_Created_Identifier => True);
7555 Set_Parent (Block, Par);
7557 -- Insert actions stuck in the transient scopes as well as all freezing
7558 -- nodes needed by those actions.
7560 Insert_Actions_In_Scope_Around (Action);
7562 Insert := Prev (Action);
7563 if Present (Insert) then
7564 Freeze_All (First_Entity (Current_Scope), Insert);
7567 -- When the transient scope was established, we pushed the entry for
7568 -- the transient scope onto the scope stack, so that the scope was
7569 -- active for the installation of finalizable entities etc. Now we
7570 -- must remove this entry, since we have constructed a proper block.
7575 end Make_Transient_Block;
7577 ------------------------
7578 -- Node_To_Be_Wrapped --
7579 ------------------------
7581 function Node_To_Be_Wrapped return Node_Id is
7583 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
7584 end Node_To_Be_Wrapped;
7586 ----------------------------
7587 -- Set_Node_To_Be_Wrapped --
7588 ----------------------------
7590 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
7592 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
7593 end Set_Node_To_Be_Wrapped;
7595 ----------------------------------
7596 -- Store_After_Actions_In_Scope --
7597 ----------------------------------
7599 procedure Store_After_Actions_In_Scope (L : List_Id) is
7600 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7603 if Present (SE.Actions_To_Be_Wrapped_After) then
7604 Insert_List_Before_And_Analyze (
7605 First (SE.Actions_To_Be_Wrapped_After), L);
7608 SE.Actions_To_Be_Wrapped_After := L;
7610 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7611 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7613 Set_Parent (L, SE.Node_To_Be_Wrapped);
7618 end Store_After_Actions_In_Scope;
7620 -----------------------------------
7621 -- Store_Before_Actions_In_Scope --
7622 -----------------------------------
7624 procedure Store_Before_Actions_In_Scope (L : List_Id) is
7625 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7628 if Present (SE.Actions_To_Be_Wrapped_Before) then
7629 Insert_List_After_And_Analyze (
7630 Last (SE.Actions_To_Be_Wrapped_Before), L);
7633 SE.Actions_To_Be_Wrapped_Before := L;
7635 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7636 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7638 Set_Parent (L, SE.Node_To_Be_Wrapped);
7643 end Store_Before_Actions_In_Scope;
7645 --------------------------------
7646 -- Wrap_Transient_Declaration --
7647 --------------------------------
7649 -- If a transient scope has been established during the processing of the
7650 -- Expression of an Object_Declaration, it is not possible to wrap the
7651 -- declaration into a transient block as usual case, otherwise the object
7652 -- would be itself declared in the wrong scope. Therefore, all entities (if
7653 -- any) defined in the transient block are moved to the proper enclosing
7654 -- scope, furthermore, if they are controlled variables they are finalized
7655 -- right after the declaration. The finalization list of the transient
7656 -- scope is defined as a renaming of the enclosing one so during their
7657 -- initialization they will be attached to the proper finalization list.
7658 -- For instance, the following declaration :
7660 -- X : Typ := F (G (A), G (B));
7662 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7663 -- is expanded into :
7665 -- X : Typ := [ complex Expression-Action ];
7666 -- [Deep_]Finalize (_v1);
7667 -- [Deep_]Finalize (_v2);
7669 procedure Wrap_Transient_Declaration (N : Node_Id) is
7676 Encl_S := Scope (S);
7678 -- Insert Actions kept in the Scope stack
7680 Insert_Actions_In_Scope_Around (N);
7682 -- If the declaration is consuming some secondary stack, mark the
7683 -- enclosing scope appropriately.
7685 Uses_SS := Uses_Sec_Stack (S);
7688 -- Put the local entities back in the enclosing scope, and set the
7689 -- Is_Public flag appropriately.
7691 Transfer_Entities (S, Encl_S);
7693 -- Mark the enclosing dynamic scope so that the sec stack will be
7694 -- released upon its exit unless this is a function that returns on
7695 -- the sec stack in which case this will be done by the caller.
7697 if VM_Target = No_VM and then Uses_SS then
7698 S := Enclosing_Dynamic_Scope (S);
7700 if Ekind (S) = E_Function
7701 and then Requires_Transient_Scope (Etype (S))
7705 Set_Uses_Sec_Stack (S);
7706 Check_Restriction (No_Secondary_Stack, N);
7709 end Wrap_Transient_Declaration;
7711 -------------------------------
7712 -- Wrap_Transient_Expression --
7713 -------------------------------
7715 procedure Wrap_Transient_Expression (N : Node_Id) is
7716 Expr : constant Node_Id := Relocate_Node (N);
7717 Loc : constant Source_Ptr := Sloc (N);
7718 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
7719 Typ : constant Entity_Id := Etype (N);
7726 -- M : constant Mark_Id := SS_Mark;
7727 -- procedure Finalizer is ... (See Build_Finalizer)
7736 Insert_Actions (N, New_List (
7737 Make_Object_Declaration (Loc,
7738 Defining_Identifier => Temp,
7739 Object_Definition => New_Reference_To (Typ, Loc)),
7741 Make_Transient_Block (Loc,
7743 Make_Assignment_Statement (Loc,
7744 Name => New_Reference_To (Temp, Loc),
7745 Expression => Expr),
7746 Par => Parent (N))));
7748 Rewrite (N, New_Reference_To (Temp, Loc));
7749 Analyze_And_Resolve (N, Typ);
7750 end Wrap_Transient_Expression;
7752 ------------------------------
7753 -- Wrap_Transient_Statement --
7754 ------------------------------
7756 procedure Wrap_Transient_Statement (N : Node_Id) is
7757 Loc : constant Source_Ptr := Sloc (N);
7758 New_Stmt : constant Node_Id := Relocate_Node (N);
7763 -- M : constant Mark_Id := SS_Mark;
7764 -- procedure Finalizer is ... (See Build_Finalizer)
7774 Make_Transient_Block (Loc,
7776 Par => Parent (N)));
7778 -- With the scope stack back to normal, we can call analyze on the
7779 -- resulting block. At this point, the transient scope is being
7780 -- treated like a perfectly normal scope, so there is nothing
7781 -- special about it.
7783 -- Note: Wrap_Transient_Statement is called with the node already
7784 -- analyzed (i.e. Analyzed (N) is True). This is important, since
7785 -- otherwise we would get a recursive processing of the node when
7786 -- we do this Analyze call.
7789 end Wrap_Transient_Statement;