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.
2273 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
2274 -- Given a statement which is part of a list, return the next
2275 -- real statement while skipping over generated checks.
2281 function Is_Init_Call
2283 Typ : Entity_Id) return Boolean
2286 -- A call to [Deep_]Initialize is always direct
2288 if Nkind (N) = N_Procedure_Call_Statement
2289 and then Nkind (Name (N)) = N_Identifier
2292 Call_Nam : constant Name_Id := Chars (Entity (Name (N)));
2293 Deep_Init : constant Entity_Id :=
2294 TSS (Typ, TSS_Deep_Initialize);
2295 Init : Entity_Id := Empty;
2298 -- A type may have controlled components but not be
2301 if Is_Controlled (Typ) then
2302 Init := Find_Prim_Op (Typ, Name_Initialize);
2306 (Present (Deep_Init)
2307 and then Chars (Deep_Init) = Call_Nam)
2310 and then Chars (Init) = Call_Nam);
2317 -----------------------------
2318 -- Next_Suitable_Statement --
2319 -----------------------------
2321 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
2322 Result : Node_Id := Next (Stmt);
2325 -- Skip over access-before-elaboration checks
2327 if Dynamic_Elaboration_Checks
2328 and then Nkind (Result) = N_Raise_Program_Error
2330 Result := Next (Result);
2334 end Next_Suitable_Statement;
2336 -- Start of processing for Find_Last_Init
2340 Body_Insert := Empty;
2342 -- Object renamings and objects associated with controlled
2343 -- function results do not have initialization calls.
2349 if Is_Concurrent_Type (Typ) then
2350 Utyp := Corresponding_Record_Type (Typ);
2355 -- The init procedures are arranged as follows:
2357 -- Object : Controlled_Type;
2358 -- Controlled_TypeIP (Object);
2359 -- [[Deep_]Initialize (Object);]
2361 -- where the user-defined initialize may be optional or may appear
2362 -- inside a block when abort deferral is needed.
2364 Nod_1 := Next_Suitable_Statement (Decl);
2365 if Present (Nod_1) then
2366 Nod_2 := Next_Suitable_Statement (Nod_1);
2368 -- The statement following an object declaration is always a
2369 -- call to the type init proc.
2374 -- Optional user-defined init or deep init processing
2376 if Present (Nod_2) then
2378 -- The statement following the type init proc may be a block
2379 -- statement in cases where abort deferral is required.
2381 if Nkind (Nod_2) = N_Block_Statement then
2383 HSS : constant Node_Id :=
2384 Handled_Statement_Sequence (Nod_2);
2389 and then Present (Statements (HSS))
2391 Stmt := First (Statements (HSS));
2393 -- Examine individual block statements and locate the
2394 -- call to [Deep_]Initialze.
2396 while Present (Stmt) loop
2397 if Is_Init_Call (Stmt, Utyp) then
2399 Body_Insert := Nod_2;
2409 elsif Is_Init_Call (Nod_2, Utyp) then
2415 -- Start of processing for Process_Object_Declaration
2418 Obj_Ref := New_Reference_To (Obj_Id, Loc);
2419 Obj_Typ := Base_Type (Etype (Obj_Id));
2421 -- Handle access types
2423 if Is_Access_Type (Obj_Typ) then
2424 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2425 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2428 Set_Etype (Obj_Ref, Obj_Typ);
2430 -- Set a new value for the state counter and insert the statement
2431 -- after the object declaration. Generate:
2433 -- Counter := <value>;
2436 Make_Assignment_Statement (Loc,
2437 Name => New_Reference_To (Counter_Id, Loc),
2438 Expression => Make_Integer_Literal (Loc, Counter_Val));
2440 -- Insert the counter after all initialization has been done. The
2441 -- place of insertion depends on the context. When dealing with a
2442 -- controlled function, the counter is inserted directly after the
2443 -- declaration because such objects lack init calls.
2445 Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
2447 Insert_After (Count_Ins, Inc_Decl);
2450 -- If the current declaration is the last in the list, the finalizer
2451 -- body needs to be inserted after the set counter statement for the
2452 -- current object declaration. This is complicated by the fact that
2453 -- the set counter statement may appear in abort deferred block. In
2454 -- that case, the proper insertion place is after the block.
2456 if No (Finalizer_Insert_Nod) then
2458 -- Insertion after an abort deffered block
2460 if Present (Body_Ins) then
2461 Finalizer_Insert_Nod := Body_Ins;
2463 Finalizer_Insert_Nod := Inc_Decl;
2467 -- Create the associated label with this object, generate:
2469 -- L<counter> : label;
2472 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2473 Set_Entity (Label_Id,
2474 Make_Defining_Identifier (Loc, Chars (Label_Id)));
2475 Label := Make_Label (Loc, Label_Id);
2477 Prepend_To (Finalizer_Decls,
2478 Make_Implicit_Label_Declaration (Loc,
2479 Defining_Identifier => Entity (Label_Id),
2480 Label_Construct => Label));
2482 -- Create the associated jump with this object, generate:
2484 -- when <counter> =>
2487 Prepend_To (Jump_Alts,
2488 Make_Case_Statement_Alternative (Loc,
2489 Discrete_Choices => New_List (
2490 Make_Integer_Literal (Loc, Counter_Val)),
2491 Statements => New_List (
2492 Make_Goto_Statement (Loc,
2493 Name => New_Reference_To (Entity (Label_Id), Loc)))));
2495 -- Insert the jump destination, generate:
2499 Append_To (Finalizer_Stmts, Label);
2501 -- Processing for simple protected objects. Such objects require
2502 -- manual finalization of their lock managers.
2504 if Is_Protected then
2505 Fin_Stmts := No_List;
2507 if Is_Simple_Protected_Type (Obj_Typ) then
2508 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
2509 if Present (Fin_Call) then
2510 Fin_Stmts := New_List (Fin_Call);
2513 elsif Has_Simple_Protected_Object (Obj_Typ) then
2514 if Is_Record_Type (Obj_Typ) then
2515 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2517 elsif Is_Array_Type (Obj_Typ) then
2518 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2524 -- System.Tasking.Protected_Objects.Finalize_Protection
2532 if Present (Fin_Stmts) then
2533 Append_To (Finalizer_Stmts,
2534 Make_Block_Statement (Loc,
2535 Handled_Statement_Sequence =>
2536 Make_Handled_Sequence_Of_Statements (Loc,
2537 Statements => Fin_Stmts,
2539 Exception_Handlers => New_List (
2540 Make_Exception_Handler (Loc,
2541 Exception_Choices => New_List (
2542 Make_Others_Choice (Loc)),
2544 Statements => New_List (
2545 Make_Null_Statement (Loc)))))));
2548 -- Processing for regular controlled objects
2552 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2554 -- begin -- Exception handlers allowed
2555 -- [Deep_]Finalize (Obj);
2558 -- when Id : others =>
2559 -- if not Raised then
2561 -- Save_Occurrence (E, Id);
2570 if Exceptions_OK then
2571 Fin_Stmts := New_List (
2572 Make_Block_Statement (Loc,
2573 Handled_Statement_Sequence =>
2574 Make_Handled_Sequence_Of_Statements (Loc,
2575 Statements => New_List (Fin_Call),
2577 Exception_Handlers => New_List (
2578 Build_Exception_Handler
2579 (Loc, E_Id, Raised_Id, For_Package)))));
2581 -- When exception handlers are prohibited, the finalization call
2582 -- appears unprotected. Any exception raised during finalization
2583 -- will bypass the circuitry which ensures the cleanup of all
2584 -- remaining objects.
2587 Fin_Stmts := New_List (Fin_Call);
2590 -- If we are dealing with a return object of a build-in-place
2591 -- function, generate the following cleanup statements:
2593 -- if BIPallocfrom > Secondary_Stack'Pos then
2595 -- type Ptr_Typ is access Obj_Typ;
2596 -- for Ptr_Typ'Storage_Pool use
2597 -- Base_Pool (BIPcollection.all).all;
2600 -- Free (Ptr_Typ (Temp));
2604 -- The generated code effectively detaches the temporary from the
2605 -- caller finalization chain and deallocates the object. This is
2606 -- disabled on .NET/JVM because pools are not supported.
2608 -- H505-021 This needs to be revisited on .NET/JVM
2610 if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2612 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2614 if Is_Build_In_Place_Function (Func_Id)
2615 and then Needs_BIP_Collection (Func_Id)
2617 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2622 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2623 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
2625 -- Return objects use a flag to aid their potential
2626 -- finalization when the enclosing function fails to return
2627 -- properly. Generate:
2630 -- <object finalization statements>
2633 if Is_Return_Object (Obj_Id) then
2634 Fin_Stmts := New_List (
2635 Make_If_Statement (Loc,
2640 (Return_Flag_Or_Transient_Decl (Obj_Id), Loc)),
2642 Then_Statements => Fin_Stmts));
2644 -- Temporaries created for the purpose of "exporting" a
2645 -- controlled transient out of an Expression_With_Actions (EWA)
2646 -- need guards. The following illustrates the usage of such
2649 -- Access_Typ : access [all] Obj_Typ;
2650 -- Temp : Access_Typ := null;
2651 -- <Counter> := ...;
2654 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2655 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2657 -- Temp := Ctrl_Trans'Unchecked_Access;
2660 -- The finalization machinery does not process EWA nodes as
2661 -- this may lead to premature finalization of expressions. Note
2662 -- that Temp is marked as being properly initialized regardless
2663 -- of whether the initialization of Ctrl_Trans succeeded. Since
2664 -- a failed initialization may leave Temp with a value of null,
2665 -- add a guard to handle this case:
2667 -- if Obj /= null then
2668 -- <object finalization statements>
2673 (Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
2674 N_Object_Declaration);
2676 Fin_Stmts := New_List (
2677 Make_If_Statement (Loc,
2680 Left_Opnd => New_Reference_To (Obj_Id, Loc),
2681 Right_Opnd => Make_Null (Loc)),
2683 Then_Statements => Fin_Stmts));
2688 Append_List_To (Finalizer_Stmts, Fin_Stmts);
2690 -- Since the declarations are examined in reverse, the state counter
2691 -- must be decremented in order to keep with the true position of
2694 Counter_Val := Counter_Val - 1;
2695 end Process_Object_Declaration;
2697 -------------------------------------
2698 -- Process_Tagged_Type_Declaration --
2699 -------------------------------------
2701 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2702 Typ : constant Entity_Id := Defining_Identifier (Decl);
2703 DT_Ptr : constant Entity_Id :=
2704 Node (First_Elmt (Access_Disp_Table (Typ)));
2707 -- Ada.Tags.Unregister_Tag (<Typ>P);
2709 Append_To (Tagged_Type_Stmts,
2710 Make_Procedure_Call_Statement (Loc,
2712 New_Reference_To (RTE (RE_Unregister_Tag), Loc),
2713 Parameter_Associations => New_List (
2714 New_Reference_To (DT_Ptr, Loc))));
2715 end Process_Tagged_Type_Declaration;
2717 -- Start of processing for Build_Finalizer
2722 -- Step 1: Extract all lists which may contain controlled objects or
2723 -- library-level tagged types.
2725 if For_Package_Spec then
2726 Decls := Visible_Declarations (Specification (N));
2727 Priv_Decls := Private_Declarations (Specification (N));
2729 -- Retrieve the package spec id
2731 Spec_Id := Defining_Unit_Name (Specification (N));
2733 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2734 Spec_Id := Defining_Identifier (Spec_Id);
2737 -- Accept statement, block, entry body, package body, protected body,
2738 -- subprogram body or task body.
2741 Decls := Declarations (N);
2742 HSS := Handled_Statement_Sequence (N);
2744 if Present (HSS) then
2745 if Present (Statements (HSS)) then
2746 Stmts := Statements (HSS);
2749 if Present (At_End_Proc (HSS)) then
2750 Prev_At_End := At_End_Proc (HSS);
2754 -- Retrieve the package spec id for package bodies
2756 if For_Package_Body then
2757 Spec_Id := Corresponding_Spec (N);
2761 -- Do not process nested packages since those are handled by the
2762 -- enclosing scope's finalizer. Do not process non-expanded package
2763 -- instantiations since those will be re-analyzed and re-expanded.
2767 (not Is_Library_Level_Entity (Spec_Id)
2769 -- Nested packages are considered to be library level entities,
2770 -- but do not need to be processed separately. True library level
2771 -- packages have a scope value of 1.
2773 or else Scope_Depth_Value (Spec_Id) /= Uint_1
2774 or else (Is_Generic_Instance (Spec_Id)
2775 and then Package_Instantiation (Spec_Id) /= N))
2780 -- Step 2: Object [pre]processing
2784 -- Preprocess the visible declarations now in order to obtain the
2785 -- correct number of controlled object by the time the private
2786 -- declarations are processed.
2788 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2790 -- From all the possible contexts, only package specifications may
2791 -- have private declarations.
2793 if For_Package_Spec then
2794 Process_Declarations
2795 (Priv_Decls, Preprocess => True, Top_Level => True);
2798 -- The current context may lack controlled objects, but require some
2799 -- other form of completion (task termination for instance). In such
2800 -- cases, the finalizer must be created and carry the additional
2803 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2807 -- The preprocessing has determined that the context has controlled
2808 -- objects or library-level tagged types.
2810 if Has_Ctrl_Objs or Has_Tagged_Types then
2812 -- Private declarations are processed first in order to preserve
2813 -- possible dependencies between public and private objects.
2815 if For_Package_Spec then
2816 Process_Declarations (Priv_Decls);
2819 Process_Declarations (Decls);
2825 -- Preprocess both declarations and statements
2827 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2828 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
2830 -- At this point it is known that N has controlled objects. Ensure
2831 -- that N has a declarative list since the finalizer spec will be
2834 if Has_Ctrl_Objs and then No (Decls) then
2835 Set_Declarations (N, New_List);
2836 Decls := Declarations (N);
2837 Spec_Decls := Decls;
2840 -- The current context may lack controlled objects, but require some
2841 -- other form of completion (task termination for instance). In such
2842 -- cases, the finalizer must be created and carry the additional
2845 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2849 if Has_Ctrl_Objs or Has_Tagged_Types then
2850 Process_Declarations (Stmts);
2851 Process_Declarations (Decls);
2855 -- Step 3: Finalizer creation
2857 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2860 end Build_Finalizer;
2862 --------------------------
2863 -- Build_Finalizer_Call --
2864 --------------------------
2866 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
2867 Loc : constant Source_Ptr := Sloc (N);
2868 HSS : Node_Id := Handled_Statement_Sequence (N);
2870 Is_Prot_Body : constant Boolean :=
2871 Nkind (N) = N_Subprogram_Body
2872 and then Is_Protected_Subprogram_Body (N);
2873 -- Determine whether N denotes the protected version of a subprogram
2874 -- which belongs to a protected type.
2877 -- The At_End handler should have been assimilated by the finalizer
2879 pragma Assert (No (At_End_Proc (HSS)));
2881 -- If the construct to be cleaned up is a protected subprogram body, the
2882 -- finalizer call needs to be associated with the block which wraps the
2883 -- unprotected version of the subprogram. The following illustrates this
2886 -- procedure Prot_SubpP is
2887 -- procedure finalizer is
2889 -- Service_Entries (Prot_Obj);
2896 -- Prot_SubpN (Prot_Obj);
2902 if Is_Prot_Body then
2903 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
2905 -- An At_End handler and regular exception handlers cannot coexist in
2906 -- the same statement sequence. Wrap the original statements in a block.
2908 elsif Present (Exception_Handlers (HSS)) then
2910 End_Lab : constant Node_Id := End_Label (HSS);
2915 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
2917 Set_Handled_Statement_Sequence (N,
2918 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
2920 HSS := Handled_Statement_Sequence (N);
2921 Set_End_Label (HSS, End_Lab);
2925 Set_At_End_Proc (HSS, New_Reference_To (Fin_Id, Loc));
2927 Analyze (At_End_Proc (HSS));
2928 Expand_At_End_Handler (HSS, Empty);
2929 end Build_Finalizer_Call;
2931 ---------------------
2932 -- Build_Late_Proc --
2933 ---------------------
2935 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
2937 for Final_Prim in Name_Of'Range loop
2938 if Name_Of (Final_Prim) = Nam then
2941 (Prim => Final_Prim,
2943 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
2946 end Build_Late_Proc;
2948 -------------------------------
2949 -- Build_Object_Declarations --
2950 -------------------------------
2952 function Build_Object_Declarations
2954 Abort_Id : Entity_Id;
2956 Raised_Id : Entity_Id;
2957 For_Package : Boolean := False) return List_Id
2964 if Restriction_Active (No_Exception_Propagation) then
2968 pragma Assert (Present (Abort_Id));
2969 pragma Assert (Present (E_Id));
2970 pragma Assert (Present (Raised_Id));
2974 -- In certain scenarios, finalization can be triggered by an abort. If
2975 -- the finalization itself fails and raises an exception, the resulting
2976 -- Program_Error must be supressed and replaced by an abort signal. In
2977 -- order to detect this scenario, save the state of entry into the
2978 -- finalization code.
2980 -- No need to do this for VM case, since VM version of Ada.Exceptions
2981 -- does not include routine Raise_From_Controlled_Operation which is the
2982 -- the sole user of flag Abort.
2984 -- This is not needed for library-level finalizers as they are called
2985 -- by the environment task and cannot be aborted.
2988 and then VM_Target = No_VM
2989 and then not For_Package
2992 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'E');
2996 -- Temp : constant Exception_Occurrence_Access :=
2997 -- Get_Current_Excep.all;
3000 Make_Object_Declaration (Loc,
3001 Defining_Identifier => Temp_Id,
3002 Constant_Present => True,
3003 Object_Definition =>
3004 New_Reference_To (RTE (RE_Exception_Occurrence_Access), Loc),
3006 Make_Function_Call (Loc,
3008 Make_Explicit_Dereference (Loc,
3011 (RTE (RE_Get_Current_Excep), Loc)))));
3015 -- and then Exception_Identity (Temp.all) =
3016 -- Standard'Abort_Signal'Identity;
3022 Left_Opnd => New_Reference_To (Temp_Id, Loc),
3023 Right_Opnd => Make_Null (Loc)),
3028 Make_Function_Call (Loc,
3030 New_Reference_To (RTE (RE_Exception_Identity), Loc),
3031 Parameter_Associations => New_List (
3032 Make_Explicit_Dereference (Loc,
3033 Prefix => New_Reference_To (Temp_Id, Loc)))),
3036 Make_Attribute_Reference (Loc,
3038 New_Reference_To (Stand.Abort_Signal, Loc),
3039 Attribute_Name => Name_Identity)));
3042 -- No abort or .NET/JVM
3045 A_Expr := New_Reference_To (Standard_False, Loc);
3049 -- Abort_Id : constant Boolean := <A_Expr>;
3052 Make_Object_Declaration (Loc,
3053 Defining_Identifier => Abort_Id,
3054 Constant_Present => True,
3055 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3056 Expression => A_Expr));
3059 -- E_Id : Exception_Occurrence;
3062 Make_Object_Declaration (Loc,
3063 Defining_Identifier => E_Id,
3064 Object_Definition =>
3065 New_Reference_To (RTE (RE_Exception_Occurrence), Loc));
3066 Set_No_Initialization (E_Decl);
3068 Append_To (Result, E_Decl);
3071 -- Raised_Id : Boolean := False;
3074 Make_Object_Declaration (Loc,
3075 Defining_Identifier => Raised_Id,
3076 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3077 Expression => New_Reference_To (Standard_False, Loc)));
3080 end Build_Object_Declarations;
3082 ---------------------------
3083 -- Build_Raise_Statement --
3084 ---------------------------
3086 function Build_Raise_Statement
3088 Abort_Id : Entity_Id;
3090 Raised_Id : Entity_Id) return Node_Id
3093 Proc_Id : Entity_Id;
3096 -- The default parameter is the local exception occurrence
3098 Params := New_List (New_Reference_To (E_Id, Loc));
3100 -- Standard run-time, .NET/JVM targets, this case handles finalization
3101 -- exceptions raised during an abort.
3103 if RTE_Available (RE_Raise_From_Controlled_Operation) then
3104 Proc_Id := RTE (RE_Raise_From_Controlled_Operation);
3105 Append_To (Params, New_Reference_To (Abort_Id, Loc));
3107 -- Restricted runtime: exception messages are not supported and hence
3108 -- Raise_From_Controlled_Operation is not supported.
3111 Proc_Id := RTE (RE_Reraise_Occurrence);
3115 -- if Raised_Id then
3116 -- <Proc_Id> (<Params>);
3120 Make_If_Statement (Loc,
3121 Condition => New_Reference_To (Raised_Id, Loc),
3122 Then_Statements => New_List (
3123 Make_Procedure_Call_Statement (Loc,
3124 Name => New_Reference_To (Proc_Id, Loc),
3125 Parameter_Associations => Params)));
3126 end Build_Raise_Statement;
3128 -----------------------------
3129 -- Build_Record_Deep_Procs --
3130 -----------------------------
3132 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3136 (Prim => Initialize_Case,
3138 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3140 if not Is_Immutably_Limited_Type (Typ) then
3143 (Prim => Adjust_Case,
3145 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3150 (Prim => Finalize_Case,
3152 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3154 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3155 -- .NET do not support address arithmetic and unchecked conversions.
3157 if VM_Target = No_VM then
3160 (Prim => Address_Case,
3162 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3164 end Build_Record_Deep_Procs;
3170 function Cleanup_Array
3173 Typ : Entity_Id) return List_Id
3175 Loc : constant Source_Ptr := Sloc (N);
3176 Index_List : constant List_Id := New_List;
3178 function Free_Component return List_Id;
3179 -- Generate the code to finalize the task or protected subcomponents
3180 -- of a single component of the array.
3182 function Free_One_Dimension (Dim : Int) return List_Id;
3183 -- Generate a loop over one dimension of the array
3185 --------------------
3186 -- Free_Component --
3187 --------------------
3189 function Free_Component return List_Id is
3190 Stmts : List_Id := New_List;
3192 C_Typ : constant Entity_Id := Component_Type (Typ);
3195 -- Component type is known to contain tasks or protected objects
3198 Make_Indexed_Component (Loc,
3199 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3200 Expressions => Index_List);
3202 Set_Etype (Tsk, C_Typ);
3204 if Is_Task_Type (C_Typ) then
3205 Append_To (Stmts, Cleanup_Task (N, Tsk));
3207 elsif Is_Simple_Protected_Type (C_Typ) then
3208 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3210 elsif Is_Record_Type (C_Typ) then
3211 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3213 elsif Is_Array_Type (C_Typ) then
3214 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3220 ------------------------
3221 -- Free_One_Dimension --
3222 ------------------------
3224 function Free_One_Dimension (Dim : Int) return List_Id is
3228 if Dim > Number_Dimensions (Typ) then
3229 return Free_Component;
3231 -- Here we generate the required loop
3234 Index := Make_Temporary (Loc, 'J');
3235 Append (New_Reference_To (Index, Loc), Index_List);
3238 Make_Implicit_Loop_Statement (N,
3239 Identifier => Empty,
3241 Make_Iteration_Scheme (Loc,
3242 Loop_Parameter_Specification =>
3243 Make_Loop_Parameter_Specification (Loc,
3244 Defining_Identifier => Index,
3245 Discrete_Subtype_Definition =>
3246 Make_Attribute_Reference (Loc,
3247 Prefix => Duplicate_Subexpr (Obj),
3248 Attribute_Name => Name_Range,
3249 Expressions => New_List (
3250 Make_Integer_Literal (Loc, Dim))))),
3251 Statements => Free_One_Dimension (Dim + 1)));
3253 end Free_One_Dimension;
3255 -- Start of processing for Cleanup_Array
3258 return Free_One_Dimension (1);
3261 --------------------
3262 -- Cleanup_Record --
3263 --------------------
3265 function Cleanup_Record
3268 Typ : Entity_Id) return List_Id
3270 Loc : constant Source_Ptr := Sloc (N);
3273 Stmts : constant List_Id := New_List;
3274 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3277 if Has_Discriminants (U_Typ)
3278 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3280 Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3283 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3285 -- For now, do not attempt to free a component that may appear in a
3286 -- variant, and instead issue a warning. Doing this "properly" would
3287 -- require building a case statement and would be quite a mess. Note
3288 -- that the RM only requires that free "work" for the case of a task
3289 -- access value, so already we go way beyond this in that we deal
3290 -- with the array case and non-discriminated record cases.
3293 ("task/protected object in variant record will not be freed?", N);
3294 return New_List (Make_Null_Statement (Loc));
3297 Comp := First_Component (Typ);
3298 while Present (Comp) loop
3299 if Has_Task (Etype (Comp))
3300 or else Has_Simple_Protected_Object (Etype (Comp))
3303 Make_Selected_Component (Loc,
3304 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3305 Selector_Name => New_Occurrence_Of (Comp, Loc));
3306 Set_Etype (Tsk, Etype (Comp));
3308 if Is_Task_Type (Etype (Comp)) then
3309 Append_To (Stmts, Cleanup_Task (N, Tsk));
3311 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3312 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3314 elsif Is_Record_Type (Etype (Comp)) then
3316 -- Recurse, by generating the prefix of the argument to
3317 -- the eventual cleanup call.
3319 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3321 elsif Is_Array_Type (Etype (Comp)) then
3322 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3326 Next_Component (Comp);
3332 ------------------------------
3333 -- Cleanup_Protected_Object --
3334 ------------------------------
3336 function Cleanup_Protected_Object
3338 Ref : Node_Id) return Node_Id
3340 Loc : constant Source_Ptr := Sloc (N);
3343 -- For restricted run-time libraries (Ravenscar), tasks are
3344 -- non-terminating, and protected objects can only appear at library
3345 -- level, so we do not want finalization of protected objects.
3347 if Restricted_Profile then
3352 Make_Procedure_Call_Statement (Loc,
3354 New_Reference_To (RTE (RE_Finalize_Protection), Loc),
3355 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3357 end Cleanup_Protected_Object;
3363 function Cleanup_Task
3365 Ref : Node_Id) return Node_Id
3367 Loc : constant Source_Ptr := Sloc (N);
3370 -- For restricted run-time libraries (Ravenscar), tasks are
3371 -- non-terminating and they can only appear at library level, so we do
3372 -- not want finalization of task objects.
3374 if Restricted_Profile then
3379 Make_Procedure_Call_Statement (Loc,
3381 New_Reference_To (RTE (RE_Free_Task), Loc),
3382 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3386 ------------------------------
3387 -- Check_Visibly_Controlled --
3388 ------------------------------
3390 procedure Check_Visibly_Controlled
3391 (Prim : Final_Primitives;
3393 E : in out Entity_Id;
3394 Cref : in out Node_Id)
3396 Parent_Type : Entity_Id;
3400 if Is_Derived_Type (Typ)
3401 and then Comes_From_Source (E)
3402 and then not Present (Overridden_Operation (E))
3404 -- We know that the explicit operation on the type does not override
3405 -- the inherited operation of the parent, and that the derivation
3406 -- is from a private type that is not visibly controlled.
3408 Parent_Type := Etype (Typ);
3409 Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3411 if Present (Op) then
3414 -- Wrap the object to be initialized into the proper
3415 -- unchecked conversion, to be compatible with the operation
3418 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3419 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3421 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3425 end Check_Visibly_Controlled;
3427 -------------------------------
3428 -- CW_Or_Has_Controlled_Part --
3429 -------------------------------
3431 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3433 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3434 end CW_Or_Has_Controlled_Part;
3440 function Convert_View
3443 Ind : Pos := 1) return Node_Id
3445 Fent : Entity_Id := First_Entity (Proc);
3450 for J in 2 .. Ind loop
3454 Ftyp := Etype (Fent);
3456 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3457 Atyp := Entity (Subtype_Mark (Arg));
3459 Atyp := Etype (Arg);
3462 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3463 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3466 and then Present (Atyp)
3467 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3468 and then Base_Type (Underlying_Type (Atyp)) =
3469 Base_Type (Underlying_Type (Ftyp))
3471 return Unchecked_Convert_To (Ftyp, Arg);
3473 -- If the argument is already a conversion, as generated by
3474 -- Make_Init_Call, set the target type to the type of the formal
3475 -- directly, to avoid spurious typing problems.
3477 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3478 and then not Is_Class_Wide_Type (Atyp)
3480 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3481 Set_Etype (Arg, Ftyp);
3489 ------------------------
3490 -- Enclosing_Function --
3491 ------------------------
3493 function Enclosing_Function (E : Entity_Id) return Entity_Id is
3494 Func_Id : Entity_Id;
3498 while Present (Func_Id)
3499 and then Func_Id /= Standard_Standard
3501 if Ekind (Func_Id) = E_Function then
3505 Func_Id := Scope (Func_Id);
3509 end Enclosing_Function;
3511 -------------------------------
3512 -- Establish_Transient_Scope --
3513 -------------------------------
3515 -- This procedure is called each time a transient block has to be inserted
3516 -- that is to say for each call to a function with unconstrained or tagged
3517 -- result. It creates a new scope on the stack scope in order to enclose
3518 -- all transient variables generated
3520 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3521 Loc : constant Source_Ptr := Sloc (N);
3522 Wrap_Node : Node_Id;
3525 -- Do not create a transient scope if we are already inside one
3527 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3528 if Scope_Stack.Table (S).Is_Transient then
3530 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3535 -- If we have encountered Standard there are no enclosing
3536 -- transient scopes.
3538 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3543 Wrap_Node := Find_Node_To_Be_Wrapped (N);
3545 -- Case of no wrap node, false alert, no transient scope needed
3547 if No (Wrap_Node) then
3550 -- If the node to wrap is an iteration_scheme, the expression is
3551 -- one of the bounds, and the expansion will make an explicit
3552 -- declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3553 -- so do not apply any transformations here.
3555 elsif Nkind (Wrap_Node) = N_Iteration_Scheme then
3558 -- In formal verification mode, if the node to wrap is a pragma check,
3559 -- this node and enclosed expression are not expanded, so do not apply
3560 -- any transformations here.
3563 and then Nkind (Wrap_Node) = N_Pragma
3564 and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
3569 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3570 Set_Scope_Is_Transient;
3573 Set_Uses_Sec_Stack (Current_Scope);
3574 Check_Restriction (No_Secondary_Stack, N);
3577 Set_Etype (Current_Scope, Standard_Void_Type);
3578 Set_Node_To_Be_Wrapped (Wrap_Node);
3580 if Debug_Flag_W then
3581 Write_Str (" <Transient>");
3585 end Establish_Transient_Scope;
3587 ----------------------------
3588 -- Expand_Cleanup_Actions --
3589 ----------------------------
3591 procedure Expand_Cleanup_Actions (N : Node_Id) is
3592 Scop : constant Entity_Id := Current_Scope;
3594 Is_Asynchronous_Call : constant Boolean :=
3595 Nkind (N) = N_Block_Statement
3596 and then Is_Asynchronous_Call_Block (N);
3597 Is_Master : constant Boolean :=
3598 Nkind (N) /= N_Entry_Body
3599 and then Is_Task_Master (N);
3600 Is_Protected_Body : constant Boolean :=
3601 Nkind (N) = N_Subprogram_Body
3602 and then Is_Protected_Subprogram_Body (N);
3603 Is_Task_Allocation : constant Boolean :=
3604 Nkind (N) = N_Block_Statement
3605 and then Is_Task_Allocation_Block (N);
3606 Is_Task_Body : constant Boolean :=
3607 Nkind (Original_Node (N)) = N_Task_Body;
3608 Needs_Sec_Stack_Mark : constant Boolean :=
3609 Uses_Sec_Stack (Scop)
3611 not Sec_Stack_Needed_For_Return (Scop)
3612 and then VM_Target = No_VM;
3614 Actions_Required : constant Boolean :=
3615 Requires_Cleanup_Actions (N)
3616 or else Is_Asynchronous_Call
3618 or else Is_Protected_Body
3619 or else Is_Task_Allocation
3620 or else Is_Task_Body
3621 or else Needs_Sec_Stack_Mark;
3623 HSS : Node_Id := Handled_Statement_Sequence (N);
3626 procedure Wrap_HSS_In_Block;
3627 -- Move HSS inside a new block along with the original exception
3628 -- handlers. Make the newly generated block the sole statement of HSS.
3630 -----------------------
3631 -- Wrap_HSS_In_Block --
3632 -----------------------
3634 procedure Wrap_HSS_In_Block is
3639 -- Preserve end label to provide proper cross-reference information
3641 End_Lab := End_Label (HSS);
3643 Make_Block_Statement (Loc,
3644 Handled_Statement_Sequence => HSS);
3646 Set_Handled_Statement_Sequence (N,
3647 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3648 HSS := Handled_Statement_Sequence (N);
3650 Set_First_Real_Statement (HSS, Block);
3651 Set_End_Label (HSS, End_Lab);
3653 -- Comment needed here, see RH for 1.306 ???
3655 if Nkind (N) = N_Subprogram_Body then
3656 Set_Has_Nested_Block_With_Handler (Scop);
3658 end Wrap_HSS_In_Block;
3660 -- Start of processing for Expand_Cleanup_Actions
3663 -- The current construct does not need any form of servicing
3665 if not Actions_Required then
3668 -- If the current node is a rewritten task body and the descriptors have
3669 -- not been delayed (due to some nested instantiations), do not generate
3670 -- redundant cleanup actions.
3673 and then Nkind (N) = N_Subprogram_Body
3674 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3680 Decls : List_Id := Declarations (N);
3682 Mark : Entity_Id := Empty;
3683 New_Decls : List_Id;
3687 -- If we are generating expanded code for debugging purposes, use the
3688 -- Sloc of the point of insertion for the cleanup code. The Sloc will
3689 -- be updated subsequently to reference the proper line in .dg files.
3690 -- If we are not debugging generated code, use No_Location instead,
3691 -- so that no debug information is generated for the cleanup code.
3692 -- This makes the behavior of the NEXT command in GDB monotonic, and
3693 -- makes the placement of breakpoints more accurate.
3695 if Debug_Generated_Code then
3701 -- Set polling off. The finalization and cleanup code is executed
3702 -- with aborts deferred.
3704 Old_Poll := Polling_Required;
3705 Polling_Required := False;
3707 -- A task activation call has already been built for a task
3708 -- allocation block.
3710 if not Is_Task_Allocation then
3711 Build_Task_Activation_Call (N);
3715 Establish_Task_Master (N);
3718 New_Decls := New_List;
3720 -- If secondary stack is in use, generate:
3722 -- Mnn : constant Mark_Id := SS_Mark;
3724 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3725 -- secondary stack is never used on a VM.
3727 if Needs_Sec_Stack_Mark then
3728 Mark := Make_Temporary (Loc, 'M');
3730 Append_To (New_Decls,
3731 Make_Object_Declaration (Loc,
3732 Defining_Identifier => Mark,
3733 Object_Definition =>
3734 New_Reference_To (RTE (RE_Mark_Id), Loc),
3736 Make_Function_Call (Loc,
3737 Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
3739 Set_Uses_Sec_Stack (Scop, False);
3742 -- If exception handlers are present, wrap the sequence of statements
3743 -- in a block since it is not possible to have exception handlers and
3744 -- an At_End handler in the same construct.
3746 if Present (Exception_Handlers (HSS)) then
3749 -- Ensure that the First_Real_Statement field is set
3751 elsif No (First_Real_Statement (HSS)) then
3752 Set_First_Real_Statement (HSS, First (Statements (HSS)));
3755 -- Do not move the Activation_Chain declaration in the context of
3756 -- task allocation blocks. Task allocation blocks use _chain in their
3757 -- cleanup handlers and gigi complains if it is declared in the
3758 -- sequence of statements of the scope that declares the handler.
3760 if Is_Task_Allocation then
3762 Chain : constant Entity_Id := Activation_Chain_Entity (N);
3766 Decl := First (Decls);
3767 while Nkind (Decl) /= N_Object_Declaration
3768 or else Defining_Identifier (Decl) /= Chain
3772 -- A task allocation block should always include a _chain
3775 pragma Assert (Present (Decl));
3779 Prepend_To (New_Decls, Decl);
3783 -- Ensure the presence of a declaration list in order to successfully
3784 -- append all original statements to it.
3787 Set_Declarations (N, New_List);
3788 Decls := Declarations (N);
3791 -- Move the declarations into the sequence of statements in order to
3792 -- have them protected by the At_End handler. It may seem weird to
3793 -- put declarations in the sequence of statement but in fact nothing
3794 -- forbids that at the tree level.
3796 Append_List_To (Decls, Statements (HSS));
3797 Set_Statements (HSS, Decls);
3799 -- Reset the Sloc of the handled statement sequence to properly
3800 -- reflect the new initial "statement" in the sequence.
3802 Set_Sloc (HSS, Sloc (First (Decls)));
3804 -- The declarations of finalizer spec and auxiliary variables replace
3805 -- the old declarations that have been moved inward.
3807 Set_Declarations (N, New_Decls);
3808 Analyze_Declarations (New_Decls);
3810 -- Generate finalization calls for all controlled objects appearing
3811 -- in the statements of N. Add context specific cleanup for various
3816 Clean_Stmts => Build_Cleanup_Statements (N),
3818 Top_Decls => New_Decls,
3819 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
3823 if Present (Fin_Id) then
3824 Build_Finalizer_Call (N, Fin_Id);
3827 -- Restore saved polling mode
3829 Polling_Required := Old_Poll;
3831 end Expand_Cleanup_Actions;
3833 ---------------------------
3834 -- Expand_N_Package_Body --
3835 ---------------------------
3837 -- Add call to Activate_Tasks if body is an activator (actual processing
3838 -- is in chapter 9).
3840 -- Generate subprogram descriptor for elaboration routine
3842 -- Encode entity names in package body
3844 procedure Expand_N_Package_Body (N : Node_Id) is
3845 Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
3849 -- This is done only for non-generic packages
3851 if Ekind (Spec_Ent) = E_Package then
3852 Push_Scope (Corresponding_Spec (N));
3854 -- Build dispatch tables of library level tagged types
3856 if Tagged_Type_Expansion
3857 and then Is_Library_Level_Entity (Spec_Ent)
3859 Build_Static_Dispatch_Tables (N);
3862 Build_Task_Activation_Call (N);
3866 Set_Elaboration_Flag (N, Corresponding_Spec (N));
3867 Set_In_Package_Body (Spec_Ent, False);
3869 -- Set to encode entity names in package body before gigi is called
3871 Qualify_Entity_Names (N);
3873 if Ekind (Spec_Ent) /= E_Generic_Package then
3876 Clean_Stmts => No_List,
3878 Top_Decls => No_List,
3879 Defer_Abort => False,
3882 if Present (Fin_Id) then
3884 Body_Ent : Node_Id := Defining_Unit_Name (N);
3887 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
3888 Body_Ent := Defining_Identifier (Body_Ent);
3891 Set_Finalizer (Body_Ent, Fin_Id);
3895 end Expand_N_Package_Body;
3897 ----------------------------------
3898 -- Expand_N_Package_Declaration --
3899 ----------------------------------
3901 -- Add call to Activate_Tasks if there are tasks declared and the package
3902 -- has no body. Note that in Ada83, this may result in premature activation
3903 -- of some tasks, given that we cannot tell whether a body will eventually
3906 procedure Expand_N_Package_Declaration (N : Node_Id) is
3907 Id : constant Entity_Id := Defining_Entity (N);
3908 Spec : constant Node_Id := Specification (N);
3912 No_Body : Boolean := False;
3913 -- True in the case of a package declaration that is a compilation
3914 -- unit and for which no associated body will be compiled in this
3918 -- Case of a package declaration other than a compilation unit
3920 if Nkind (Parent (N)) /= N_Compilation_Unit then
3923 -- Case of a compilation unit that does not require a body
3925 elsif not Body_Required (Parent (N))
3926 and then not Unit_Requires_Body (Id)
3930 -- Special case of generating calling stubs for a remote call interface
3931 -- package: even though the package declaration requires one, the body
3932 -- won't be processed in this compilation (so any stubs for RACWs
3933 -- declared in the package must be generated here, along with the spec).
3935 elsif Parent (N) = Cunit (Main_Unit)
3936 and then Is_Remote_Call_Interface (Id)
3937 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
3942 -- For a package declaration that implies no associated body, generate
3943 -- task activation call and RACW supporting bodies now (since we won't
3944 -- have a specific separate compilation unit for that).
3949 if Has_RACW (Id) then
3951 -- Generate RACW subprogram bodies
3953 Decls := Private_Declarations (Spec);
3956 Decls := Visible_Declarations (Spec);
3961 Set_Visible_Declarations (Spec, Decls);
3964 Append_RACW_Bodies (Decls, Id);
3965 Analyze_List (Decls);
3968 if Present (Activation_Chain_Entity (N)) then
3970 -- Generate task activation call as last step of elaboration
3972 Build_Task_Activation_Call (N);
3978 -- Build dispatch tables of library level tagged types
3980 if Tagged_Type_Expansion
3981 and then (Is_Compilation_Unit (Id)
3982 or else (Is_Generic_Instance (Id)
3983 and then Is_Library_Level_Entity (Id)))
3985 Build_Static_Dispatch_Tables (N);
3988 -- Note: it is not necessary to worry about generating a subprogram
3989 -- descriptor, since the only way to get exception handlers into a
3990 -- package spec is to include instantiations, and that would cause
3991 -- generation of subprogram descriptors to be delayed in any case.
3993 -- Set to encode entity names in package spec before gigi is called
3995 Qualify_Entity_Names (N);
3997 if Ekind (Id) /= E_Generic_Package then
4000 Clean_Stmts => No_List,
4002 Top_Decls => No_List,
4003 Defer_Abort => False,
4006 Set_Finalizer (Id, Fin_Id);
4008 end Expand_N_Package_Declaration;
4010 -----------------------------
4011 -- Find_Node_To_Be_Wrapped --
4012 -----------------------------
4014 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
4016 The_Parent : Node_Id;
4022 pragma Assert (P /= Empty);
4023 The_Parent := Parent (P);
4025 case Nkind (The_Parent) is
4027 -- Simple statement can be wrapped
4032 -- Usually assignments are good candidate for wrapping
4033 -- except when they have been generated as part of a
4034 -- controlled aggregate where the wrapping should take
4035 -- place more globally.
4037 when N_Assignment_Statement =>
4038 if No_Ctrl_Actions (The_Parent) then
4044 -- An entry call statement is a special case if it occurs in
4045 -- the context of a Timed_Entry_Call. In this case we wrap
4046 -- the entire timed entry call.
4048 when N_Entry_Call_Statement |
4049 N_Procedure_Call_Statement =>
4050 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
4051 and then Nkind_In (Parent (Parent (The_Parent)),
4053 N_Conditional_Entry_Call)
4055 return Parent (Parent (The_Parent));
4060 -- Object declarations are also a boundary for the transient scope
4061 -- even if they are not really wrapped
4062 -- (see Wrap_Transient_Declaration)
4064 when N_Object_Declaration |
4065 N_Object_Renaming_Declaration |
4066 N_Subtype_Declaration =>
4069 -- The expression itself is to be wrapped if its parent is a
4070 -- compound statement or any other statement where the expression
4071 -- is known to be scalar
4073 when N_Accept_Alternative |
4074 N_Attribute_Definition_Clause |
4077 N_Delay_Alternative |
4078 N_Delay_Until_Statement |
4079 N_Delay_Relative_Statement |
4080 N_Discriminant_Association |
4082 N_Entry_Body_Formal_Part |
4085 N_Iteration_Scheme |
4086 N_Terminate_Alternative =>
4089 when N_Attribute_Reference =>
4091 if Is_Procedure_Attribute_Name
4092 (Attribute_Name (The_Parent))
4097 -- A raise statement can be wrapped. This will arise when the
4098 -- expression in a raise_with_expression uses the secondary
4099 -- stack, for example.
4101 when N_Raise_Statement =>
4104 -- If the expression is within the iteration scheme of a loop,
4105 -- we must create a declaration for it, followed by an assignment
4106 -- in order to have a usable statement to wrap.
4108 when N_Loop_Parameter_Specification =>
4109 return Parent (The_Parent);
4111 -- The following nodes contains "dummy calls" which don't
4112 -- need to be wrapped.
4114 when N_Parameter_Specification |
4115 N_Discriminant_Specification |
4116 N_Component_Declaration =>
4119 -- The return statement is not to be wrapped when the function
4120 -- itself needs wrapping at the outer-level
4122 when N_Simple_Return_Statement =>
4124 Applies_To : constant Entity_Id :=
4126 (Return_Statement_Entity (The_Parent));
4127 Return_Type : constant Entity_Id := Etype (Applies_To);
4129 if Requires_Transient_Scope (Return_Type) then
4136 -- If we leave a scope without having been able to find a node to
4137 -- wrap, something is going wrong but this can happen in error
4138 -- situation that are not detected yet (such as a dynamic string
4139 -- in a pragma export)
4141 when N_Subprogram_Body |
4142 N_Package_Declaration |
4144 N_Block_Statement =>
4147 -- otherwise continue the search
4153 end Find_Node_To_Be_Wrapped;
4155 -------------------------------------
4156 -- Get_Global_Pool_For_Access_Type --
4157 -------------------------------------
4159 function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id is
4161 -- Access types whose size is smaller than System.Address size can
4162 -- exist only on VMS. We can't use the usual global pool which returns
4163 -- an object of type Address as truncation will make it invalid.
4164 -- To handle this case, VMS has a dedicated global pool that returns
4165 -- addresses that fit into 32 bit accesses.
4167 if Opt.True_VMS_Target and then Esize (T) = 32 then
4168 return RTE (RE_Global_Pool_32_Object);
4170 return RTE (RE_Global_Pool_Object);
4172 end Get_Global_Pool_For_Access_Type;
4174 ----------------------------------
4175 -- Has_New_Controlled_Component --
4176 ----------------------------------
4178 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4182 if not Is_Tagged_Type (E) then
4183 return Has_Controlled_Component (E);
4184 elsif not Is_Derived_Type (E) then
4185 return Has_Controlled_Component (E);
4188 Comp := First_Component (E);
4189 while Present (Comp) loop
4190 if Chars (Comp) = Name_uParent then
4193 elsif Scope (Original_Record_Component (Comp)) = E
4194 and then Needs_Finalization (Etype (Comp))
4199 Next_Component (Comp);
4203 end Has_New_Controlled_Component;
4205 ---------------------------------
4206 -- Has_Simple_Protected_Object --
4207 ---------------------------------
4209 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4211 if Has_Task (T) then
4214 elsif Is_Simple_Protected_Type (T) then
4217 elsif Is_Array_Type (T) then
4218 return Has_Simple_Protected_Object (Component_Type (T));
4220 elsif Is_Record_Type (T) then
4225 Comp := First_Component (T);
4226 while Present (Comp) loop
4227 if Has_Simple_Protected_Object (Etype (Comp)) then
4231 Next_Component (Comp);
4240 end Has_Simple_Protected_Object;
4242 ------------------------------------
4243 -- Insert_Actions_In_Scope_Around --
4244 ------------------------------------
4246 procedure Insert_Actions_In_Scope_Around (N : Node_Id) is
4247 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
4248 After : List_Id renames SE.Actions_To_Be_Wrapped_After;
4249 Before : List_Id renames SE.Actions_To_Be_Wrapped_Before;
4251 procedure Process_Transient_Objects
4252 (First_Object : Node_Id;
4253 Last_Object : Node_Id;
4254 Related_Node : Node_Id);
4255 -- First_Object and Last_Object define a list which contains potential
4256 -- controlled transient objects. Finalization flags are inserted before
4257 -- First_Object and finalization calls are inserted after Last_Object.
4258 -- Related_Node is the node for which transient objects have been
4261 -------------------------------
4262 -- Process_Transient_Objects --
4263 -------------------------------
4265 procedure Process_Transient_Objects
4266 (First_Object : Node_Id;
4267 Last_Object : Node_Id;
4268 Related_Node : Node_Id)
4270 Abort_Id : Entity_Id;
4271 Built : Boolean := False;
4274 Fin_Block : Node_Id;
4275 Last_Fin : Node_Id := Empty;
4279 Obj_Typ : Entity_Id;
4280 Raised_Id : Entity_Id;
4284 -- Examine all objects in the list First_Object .. Last_Object
4286 Stmt := First_Object;
4287 while Present (Stmt) loop
4288 if Nkind (Stmt) = N_Object_Declaration
4289 and then Analyzed (Stmt)
4290 and then Is_Finalizable_Transient (Stmt, N)
4292 -- Do not process the node to be wrapped since it will be
4293 -- handled by the enclosing finalizer.
4295 and then Stmt /= Related_Node
4298 Obj_Id := Defining_Identifier (Stmt);
4299 Obj_Typ := Base_Type (Etype (Obj_Id));
4302 Set_Is_Processed_Transient (Obj_Id);
4304 -- Handle access types
4306 if Is_Access_Type (Desig) then
4307 Desig := Available_View (Designated_Type (Desig));
4310 -- Create the necessary entities and declarations the first
4314 Abort_Id := Make_Temporary (Loc, 'A');
4315 E_Id := Make_Temporary (Loc, 'E');
4316 Raised_Id := Make_Temporary (Loc, 'R');
4318 Insert_List_Before_And_Analyze (First_Object,
4319 Build_Object_Declarations
4320 (Loc, Abort_Id, E_Id, Raised_Id));
4327 -- [Deep_]Finalize (Obj_Ref);
4334 -- (Enn, Get_Current_Excep.all.all);
4338 Obj_Ref := New_Reference_To (Obj_Id, Loc);
4340 if Is_Access_Type (Obj_Typ) then
4341 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4345 Make_Block_Statement (Loc,
4346 Handled_Statement_Sequence =>
4347 Make_Handled_Sequence_Of_Statements (Loc,
4348 Statements => New_List (
4350 (Obj_Ref => Obj_Ref,
4353 Exception_Handlers => New_List (
4354 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4355 Insert_After_And_Analyze (Last_Object, Fin_Block);
4357 -- The raise statement must be inserted after all the
4358 -- finalization blocks.
4360 if No (Last_Fin) then
4361 Last_Fin := Fin_Block;
4364 -- When the associated node is an array object, the expander may
4365 -- sometimes generate a loop and create transient objects inside
4368 elsif Nkind (Related_Node) = N_Object_Declaration
4369 and then Is_Array_Type (Base_Type
4370 (Etype (Defining_Identifier (Related_Node))))
4371 and then Nkind (Stmt) = N_Loop_Statement
4374 Block_HSS : Node_Id := First (Statements (Stmt));
4377 -- The loop statements may have been wrapped in a block by
4378 -- Process_Statements_For_Controlled_Objects, inspect the
4379 -- handled sequence of statements.
4381 if Nkind (Block_HSS) = N_Block_Statement
4382 and then No (Next (Block_HSS))
4384 Block_HSS := Handled_Statement_Sequence (Block_HSS);
4386 Process_Transient_Objects
4387 (First_Object => First (Statements (Block_HSS)),
4388 Last_Object => Last (Statements (Block_HSS)),
4389 Related_Node => Related_Node);
4391 -- Inspect the statements of the loop
4394 Process_Transient_Objects
4395 (First_Object => First (Statements (Stmt)),
4396 Last_Object => Last (Statements (Stmt)),
4397 Related_Node => Related_Node);
4401 -- Terminate the scan after the last object has been processed
4403 elsif Stmt = Last_Object then
4412 -- Raise_From_Controlled_Operation (E, Abort);
4416 and then Present (Last_Fin)
4418 Insert_After_And_Analyze (Last_Fin,
4419 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4421 end Process_Transient_Objects;
4423 -- Start of processing for Insert_Actions_In_Scope_Around
4426 if No (Before) and then No (After) then
4431 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
4432 First_Obj : Node_Id;
4437 -- If the node to be wrapped is the trigger of an asynchronous
4438 -- select, it is not part of a statement list. The actions must be
4439 -- inserted before the select itself, which is part of some list of
4440 -- statements. Note that the triggering alternative includes the
4441 -- triggering statement and an optional statement list. If the node
4442 -- to be wrapped is part of that list, the normal insertion applies.
4444 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4445 and then not Is_List_Member (Node_To_Wrap)
4447 Target := Parent (Parent (Node_To_Wrap));
4452 First_Obj := Target;
4455 -- Add all actions associated with a transient scope into the main
4456 -- tree. There are several scenarios here:
4458 -- +--- Before ----+ +----- After ---+
4459 -- 1) First_Obj ....... Target ........ Last_Obj
4461 -- 2) First_Obj ....... Target
4463 -- 3) Target ........ Last_Obj
4465 if Present (Before) then
4467 -- Flag declarations are inserted before the first object
4469 First_Obj := First (Before);
4471 Insert_List_Before (Target, Before);
4474 if Present (After) then
4476 -- Finalization calls are inserted after the last object
4478 Last_Obj := Last (After);
4480 Insert_List_After (Target, After);
4483 -- Check for transient controlled objects associated with Target and
4484 -- generate the appropriate finalization actions for them.
4486 Process_Transient_Objects
4487 (First_Object => First_Obj,
4488 Last_Object => Last_Obj,
4489 Related_Node => Target);
4491 -- Reset the action lists
4493 if Present (Before) then
4497 if Present (After) then
4501 end Insert_Actions_In_Scope_Around;
4503 ------------------------------
4504 -- Is_Simple_Protected_Type --
4505 ------------------------------
4507 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
4510 Is_Protected_Type (T)
4511 and then not Has_Entries (T)
4512 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
4513 end Is_Simple_Protected_Type;
4515 -----------------------
4516 -- Make_Adjust_Call --
4517 -----------------------
4519 function Make_Adjust_Call
4522 For_Parent : Boolean := False) return Node_Id
4524 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4525 Adj_Id : Entity_Id := Empty;
4526 Ref : Node_Id := Obj_Ref;
4530 -- Recover the proper type which contains Deep_Adjust
4532 if Is_Class_Wide_Type (Typ) then
4533 Utyp := Root_Type (Typ);
4538 Utyp := Underlying_Type (Base_Type (Utyp));
4539 Set_Assignment_OK (Ref);
4541 -- Deal with non-tagged derivation of private views
4543 if Is_Untagged_Derivation (Typ) then
4544 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
4545 Ref := Unchecked_Convert_To (Utyp, Ref);
4546 Set_Assignment_OK (Ref);
4549 -- When dealing with the completion of a private type, use the base
4552 if Utyp /= Base_Type (Utyp) then
4553 pragma Assert (Is_Private_Type (Typ));
4555 Utyp := Base_Type (Utyp);
4556 Ref := Unchecked_Convert_To (Utyp, Ref);
4559 -- Select the appropriate version of adjust
4562 if Has_Controlled_Component (Utyp) then
4563 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4566 -- For types that are both controlled and have controlled components,
4567 -- generate a call to Deep_Adjust.
4569 elsif Is_Controlled (Utyp)
4570 and then Has_Controlled_Component (Utyp)
4572 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4574 -- For types that are not controlled themselves, but contain controlled
4575 -- components or can be extended by types with controlled components,
4576 -- create a call to Deep_Adjust.
4578 elsif Is_Class_Wide_Type (Typ)
4579 or else Has_Controlled_Component (Utyp)
4581 if Is_Tagged_Type (Utyp) then
4582 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4584 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
4587 -- For types that are derived from Controlled and do not have controlled
4588 -- components, build a call to Adjust.
4591 Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
4594 if Present (Adj_Id) then
4596 -- If the object is unanalyzed, set its expected type for use in
4597 -- Convert_View in case an additional conversion is needed.
4600 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
4602 Set_Etype (Ref, Typ);
4605 -- The object reference may need another conversion depending on the
4606 -- type of the formal and that of the actual.
4608 if not Is_Class_Wide_Type (Typ) then
4609 Ref := Convert_View (Adj_Id, Ref);
4612 return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent);
4616 end Make_Adjust_Call;
4618 ----------------------
4619 -- Make_Attach_Call --
4620 ----------------------
4622 function Make_Attach_Call
4624 Ptr_Typ : Entity_Id) return Node_Id
4626 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4629 Make_Procedure_Call_Statement (Loc,
4631 New_Reference_To (RTE (RE_Attach), Loc),
4632 Parameter_Associations => New_List (
4633 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
4634 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4635 end Make_Attach_Call;
4637 ----------------------
4638 -- Make_Detach_Call --
4639 ----------------------
4641 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
4642 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4646 Make_Procedure_Call_Statement (Loc,
4648 New_Reference_To (RTE (RE_Detach), Loc),
4649 Parameter_Associations => New_List (
4650 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4651 end Make_Detach_Call;
4659 Proc_Id : Entity_Id;
4661 For_Parent : Boolean := False) return Node_Id
4663 Params : constant List_Id := New_List (Param);
4666 -- When creating a call to Deep_Finalize for a _parent field of a
4667 -- derived type, disable the invocation of the nested Finalize by giving
4668 -- the corresponding flag a False value.
4671 Append_To (Params, New_Reference_To (Standard_False, Loc));
4675 Make_Procedure_Call_Statement (Loc,
4676 Name => New_Reference_To (Proc_Id, Loc),
4677 Parameter_Associations => Params);
4680 --------------------------
4681 -- Make_Deep_Array_Body --
4682 --------------------------
4684 function Make_Deep_Array_Body
4685 (Prim : Final_Primitives;
4686 Typ : Entity_Id) return List_Id
4688 function Build_Adjust_Or_Finalize_Statements
4689 (Typ : Entity_Id) return List_Id;
4690 -- Create the statements necessary to adjust or finalize an array of
4691 -- controlled elements. Generate:
4694 -- Temp : constant Exception_Occurrence_Access :=
4695 -- Get_Current_Excep.all;
4696 -- Abort : constant Boolean :=
4698 -- and then Exception_Identity (Temp_Id.all) =
4699 -- Standard'Abort_Signal'Identity;
4701 -- Abort : constant Boolean := False; -- no abort
4703 -- E : Exception_Occurrence;
4704 -- Raised : Boolean := False;
4707 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
4708 -- ^-- in the finalization case
4710 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
4712 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
4716 -- if not Raised then
4718 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4726 -- Raise_From_Controlled_Operation (E, Abort);
4730 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
4731 -- Create the statements necessary to initialize an array of controlled
4732 -- elements. Include a mechanism to carry out partial finalization if an
4733 -- exception occurs. Generate:
4736 -- Counter : Integer := 0;
4739 -- for J1 in V'Range (1) loop
4741 -- for JN in V'Range (N) loop
4743 -- [Deep_]Initialize (V (J1, ..., JN));
4745 -- Counter := Counter + 1;
4750 -- Temp : constant Exception_Occurrence_Access :=
4751 -- Get_Current_Excep.all;
4752 -- Abort : constant Boolean :=
4754 -- and then Exception_Identity (Temp_Id.all) =
4755 -- Standard'Abort_Signal'Identity;
4757 -- Abort : constant Boolean := False; -- no abort
4758 -- E : Exception_Occurence;
4759 -- Raised : Boolean := False;
4766 -- V'Length (N) - Counter;
4768 -- for F1 in reverse V'Range (1) loop
4770 -- for FN in reverse V'Range (N) loop
4771 -- if Counter > 0 then
4772 -- Counter := Counter - 1;
4775 -- [Deep_]Finalize (V (F1, ..., FN));
4779 -- if not Raised then
4781 -- Save_Occurrence (E,
4782 -- Get_Current_Excep.all.all);
4792 -- Raise_From_Controlled_Operation (E, Abort);
4801 function New_References_To
4803 Loc : Source_Ptr) return List_Id;
4804 -- Given a list of defining identifiers, return a list of references to
4805 -- the original identifiers, in the same order as they appear.
4807 -----------------------------------------
4808 -- Build_Adjust_Or_Finalize_Statements --
4809 -----------------------------------------
4811 function Build_Adjust_Or_Finalize_Statements
4812 (Typ : Entity_Id) return List_Id
4814 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4815 Index_List : constant List_Id := New_List;
4816 Loc : constant Source_Ptr := Sloc (Typ);
4817 Num_Dims : constant Int := Number_Dimensions (Typ);
4818 Abort_Id : Entity_Id := Empty;
4821 Core_Loop : Node_Id;
4823 E_Id : Entity_Id := Empty;
4825 Loop_Id : Entity_Id;
4826 Raised_Id : Entity_Id := Empty;
4829 Exceptions_OK : constant Boolean :=
4830 not Restriction_Active (No_Exception_Propagation);
4832 procedure Build_Indices;
4833 -- Generate the indices used in the dimension loops
4839 procedure Build_Indices is
4841 -- Generate the following identifiers:
4842 -- Jnn - for initialization
4844 for Dim in 1 .. Num_Dims loop
4845 Append_To (Index_List,
4846 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4850 -- Start of processing for Build_Adjust_Or_Finalize_Statements
4855 if Exceptions_OK then
4856 Abort_Id := Make_Temporary (Loc, 'A');
4857 E_Id := Make_Temporary (Loc, 'E');
4858 Raised_Id := Make_Temporary (Loc, 'R');
4862 Make_Indexed_Component (Loc,
4863 Prefix => Make_Identifier (Loc, Name_V),
4864 Expressions => New_References_To (Index_List, Loc));
4865 Set_Etype (Comp_Ref, Comp_Typ);
4868 -- [Deep_]Adjust (V (J1, ..., JN))
4870 if Prim = Adjust_Case then
4871 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4874 -- [Deep_]Finalize (V (J1, ..., JN))
4876 else pragma Assert (Prim = Finalize_Case);
4877 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4880 -- Generate the block which houses the adjust or finalize call:
4882 -- <adjust or finalize call>; -- No_Exception_Propagation
4884 -- begin -- Exception handlers allowed
4885 -- <adjust or finalize call>
4889 -- if not Raised then
4891 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4895 if Exceptions_OK then
4897 Make_Block_Statement (Loc,
4898 Handled_Statement_Sequence =>
4899 Make_Handled_Sequence_Of_Statements (Loc,
4900 Statements => New_List (Call),
4901 Exception_Handlers => New_List (
4902 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4907 -- Generate the dimension loops starting from the innermost one
4909 -- for Jnn in [reverse] V'Range (Dim) loop
4913 J := Last (Index_List);
4915 while Present (J) and then Dim > 0 loop
4921 Make_Loop_Statement (Loc,
4923 Make_Iteration_Scheme (Loc,
4924 Loop_Parameter_Specification =>
4925 Make_Loop_Parameter_Specification (Loc,
4926 Defining_Identifier => Loop_Id,
4927 Discrete_Subtype_Definition =>
4928 Make_Attribute_Reference (Loc,
4929 Prefix => Make_Identifier (Loc, Name_V),
4930 Attribute_Name => Name_Range,
4931 Expressions => New_List (
4932 Make_Integer_Literal (Loc, Dim))),
4934 Reverse_Present => Prim = Finalize_Case)),
4936 Statements => New_List (Core_Loop),
4937 End_Label => Empty);
4942 -- Generate the block which contains the core loop, the declarations
4943 -- of the abort flag, the exception occurrence, the raised flag and
4944 -- the conditional raise:
4947 -- Abort : constant Boolean :=
4948 -- Exception_Occurrence (Get_Current_Excep.all.all) =
4949 -- Standard'Abort_Signal'Identity;
4951 -- Abort : constant Boolean := False; -- no abort
4953 -- E : Exception_Occurrence;
4954 -- Raised : Boolean := False;
4959 -- if Raised then -- Expection handlers allowed
4960 -- Raise_From_Controlled_Operation (E, Abort);
4964 Stmts := New_List (Core_Loop);
4966 if Exceptions_OK then
4968 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4973 Make_Block_Statement (Loc,
4975 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
4976 Handled_Statement_Sequence =>
4977 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4978 end Build_Adjust_Or_Finalize_Statements;
4980 ---------------------------------
4981 -- Build_Initialize_Statements --
4982 ---------------------------------
4984 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
4985 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4986 Final_List : constant List_Id := New_List;
4987 Index_List : constant List_Id := New_List;
4988 Loc : constant Source_Ptr := Sloc (Typ);
4989 Num_Dims : constant Int := Number_Dimensions (Typ);
4990 Abort_Id : Entity_Id;
4991 Counter_Id : Entity_Id;
4993 E_Id : Entity_Id := Empty;
4996 Final_Block : Node_Id;
4997 Final_Loop : Node_Id;
4998 Init_Loop : Node_Id;
5001 Raised_Id : Entity_Id := Empty;
5004 Exceptions_OK : constant Boolean :=
5005 not Restriction_Active (No_Exception_Propagation);
5007 function Build_Counter_Assignment return Node_Id;
5008 -- Generate the following assignment:
5009 -- Counter := V'Length (1) *
5011 -- V'Length (N) - Counter;
5013 function Build_Finalization_Call return Node_Id;
5014 -- Generate a deep finalization call for an array element
5016 procedure Build_Indices;
5017 -- Generate the initialization and finalization indices used in the
5020 function Build_Initialization_Call return Node_Id;
5021 -- Generate a deep initialization call for an array element
5023 ------------------------------
5024 -- Build_Counter_Assignment --
5025 ------------------------------
5027 function Build_Counter_Assignment return Node_Id is
5032 -- Start from the first dimension and generate:
5037 Make_Attribute_Reference (Loc,
5038 Prefix => Make_Identifier (Loc, Name_V),
5039 Attribute_Name => Name_Length,
5040 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
5042 -- Process the rest of the dimensions, generate:
5043 -- Expr * V'Length (N)
5046 while Dim <= Num_Dims loop
5048 Make_Op_Multiply (Loc,
5051 Make_Attribute_Reference (Loc,
5052 Prefix => Make_Identifier (Loc, Name_V),
5053 Attribute_Name => Name_Length,
5054 Expressions => New_List (
5055 Make_Integer_Literal (Loc, Dim))));
5061 -- Counter := Expr - Counter;
5064 Make_Assignment_Statement (Loc,
5065 Name => New_Reference_To (Counter_Id, Loc),
5067 Make_Op_Subtract (Loc,
5069 Right_Opnd => New_Reference_To (Counter_Id, Loc)));
5070 end Build_Counter_Assignment;
5072 -----------------------------
5073 -- Build_Finalization_Call --
5074 -----------------------------
5076 function Build_Finalization_Call return Node_Id is
5077 Comp_Ref : constant Node_Id :=
5078 Make_Indexed_Component (Loc,
5079 Prefix => Make_Identifier (Loc, Name_V),
5080 Expressions => New_References_To (Final_List, Loc));
5083 Set_Etype (Comp_Ref, Comp_Typ);
5086 -- [Deep_]Finalize (V);
5088 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5089 end Build_Finalization_Call;
5095 procedure Build_Indices is
5097 -- Generate the following identifiers:
5098 -- Jnn - for initialization
5099 -- Fnn - for finalization
5101 for Dim in 1 .. Num_Dims loop
5102 Append_To (Index_List,
5103 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5105 Append_To (Final_List,
5106 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5110 -------------------------------
5111 -- Build_Initialization_Call --
5112 -------------------------------
5114 function Build_Initialization_Call return Node_Id is
5115 Comp_Ref : constant Node_Id :=
5116 Make_Indexed_Component (Loc,
5117 Prefix => Make_Identifier (Loc, Name_V),
5118 Expressions => New_References_To (Index_List, Loc));
5121 Set_Etype (Comp_Ref, Comp_Typ);
5124 -- [Deep_]Initialize (V (J1, ..., JN));
5126 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5127 end Build_Initialization_Call;
5129 -- Start of processing for Build_Initialize_Statements
5134 Counter_Id := Make_Temporary (Loc, 'C');
5136 if Exceptions_OK then
5137 Abort_Id := Make_Temporary (Loc, 'A');
5138 E_Id := Make_Temporary (Loc, 'E');
5139 Raised_Id := Make_Temporary (Loc, 'R');
5142 -- Generate the block which houses the finalization call, the index
5143 -- guard and the handler which triggers Program_Error later on.
5145 -- if Counter > 0 then
5146 -- Counter := Counter - 1;
5148 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5150 -- begin -- Exceptions allowed
5151 -- [Deep_]Finalize (V (F1, ..., FN));
5154 -- if not Raised then
5156 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5161 if Exceptions_OK then
5163 Make_Block_Statement (Loc,
5164 Handled_Statement_Sequence =>
5165 Make_Handled_Sequence_Of_Statements (Loc,
5166 Statements => New_List (Build_Finalization_Call),
5167 Exception_Handlers => New_List (
5168 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5170 Fin_Stmt := Build_Finalization_Call;
5173 -- This is the core of the loop, the dimension iterators are added
5174 -- one by one in reverse.
5177 Make_If_Statement (Loc,
5180 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5181 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5183 Then_Statements => New_List (
5184 Make_Assignment_Statement (Loc,
5185 Name => New_Reference_To (Counter_Id, Loc),
5187 Make_Op_Subtract (Loc,
5188 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5189 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5191 Else_Statements => New_List (Fin_Stmt));
5193 -- Generate all finalization loops starting from the innermost
5196 -- for Fnn in reverse V'Range (Dim) loop
5200 F := Last (Final_List);
5202 while Present (F) and then Dim > 0 loop
5208 Make_Loop_Statement (Loc,
5210 Make_Iteration_Scheme (Loc,
5211 Loop_Parameter_Specification =>
5212 Make_Loop_Parameter_Specification (Loc,
5213 Defining_Identifier => Loop_Id,
5214 Discrete_Subtype_Definition =>
5215 Make_Attribute_Reference (Loc,
5216 Prefix => Make_Identifier (Loc, Name_V),
5217 Attribute_Name => Name_Range,
5218 Expressions => New_List (
5219 Make_Integer_Literal (Loc, Dim))),
5221 Reverse_Present => True)),
5223 Statements => New_List (Final_Loop),
5224 End_Label => Empty);
5229 -- Generate the block which contains the finalization loops, the
5230 -- declarations of the abort flag, the exception occurrence, the
5231 -- raised flag and the conditional raise.
5234 -- Abort : constant Boolean :=
5235 -- Exception_Occurrence (Get_Current_Excep.all.all) =
5236 -- Standard'Abort_Signal'Identity;
5238 -- Abort : constant Boolean := False; -- no abort
5240 -- E : Exception_Occurrence;
5241 -- Raised : Boolean := False;
5247 -- V'Length (N) - Counter;
5251 -- if Raised then -- Exception handlers allowed
5252 -- Raise_From_Controlled_Operation (E, Abort);
5255 -- raise; -- Exception handlers allowed
5258 Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5260 if Exceptions_OK then
5262 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
5263 Append_To (Stmts, Make_Raise_Statement (Loc));
5267 Make_Block_Statement (Loc,
5269 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
5270 Handled_Statement_Sequence =>
5271 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5273 -- Generate the block which contains the initialization call and
5274 -- the partial finalization code.
5277 -- [Deep_]Initialize (V (J1, ..., JN));
5279 -- Counter := Counter + 1;
5283 -- <finalization code>
5287 Make_Block_Statement (Loc,
5288 Handled_Statement_Sequence =>
5289 Make_Handled_Sequence_Of_Statements (Loc,
5290 Statements => New_List (Build_Initialization_Call),
5291 Exception_Handlers => New_List (
5292 Make_Exception_Handler (Loc,
5293 Exception_Choices => New_List (Make_Others_Choice (Loc)),
5294 Statements => New_List (Final_Block)))));
5296 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5297 Make_Assignment_Statement (Loc,
5298 Name => New_Reference_To (Counter_Id, Loc),
5301 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5302 Right_Opnd => Make_Integer_Literal (Loc, 1))));
5304 -- Generate all initialization loops starting from the innermost
5307 -- for Jnn in V'Range (Dim) loop
5311 J := Last (Index_List);
5313 while Present (J) and then Dim > 0 loop
5319 Make_Loop_Statement (Loc,
5321 Make_Iteration_Scheme (Loc,
5322 Loop_Parameter_Specification =>
5323 Make_Loop_Parameter_Specification (Loc,
5324 Defining_Identifier => Loop_Id,
5325 Discrete_Subtype_Definition =>
5326 Make_Attribute_Reference (Loc,
5327 Prefix => Make_Identifier (Loc, Name_V),
5328 Attribute_Name => Name_Range,
5329 Expressions => New_List (
5330 Make_Integer_Literal (Loc, Dim))))),
5332 Statements => New_List (Init_Loop),
5333 End_Label => Empty);
5338 -- Generate the block which contains the counter variable and the
5339 -- initialization loops.
5342 -- Counter : Integer := 0;
5349 Make_Block_Statement (Loc,
5350 Declarations => New_List (
5351 Make_Object_Declaration (Loc,
5352 Defining_Identifier => Counter_Id,
5353 Object_Definition =>
5354 New_Reference_To (Standard_Integer, Loc),
5355 Expression => Make_Integer_Literal (Loc, 0))),
5357 Handled_Statement_Sequence =>
5358 Make_Handled_Sequence_Of_Statements (Loc,
5359 Statements => New_List (Init_Loop))));
5360 end Build_Initialize_Statements;
5362 -----------------------
5363 -- New_References_To --
5364 -----------------------
5366 function New_References_To
5368 Loc : Source_Ptr) return List_Id
5370 Refs : constant List_Id := New_List;
5375 while Present (Id) loop
5376 Append_To (Refs, New_Reference_To (Id, Loc));
5381 end New_References_To;
5383 -- Start of processing for Make_Deep_Array_Body
5387 when Address_Case =>
5388 return Make_Finalize_Address_Stmts (Typ);
5392 return Build_Adjust_Or_Finalize_Statements (Typ);
5394 when Initialize_Case =>
5395 return Build_Initialize_Statements (Typ);
5397 end Make_Deep_Array_Body;
5399 --------------------
5400 -- Make_Deep_Proc --
5401 --------------------
5403 function Make_Deep_Proc
5404 (Prim : Final_Primitives;
5406 Stmts : List_Id) return Entity_Id
5408 Loc : constant Source_Ptr := Sloc (Typ);
5410 Proc_Id : Entity_Id;
5413 -- Create the object formal, generate:
5414 -- V : System.Address
5416 if Prim = Address_Case then
5417 Formals := New_List (
5418 Make_Parameter_Specification (Loc,
5419 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5420 Parameter_Type => New_Reference_To (RTE (RE_Address), Loc)));
5427 Formals := New_List (
5428 Make_Parameter_Specification (Loc,
5429 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5431 Out_Present => True,
5432 Parameter_Type => New_Reference_To (Typ, Loc)));
5434 -- F : Boolean := True
5436 if Prim = Adjust_Case
5437 or else Prim = Finalize_Case
5440 Make_Parameter_Specification (Loc,
5441 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5443 New_Reference_To (Standard_Boolean, Loc),
5445 New_Reference_To (Standard_True, Loc)));
5450 Make_Defining_Identifier (Loc,
5451 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5454 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5457 -- exception -- Finalize and Adjust cases only
5458 -- raise Program_Error;
5459 -- end Deep_Initialize / Adjust / Finalize;
5463 -- procedure Finalize_Address (V : System.Address) is
5466 -- end Finalize_Address;
5469 Make_Subprogram_Body (Loc,
5471 Make_Procedure_Specification (Loc,
5472 Defining_Unit_Name => Proc_Id,
5473 Parameter_Specifications => Formals),
5475 Declarations => Empty_List,
5477 Handled_Statement_Sequence =>
5478 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
5483 ---------------------------
5484 -- Make_Deep_Record_Body --
5485 ---------------------------
5487 function Make_Deep_Record_Body
5488 (Prim : Final_Primitives;
5490 Is_Local : Boolean := False) return List_Id
5492 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
5493 -- Build the statements necessary to adjust a record type. The type may
5494 -- have discriminants and contain variant parts. Generate:
5497 -- Root_Controlled (V).Finalized := False;
5500 -- [Deep_]Adjust (V.Comp_1);
5502 -- when Id : others =>
5503 -- if not Raised then
5505 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5510 -- [Deep_]Adjust (V.Comp_N);
5512 -- when Id : others =>
5513 -- if not Raised then
5515 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5520 -- Deep_Adjust (V._parent, False); -- If applicable
5522 -- when Id : others =>
5523 -- if not Raised then
5525 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5531 -- Adjust (V); -- If applicable
5534 -- if not Raised then
5536 -- Save_Occurence (E, Get_Current_Excep.all.all);
5542 -- Raise_From_Controlled_Object (E, Abort);
5546 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
5547 -- Build the statements necessary to finalize a record type. The type
5548 -- may have discriminants and contain variant parts. Generate:
5551 -- Temp : constant Exception_Occurrence_Access :=
5552 -- Get_Current_Excep.all;
5553 -- Abort : constant Boolean :=
5555 -- and then Exception_Identity (Temp_Id.all) =
5556 -- Standard'Abort_Signal'Identity;
5558 -- Abort : constant Boolean := False; -- no abort
5559 -- E : Exception_Occurence;
5560 -- Raised : Boolean := False;
5563 -- if Root_Controlled (V).Finalized then
5569 -- Finalize (V); -- If applicable
5572 -- if not Raised then
5574 -- Save_Occurence (E, Get_Current_Excep.all.all);
5579 -- case Variant_1 is
5581 -- case State_Counter_N => -- If Is_Local is enabled
5591 -- <<LN>> -- If Is_Local is enabled
5593 -- [Deep_]Finalize (V.Comp_N);
5596 -- if not Raised then
5598 -- Save_Occurence (E, Get_Current_Excep.all.all);
5604 -- [Deep_]Finalize (V.Comp_1);
5607 -- if not Raised then
5609 -- Save_Occurence (E, Get_Current_Excep.all.all);
5615 -- case State_Counter_1 => -- If Is_Local is enabled
5621 -- Deep_Finalize (V._parent, False); -- If applicable
5623 -- when Id : others =>
5624 -- if not Raised then
5626 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5630 -- Root_Controlled (V).Finalized := True;
5633 -- Raise_From_Controlled_Object (E, Abort);
5637 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
5638 -- Given a derived tagged type Typ, traverse all components, find field
5639 -- _parent and return its type.
5641 procedure Preprocess_Components
5643 Num_Comps : out Int;
5644 Has_POC : out Boolean);
5645 -- Examine all components in component list Comps, count all controlled
5646 -- components and determine whether at least one of them is per-object
5647 -- constrained. Component _parent is always skipped.
5649 -----------------------------
5650 -- Build_Adjust_Statements --
5651 -----------------------------
5653 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
5654 Loc : constant Source_Ptr := Sloc (Typ);
5655 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
5656 Abort_Id : Entity_Id := Empty;
5657 Bod_Stmts : List_Id;
5658 E_Id : Entity_Id := Empty;
5659 Raised_Id : Entity_Id := Empty;
5663 Exceptions_OK : constant Boolean :=
5664 not Restriction_Active (No_Exception_Propagation);
5666 function Process_Component_List_For_Adjust
5667 (Comps : Node_Id) return List_Id;
5668 -- Build all necessary adjust statements for a single component list
5670 ---------------------------------------
5671 -- Process_Component_List_For_Adjust --
5672 ---------------------------------------
5674 function Process_Component_List_For_Adjust
5675 (Comps : Node_Id) return List_Id
5677 Stmts : constant List_Id := New_List;
5679 Decl_Id : Entity_Id;
5680 Decl_Typ : Entity_Id;
5684 procedure Process_Component_For_Adjust (Decl : Node_Id);
5685 -- Process the declaration of a single controlled component
5687 ----------------------------------
5688 -- Process_Component_For_Adjust --
5689 ----------------------------------
5691 procedure Process_Component_For_Adjust (Decl : Node_Id) is
5692 Id : constant Entity_Id := Defining_Identifier (Decl);
5693 Typ : constant Entity_Id := Etype (Id);
5698 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
5700 -- begin -- Exception handlers allowed
5701 -- [Deep_]Adjust (V.Id);
5704 -- if not Raised then
5706 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5713 Make_Selected_Component (Loc,
5714 Prefix => Make_Identifier (Loc, Name_V),
5715 Selector_Name => Make_Identifier (Loc, Chars (Id))),
5718 if Exceptions_OK then
5720 Make_Block_Statement (Loc,
5721 Handled_Statement_Sequence =>
5722 Make_Handled_Sequence_Of_Statements (Loc,
5723 Statements => New_List (Adj_Stmt),
5724 Exception_Handlers => New_List (
5725 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5728 Append_To (Stmts, Adj_Stmt);
5729 end Process_Component_For_Adjust;
5731 -- Start of processing for Process_Component_List_For_Adjust
5734 -- Perform an initial check, determine the number of controlled
5735 -- components in the current list and whether at least one of them
5736 -- is per-object constrained.
5738 Preprocess_Components (Comps, Num_Comps, Has_POC);
5740 -- The processing in this routine is done in the following order:
5741 -- 1) Regular components
5742 -- 2) Per-object constrained components
5745 if Num_Comps > 0 then
5747 -- Process all regular components in order of declarations
5749 Decl := First_Non_Pragma (Component_Items (Comps));
5750 while Present (Decl) loop
5751 Decl_Id := Defining_Identifier (Decl);
5752 Decl_Typ := Etype (Decl_Id);
5754 -- Skip _parent as well as per-object constrained components
5756 if Chars (Decl_Id) /= Name_uParent
5757 and then Needs_Finalization (Decl_Typ)
5759 if Has_Access_Constraint (Decl_Id)
5760 and then No (Expression (Decl))
5764 Process_Component_For_Adjust (Decl);
5768 Next_Non_Pragma (Decl);
5771 -- Process all per-object constrained components in order of
5775 Decl := First_Non_Pragma (Component_Items (Comps));
5776 while Present (Decl) loop
5777 Decl_Id := Defining_Identifier (Decl);
5778 Decl_Typ := Etype (Decl_Id);
5782 if Chars (Decl_Id) /= Name_uParent
5783 and then Needs_Finalization (Decl_Typ)
5784 and then Has_Access_Constraint (Decl_Id)
5785 and then No (Expression (Decl))
5787 Process_Component_For_Adjust (Decl);
5790 Next_Non_Pragma (Decl);
5795 -- Process all variants, if any
5798 if Present (Variant_Part (Comps)) then
5800 Var_Alts : constant List_Id := New_List;
5804 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
5805 while Present (Var) loop
5808 -- when <discrete choices> =>
5809 -- <adjust statements>
5811 Append_To (Var_Alts,
5812 Make_Case_Statement_Alternative (Loc,
5814 New_Copy_List (Discrete_Choices (Var)),
5816 Process_Component_List_For_Adjust (
5817 Component_List (Var))));
5819 Next_Non_Pragma (Var);
5823 -- case V.<discriminant> is
5824 -- when <discrete choices 1> =>
5825 -- <adjust statements 1>
5827 -- when <discrete choices N> =>
5828 -- <adjust statements N>
5832 Make_Case_Statement (Loc,
5834 Make_Selected_Component (Loc,
5835 Prefix => Make_Identifier (Loc, Name_V),
5837 Make_Identifier (Loc,
5838 Chars => Chars (Name (Variant_Part (Comps))))),
5839 Alternatives => Var_Alts);
5843 -- Add the variant case statement to the list of statements
5845 if Present (Var_Case) then
5846 Append_To (Stmts, Var_Case);
5849 -- If the component list did not have any controlled components
5850 -- nor variants, return null.
5852 if Is_Empty_List (Stmts) then
5853 Append_To (Stmts, Make_Null_Statement (Loc));
5857 end Process_Component_List_For_Adjust;
5859 -- Start of processing for Build_Adjust_Statements
5862 if Exceptions_OK then
5863 Abort_Id := Make_Temporary (Loc, 'A');
5864 E_Id := Make_Temporary (Loc, 'E');
5865 Raised_Id := Make_Temporary (Loc, 'R');
5868 if Nkind (Typ_Def) = N_Derived_Type_Definition then
5869 Rec_Def := Record_Extension_Part (Typ_Def);
5874 -- Create an adjust sequence for all record components
5876 if Present (Component_List (Rec_Def)) then
5878 Process_Component_List_For_Adjust (Component_List (Rec_Def));
5881 -- A derived record type must adjust all inherited components. This
5882 -- action poses the following problem:
5884 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
5889 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
5891 -- Deep_Adjust (Obj._parent);
5896 -- Adjusting the derived type will invoke Adjust of the parent and
5897 -- then that of the derived type. This is undesirable because both
5898 -- routines may modify shared components. Only the Adjust of the
5899 -- derived type should be invoked.
5901 -- To prevent this double adjustment of shared components,
5902 -- Deep_Adjust uses a flag to control the invocation of Adjust:
5904 -- procedure Deep_Adjust
5905 -- (Obj : in out Some_Type;
5906 -- Flag : Boolean := True)
5914 -- When Deep_Adjust is invokes for field _parent, a value of False is
5915 -- provided for the flag:
5917 -- Deep_Adjust (Obj._parent, False);
5919 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
5921 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
5926 if Needs_Finalization (Par_Typ) then
5930 Make_Selected_Component (Loc,
5931 Prefix => Make_Identifier (Loc, Name_V),
5933 Make_Identifier (Loc, Name_uParent)),
5935 For_Parent => True);
5938 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
5940 -- begin -- Exceptions OK
5941 -- Deep_Adjust (V._parent, False);
5943 -- when Id : others =>
5944 -- if not Raised then
5946 -- Save_Occurrence (E,
5947 -- Get_Current_Excep.all.all);
5951 if Present (Call) then
5954 if Exceptions_OK then
5956 Make_Block_Statement (Loc,
5957 Handled_Statement_Sequence =>
5958 Make_Handled_Sequence_Of_Statements (Loc,
5959 Statements => New_List (Adj_Stmt),
5960 Exception_Handlers => New_List (
5961 Build_Exception_Handler
5962 (Loc, E_Id, Raised_Id))));
5965 Prepend_To (Bod_Stmts, Adj_Stmt);
5971 -- Adjust the object. This action must be performed last after all
5972 -- components have been adjusted.
5974 if Is_Controlled (Typ) then
5980 Proc := Find_Prim_Op (Typ, Name_Adjust);
5984 -- Adjust (V); -- No_Exception_Propagation
5986 -- begin -- Exception handlers allowed
5990 -- if not Raised then
5992 -- Save_Occurrence (E,
5993 -- Get_Current_Excep.all.all);
5998 if Present (Proc) then
6000 Make_Procedure_Call_Statement (Loc,
6001 Name => New_Reference_To (Proc, Loc),
6002 Parameter_Associations => New_List (
6003 Make_Identifier (Loc, Name_V)));
6005 if Exceptions_OK then
6007 Make_Block_Statement (Loc,
6008 Handled_Statement_Sequence =>
6009 Make_Handled_Sequence_Of_Statements (Loc,
6010 Statements => New_List (Adj_Stmt),
6011 Exception_Handlers => New_List (
6012 Build_Exception_Handler
6013 (Loc, E_Id, Raised_Id))));
6016 Append_To (Bod_Stmts,
6017 Make_If_Statement (Loc,
6018 Condition => Make_Identifier (Loc, Name_F),
6019 Then_Statements => New_List (Adj_Stmt)));
6024 -- At this point either all adjustment statements have been generated
6025 -- or the type is not controlled.
6027 if Is_Empty_List (Bod_Stmts) then
6028 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6034 -- Abort : constant Boolean :=
6035 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6036 -- Standard'Abort_Signal'Identity;
6038 -- Abort : constant Boolean := False; -- no abort
6040 -- E : Exception_Occurence;
6041 -- Raised : Boolean := False;
6044 -- Root_Controlled (V).Finalized := False;
6046 -- <adjust statements>
6049 -- Raise_From_Controlled_Operation (E, Abort);
6054 if Exceptions_OK then
6055 Append_To (Bod_Stmts,
6056 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6061 Make_Block_Statement (Loc,
6063 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6064 Handled_Statement_Sequence =>
6065 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6067 end Build_Adjust_Statements;
6069 -------------------------------
6070 -- Build_Finalize_Statements --
6071 -------------------------------
6073 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6074 Loc : constant Source_Ptr := Sloc (Typ);
6075 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6076 Abort_Id : Entity_Id := Empty;
6077 Bod_Stmts : List_Id;
6079 E_Id : Entity_Id := Empty;
6080 Raised_Id : Entity_Id := Empty;
6084 Exceptions_OK : constant Boolean :=
6085 not Restriction_Active (No_Exception_Propagation);
6087 function Process_Component_List_For_Finalize
6088 (Comps : Node_Id) return List_Id;
6089 -- Build all necessary finalization statements for a single component
6090 -- list. The statements may include a jump circuitry if flag Is_Local
6093 -----------------------------------------
6094 -- Process_Component_List_For_Finalize --
6095 -----------------------------------------
6097 function Process_Component_List_For_Finalize
6098 (Comps : Node_Id) return List_Id
6101 Counter_Id : Entity_Id;
6103 Decl_Id : Entity_Id;
6104 Decl_Typ : Entity_Id;
6107 Jump_Block : Node_Id;
6109 Label_Id : Entity_Id;
6113 procedure Process_Component_For_Finalize
6118 -- Process the declaration of a single controlled component. If
6119 -- flag Is_Local is enabled, create the corresponding label and
6120 -- jump circuitry. Alts is the list of case alternatives, Decls
6121 -- is the top level declaration list where labels are declared
6122 -- and Stmts is the list of finalization actions.
6124 ------------------------------------
6125 -- Process_Component_For_Finalize --
6126 ------------------------------------
6128 procedure Process_Component_For_Finalize
6134 Id : constant Entity_Id := Defining_Identifier (Decl);
6135 Typ : constant Entity_Id := Etype (Id);
6142 Label_Id : Entity_Id;
6149 Make_Identifier (Loc,
6150 Chars => New_External_Name ('L', Num_Comps));
6151 Set_Entity (Label_Id,
6152 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6153 Label := Make_Label (Loc, Label_Id);
6156 Make_Implicit_Label_Declaration (Loc,
6157 Defining_Identifier => Entity (Label_Id),
6158 Label_Construct => Label));
6165 Make_Case_Statement_Alternative (Loc,
6166 Discrete_Choices => New_List (
6167 Make_Integer_Literal (Loc, Num_Comps)),
6169 Statements => New_List (
6170 Make_Goto_Statement (Loc,
6172 New_Reference_To (Entity (Label_Id), Loc)))));
6177 Append_To (Stmts, Label);
6179 -- Decrease the number of components to be processed.
6180 -- This action yields a new Label_Id in future calls.
6182 Num_Comps := Num_Comps - 1;
6187 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6189 -- begin -- Exception handlers allowed
6190 -- [Deep_]Finalize (V.Id);
6193 -- if not Raised then
6195 -- Save_Occurrence (E,
6196 -- Get_Current_Excep.all.all);
6203 Make_Selected_Component (Loc,
6204 Prefix => Make_Identifier (Loc, Name_V),
6205 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6208 if not Restriction_Active (No_Exception_Propagation) then
6210 Make_Block_Statement (Loc,
6211 Handled_Statement_Sequence =>
6212 Make_Handled_Sequence_Of_Statements (Loc,
6213 Statements => New_List (Fin_Stmt),
6214 Exception_Handlers => New_List (
6215 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
6218 Append_To (Stmts, Fin_Stmt);
6219 end Process_Component_For_Finalize;
6221 -- Start of processing for Process_Component_List_For_Finalize
6224 -- Perform an initial check, look for controlled and per-object
6225 -- constrained components.
6227 Preprocess_Components (Comps, Num_Comps, Has_POC);
6229 -- Create a state counter to service the current component list.
6230 -- This step is performed before the variants are inspected in
6231 -- order to generate the same state counter names as those from
6232 -- Build_Initialize_Statements.
6237 Counter := Counter + 1;
6240 Make_Defining_Identifier (Loc,
6241 Chars => New_External_Name ('C', Counter));
6244 -- Process the component in the following order:
6246 -- 2) Per-object constrained components
6247 -- 3) Regular components
6249 -- Start with the variant parts
6252 if Present (Variant_Part (Comps)) then
6254 Var_Alts : constant List_Id := New_List;
6258 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6259 while Present (Var) loop
6262 -- when <discrete choices> =>
6263 -- <finalize statements>
6265 Append_To (Var_Alts,
6266 Make_Case_Statement_Alternative (Loc,
6268 New_Copy_List (Discrete_Choices (Var)),
6270 Process_Component_List_For_Finalize (
6271 Component_List (Var))));
6273 Next_Non_Pragma (Var);
6277 -- case V.<discriminant> is
6278 -- when <discrete choices 1> =>
6279 -- <finalize statements 1>
6281 -- when <discrete choices N> =>
6282 -- <finalize statements N>
6286 Make_Case_Statement (Loc,
6288 Make_Selected_Component (Loc,
6289 Prefix => Make_Identifier (Loc, Name_V),
6291 Make_Identifier (Loc,
6292 Chars => Chars (Name (Variant_Part (Comps))))),
6293 Alternatives => Var_Alts);
6297 -- The current component list does not have a single controlled
6298 -- component, however it may contain variants. Return the case
6299 -- statement for the variants or nothing.
6301 if Num_Comps = 0 then
6302 if Present (Var_Case) then
6303 return New_List (Var_Case);
6305 return New_List (Make_Null_Statement (Loc));
6309 -- Prepare all lists
6315 -- Process all per-object constrained components in reverse order
6318 Decl := Last_Non_Pragma (Component_Items (Comps));
6319 while Present (Decl) loop
6320 Decl_Id := Defining_Identifier (Decl);
6321 Decl_Typ := Etype (Decl_Id);
6325 if Chars (Decl_Id) /= Name_uParent
6326 and then Needs_Finalization (Decl_Typ)
6327 and then Has_Access_Constraint (Decl_Id)
6328 and then No (Expression (Decl))
6330 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6333 Prev_Non_Pragma (Decl);
6337 -- Process the rest of the components in reverse order
6339 Decl := Last_Non_Pragma (Component_Items (Comps));
6340 while Present (Decl) loop
6341 Decl_Id := Defining_Identifier (Decl);
6342 Decl_Typ := Etype (Decl_Id);
6346 if Chars (Decl_Id) /= Name_uParent
6347 and then Needs_Finalization (Decl_Typ)
6349 -- Skip per-object constrained components since they were
6350 -- handled in the above step.
6352 if Has_Access_Constraint (Decl_Id)
6353 and then No (Expression (Decl))
6357 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6361 Prev_Non_Pragma (Decl);
6366 -- LN : label; -- If Is_Local is enabled
6371 -- case CounterX is .
6381 -- <<LN>> -- If Is_Local is enabled
6383 -- [Deep_]Finalize (V.CompY);
6385 -- when Id : others =>
6386 -- if not Raised then
6388 -- Save_Occurrence (E,
6389 -- Get_Current_Excep.all.all);
6393 -- <<L0>> -- If Is_Local is enabled
6398 -- Add the declaration of default jump location L0, its
6399 -- corresponding alternative and its place in the statements.
6401 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6402 Set_Entity (Label_Id,
6403 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6404 Label := Make_Label (Loc, Label_Id);
6406 Append_To (Decls, -- declaration
6407 Make_Implicit_Label_Declaration (Loc,
6408 Defining_Identifier => Entity (Label_Id),
6409 Label_Construct => Label));
6411 Append_To (Alts, -- alternative
6412 Make_Case_Statement_Alternative (Loc,
6413 Discrete_Choices => New_List (
6414 Make_Others_Choice (Loc)),
6416 Statements => New_List (
6417 Make_Goto_Statement (Loc,
6418 Name => New_Reference_To (Entity (Label_Id), Loc)))));
6420 Append_To (Stmts, Label); -- statement
6422 -- Create the jump block
6425 Make_Case_Statement (Loc,
6426 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
6427 Alternatives => Alts));
6431 Make_Block_Statement (Loc,
6432 Declarations => Decls,
6433 Handled_Statement_Sequence =>
6434 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6436 if Present (Var_Case) then
6437 return New_List (Var_Case, Jump_Block);
6439 return New_List (Jump_Block);
6441 end Process_Component_List_For_Finalize;
6443 -- Start of processing for Build_Finalize_Statements
6446 if Exceptions_OK then
6447 Abort_Id := Make_Temporary (Loc, 'A');
6448 E_Id := Make_Temporary (Loc, 'E');
6449 Raised_Id := Make_Temporary (Loc, 'R');
6452 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6453 Rec_Def := Record_Extension_Part (Typ_Def);
6458 -- Create a finalization sequence for all record components
6460 if Present (Component_List (Rec_Def)) then
6462 Process_Component_List_For_Finalize (Component_List (Rec_Def));
6465 -- A derived record type must finalize all inherited components. This
6466 -- action poses the following problem:
6468 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6473 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6475 -- Deep_Finalize (Obj._parent);
6480 -- Finalizing the derived type will invoke Finalize of the parent and
6481 -- then that of the derived type. This is undesirable because both
6482 -- routines may modify shared components. Only the Finalize of the
6483 -- derived type should be invoked.
6485 -- To prevent this double adjustment of shared components,
6486 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6488 -- procedure Deep_Finalize
6489 -- (Obj : in out Some_Type;
6490 -- Flag : Boolean := True)
6498 -- When Deep_Finalize is invokes for field _parent, a value of False
6499 -- is provided for the flag:
6501 -- Deep_Finalize (Obj._parent, False);
6503 if Is_Tagged_Type (Typ)
6504 and then Is_Derived_Type (Typ)
6507 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6512 if Needs_Finalization (Par_Typ) then
6516 Make_Selected_Component (Loc,
6517 Prefix => Make_Identifier (Loc, Name_V),
6519 Make_Identifier (Loc, Name_uParent)),
6521 For_Parent => True);
6524 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
6526 -- begin -- Exceptions OK
6527 -- Deep_Finalize (V._parent, False);
6529 -- when Id : others =>
6530 -- if not Raised then
6532 -- Save_Occurrence (E,
6533 -- Get_Current_Excep.all.all);
6537 if Present (Call) then
6540 if Exceptions_OK then
6542 Make_Block_Statement (Loc,
6543 Handled_Statement_Sequence =>
6544 Make_Handled_Sequence_Of_Statements (Loc,
6545 Statements => New_List (Fin_Stmt),
6546 Exception_Handlers => New_List (
6547 Build_Exception_Handler
6548 (Loc, E_Id, Raised_Id))));
6551 Append_To (Bod_Stmts, Fin_Stmt);
6557 -- Finalize the object. This action must be performed first before
6558 -- all components have been finalized.
6560 if Is_Controlled (Typ)
6561 and then not Is_Local
6568 Proc := Find_Prim_Op (Typ, Name_Finalize);
6572 -- Finalize (V); -- No_Exception_Propagation
6578 -- if not Raised then
6580 -- Save_Occurrence (E,
6581 -- Get_Current_Excep.all.all);
6586 if Present (Proc) then
6588 Make_Procedure_Call_Statement (Loc,
6589 Name => New_Reference_To (Proc, Loc),
6590 Parameter_Associations => New_List (
6591 Make_Identifier (Loc, Name_V)));
6593 if Exceptions_OK then
6595 Make_Block_Statement (Loc,
6596 Handled_Statement_Sequence =>
6597 Make_Handled_Sequence_Of_Statements (Loc,
6598 Statements => New_List (Fin_Stmt),
6599 Exception_Handlers => New_List (
6600 Build_Exception_Handler
6601 (Loc, E_Id, Raised_Id))));
6604 Prepend_To (Bod_Stmts,
6605 Make_If_Statement (Loc,
6606 Condition => Make_Identifier (Loc, Name_F),
6607 Then_Statements => New_List (Fin_Stmt)));
6612 -- At this point either all finalization statements have been
6613 -- generated or the type is not controlled.
6615 if No (Bod_Stmts) then
6616 return New_List (Make_Null_Statement (Loc));
6620 -- Abort : constant Boolean :=
6621 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6622 -- Standard'Abort_Signal'Identity;
6624 -- Abort : constant Boolean := False; -- no abort
6626 -- E : Exception_Occurence;
6627 -- Raised : Boolean := False;
6630 -- if V.Finalized then
6634 -- <finalize statements>
6635 -- V.Finalized := True;
6638 -- Raise_From_Controlled_Operation (E, Abort);
6643 if Exceptions_OK then
6644 Append_To (Bod_Stmts,
6645 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6650 Make_Block_Statement (Loc,
6652 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6653 Handled_Statement_Sequence =>
6654 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6656 end Build_Finalize_Statements;
6658 -----------------------
6659 -- Parent_Field_Type --
6660 -----------------------
6662 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
6666 Field := First_Entity (Typ);
6667 while Present (Field) loop
6668 if Chars (Field) = Name_uParent then
6669 return Etype (Field);
6672 Next_Entity (Field);
6675 -- A derived tagged type should always have a parent field
6677 raise Program_Error;
6678 end Parent_Field_Type;
6680 ---------------------------
6681 -- Preprocess_Components --
6682 ---------------------------
6684 procedure Preprocess_Components
6686 Num_Comps : out Int;
6687 Has_POC : out Boolean)
6697 Decl := First_Non_Pragma (Component_Items (Comps));
6698 while Present (Decl) loop
6699 Id := Defining_Identifier (Decl);
6702 -- Skip field _parent
6704 if Chars (Id) /= Name_uParent
6705 and then Needs_Finalization (Typ)
6707 Num_Comps := Num_Comps + 1;
6709 if Has_Access_Constraint (Id)
6710 and then No (Expression (Decl))
6716 Next_Non_Pragma (Decl);
6718 end Preprocess_Components;
6720 -- Start of processing for Make_Deep_Record_Body
6724 when Address_Case =>
6725 return Make_Finalize_Address_Stmts (Typ);
6728 return Build_Adjust_Statements (Typ);
6730 when Finalize_Case =>
6731 return Build_Finalize_Statements (Typ);
6733 when Initialize_Case =>
6735 Loc : constant Source_Ptr := Sloc (Typ);
6738 if Is_Controlled (Typ) then
6740 Make_Procedure_Call_Statement (Loc,
6743 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
6744 Parameter_Associations => New_List (
6745 Make_Identifier (Loc, Name_V))));
6751 end Make_Deep_Record_Body;
6753 ----------------------
6754 -- Make_Final_Call --
6755 ----------------------
6757 function Make_Final_Call
6760 For_Parent : Boolean := False) return Node_Id
6762 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6764 Fin_Id : Entity_Id := Empty;
6769 -- Recover the proper type which contains [Deep_]Finalize
6771 if Is_Class_Wide_Type (Typ) then
6772 Utyp := Root_Type (Typ);
6776 elsif Is_Concurrent_Type (Typ) then
6777 Utyp := Corresponding_Record_Type (Typ);
6779 Ref := Convert_Concurrent (Obj_Ref, Typ);
6781 elsif Is_Private_Type (Typ)
6782 and then Present (Full_View (Typ))
6783 and then Is_Concurrent_Type (Full_View (Typ))
6785 Utyp := Corresponding_Record_Type (Full_View (Typ));
6787 Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ));
6795 Utyp := Underlying_Type (Base_Type (Utyp));
6796 Set_Assignment_OK (Ref);
6798 -- Deal with non-tagged derivation of private views. If the parent type
6799 -- is a protected type, Deep_Finalize is found on the corresponding
6800 -- record of the ancestor.
6802 if Is_Untagged_Derivation (Typ) then
6803 if Is_Protected_Type (Typ) then
6804 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
6806 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6808 if Is_Protected_Type (Utyp) then
6809 Utyp := Corresponding_Record_Type (Utyp);
6813 Ref := Unchecked_Convert_To (Utyp, Ref);
6814 Set_Assignment_OK (Ref);
6817 -- Deal with derived private types which do not inherit primitives from
6818 -- their parents. In this case, [Deep_]Finalize can be found in the full
6819 -- view of the parent type.
6821 if Is_Tagged_Type (Utyp)
6822 and then Is_Derived_Type (Utyp)
6823 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
6824 and then Is_Private_Type (Etype (Utyp))
6825 and then Present (Full_View (Etype (Utyp)))
6827 Utyp := Full_View (Etype (Utyp));
6828 Ref := Unchecked_Convert_To (Utyp, Ref);
6829 Set_Assignment_OK (Ref);
6832 -- When dealing with the completion of a private type, use the base type
6835 if Utyp /= Base_Type (Utyp) then
6836 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
6838 Utyp := Base_Type (Utyp);
6839 Ref := Unchecked_Convert_To (Utyp, Ref);
6840 Set_Assignment_OK (Ref);
6843 -- Select the appropriate version of finalize
6846 if Has_Controlled_Component (Utyp) then
6847 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6850 -- For types that are both controlled and have controlled components,
6851 -- generate a call to Deep_Finalize.
6853 elsif Is_Controlled (Utyp)
6854 and then Has_Controlled_Component (Utyp)
6856 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6858 -- For types that are not controlled themselves, but contain controlled
6859 -- components or can be extended by types with controlled components,
6860 -- create a call to Deep_Finalize.
6862 elsif Is_Class_Wide_Type (Typ)
6863 or else Is_Interface (Typ)
6864 or else Has_Controlled_Component (Utyp)
6866 if Is_Tagged_Type (Utyp) then
6867 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6869 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
6872 -- For types that are derived from Controlled and do not have controlled
6873 -- components, build a call to Finalize.
6876 Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
6879 if Present (Fin_Id) then
6881 -- When finalizing a class-wide object, do not convert to the root
6882 -- type in order to produce a dispatching call.
6884 if Is_Class_Wide_Type (Typ) then
6887 -- Ensure that a finalization routine is at least decorated in order
6888 -- to inspect the object parameter.
6890 elsif Analyzed (Fin_Id)
6891 or else Ekind (Fin_Id) = E_Procedure
6893 -- In certain cases, such as the creation of Stream_Read, the
6894 -- visible entity of the type is its full view. Since Stream_Read
6895 -- will have to create an object of type Typ, the local object
6896 -- will be finalzed by the scope finalizer generated later on. The
6897 -- object parameter of Deep_Finalize will always use the private
6898 -- view of the type. To avoid such a clash between a private and a
6899 -- full view, perform an unchecked conversion of the object
6900 -- reference to the private view.
6903 Formal_Typ : constant Entity_Id :=
6904 Etype (First_Formal (Fin_Id));
6906 if Is_Private_Type (Formal_Typ)
6907 and then Present (Full_View (Formal_Typ))
6908 and then Full_View (Formal_Typ) = Utyp
6910 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
6914 Ref := Convert_View (Fin_Id, Ref);
6917 return Make_Call (Loc, Fin_Id, New_Copy_Tree (Ref), For_Parent);
6921 end Make_Final_Call;
6923 --------------------------------
6924 -- Make_Finalize_Address_Body --
6925 --------------------------------
6927 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
6929 -- Nothing to do if the type is not controlled or it already has a
6930 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
6931 -- come from source. These are usually generated for completeness and
6932 -- do not need the Finalize_Address primitive.
6934 if not Needs_Finalization (Typ)
6935 or else Present (TSS (Typ, TSS_Finalize_Address))
6937 (Is_Class_Wide_Type (Typ)
6938 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
6939 and then not Comes_From_Source (Root_Type (Typ)))
6945 Loc : constant Source_Ptr := Sloc (Typ);
6946 Proc_Id : Entity_Id;
6950 Make_Defining_Identifier (Loc,
6951 Make_TSS_Name (Typ, TSS_Finalize_Address));
6954 -- procedure TypFD (V : System.Address) is
6957 -- type Pnn is access all Typ;
6958 -- for Pnn'Storage_Size use 0;
6960 -- [Deep_]Finalize (Pnn (V).all);
6965 Make_Subprogram_Body (Loc,
6967 Make_Procedure_Specification (Loc,
6968 Defining_Unit_Name => Proc_Id,
6970 Parameter_Specifications => New_List (
6971 Make_Parameter_Specification (Loc,
6972 Defining_Identifier =>
6973 Make_Defining_Identifier (Loc, Name_V),
6975 New_Reference_To (RTE (RE_Address), Loc)))),
6977 Declarations => No_List,
6979 Handled_Statement_Sequence =>
6980 Make_Handled_Sequence_Of_Statements (Loc,
6982 Make_Finalize_Address_Stmts (Typ))));
6984 Set_TSS (Typ, Proc_Id);
6986 end Make_Finalize_Address_Body;
6988 ---------------------------------
6989 -- Make_Finalize_Address_Stmts --
6990 ---------------------------------
6992 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
6993 Loc : constant Source_Ptr := Sloc (Typ);
6994 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
6996 Desg_Typ : Entity_Id;
6999 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
7000 -- Subsidiary routine, generate the following attribute reference:
7002 -- Some_Typ'Alignment
7004 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
7005 -- Subsidiary routine, generate the following expression:
7007 -- 2 * Some_Typ'Alignment
7013 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
7016 Make_Attribute_Reference (Loc,
7017 Prefix => New_Reference_To (Some_Typ, Loc),
7018 Attribute_Name => Name_Alignment);
7021 -------------------------
7022 -- Double_Alignment_Of --
7023 -------------------------
7025 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
7028 Make_Op_Multiply (Loc,
7029 Left_Opnd => Make_Integer_Literal (Loc, 2),
7030 Right_Opnd => Alignment_Of (Some_Typ));
7031 end Double_Alignment_Of;
7033 -- Start of processing for Make_Finalize_Address_Stmts
7036 if Is_Array_Type (Typ) then
7037 if Is_Constrained (First_Subtype (Typ)) then
7038 Desg_Typ := First_Subtype (Typ);
7040 Desg_Typ := Base_Type (Typ);
7043 -- Class-wide types of constrained root types
7045 elsif Is_Class_Wide_Type (Typ)
7046 and then Has_Discriminants (Root_Type (Typ))
7048 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7051 Parent_Typ : Entity_Id := Root_Type (Typ);
7054 -- Climb the parent type chain looking for a non-constrained type
7056 while Parent_Typ /= Etype (Parent_Typ)
7057 and then Has_Discriminants (Parent_Typ)
7059 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7061 Parent_Typ := Etype (Parent_Typ);
7064 -- Handle views created for tagged types with unknown
7067 if Is_Underlying_Record_View (Parent_Typ) then
7068 Parent_Typ := Underlying_Record_View (Parent_Typ);
7071 Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
7081 -- type Ptr_Typ is access all Typ;
7082 -- for Ptr_Typ'Storage_Size use 0;
7085 Make_Full_Type_Declaration (Loc,
7086 Defining_Identifier => Ptr_Typ,
7088 Make_Access_To_Object_Definition (Loc,
7089 All_Present => True,
7090 Subtype_Indication => New_Reference_To (Desg_Typ, Loc))),
7092 Make_Attribute_Definition_Clause (Loc,
7093 Name => New_Reference_To (Ptr_Typ, Loc),
7094 Chars => Name_Storage_Size,
7095 Expression => Make_Integer_Literal (Loc, 0)));
7097 Obj_Expr := Make_Identifier (Loc, Name_V);
7099 -- Unconstrained arrays require special processing in order to retrieve
7100 -- the elements. To achieve this, we have to skip the dope vector which
7101 -- lays in front of the elements and then use a thin pointer to perform
7102 -- the address-to-access conversion.
7104 if Is_Array_Type (Typ)
7105 and then not Is_Constrained (First_Subtype (Typ))
7108 Dope_Expr : Node_Id;
7109 Dope_Id : Entity_Id;
7110 For_First : Boolean := True;
7112 Index_Typ : Entity_Id;
7115 -- Ensure that Ptr_Typ a thin pointer, generate:
7117 -- for Ptr_Typ'Size use System.Address'Size;
7120 Make_Attribute_Definition_Clause (Loc,
7121 Name => New_Reference_To (Ptr_Typ, Loc),
7124 Make_Integer_Literal (Loc, System_Address_Size)));
7126 -- For unconstrained arrays, create the expression which computes
7127 -- the size of the dope vector.
7129 Index := First_Index (Typ);
7130 while Present (Index) loop
7131 Index_Typ := Etype (Index);
7133 -- Each bound has two values and a potential hole added to
7134 -- compensate for alignment differences.
7140 -- 2 * Index_Typ'Alignment
7142 Dope_Expr := Double_Alignment_Of (Index_Typ);
7146 -- Dope_Expr + 2 * Index_Typ'Alignment
7150 Left_Opnd => Dope_Expr,
7151 Right_Opnd => Double_Alignment_Of (Index_Typ));
7157 -- Round the cumulative alignment to the next higher multiple of
7158 -- the array alignment. Generate:
7160 -- ((Dope_Expr + Typ'Alignment - 1) / Typ'Alignment)
7164 Make_Op_Multiply (Loc,
7166 Make_Op_Divide (Loc,
7169 Left_Opnd => Dope_Expr,
7171 Make_Op_Subtract (Loc,
7172 Left_Opnd => Alignment_Of (Typ),
7173 Right_Opnd => Make_Integer_Literal (Loc, 1))),
7174 Right_Opnd => Alignment_Of (Typ)),
7175 Right_Opnd => Alignment_Of (Typ));
7178 -- Dnn : Storage_Offset := Dope_Expr;
7180 Dope_Id := Make_Temporary (Loc, 'D');
7183 Make_Object_Declaration (Loc,
7184 Defining_Identifier => Dope_Id,
7185 Constant_Present => True,
7186 Object_Definition =>
7187 New_Reference_To (RTE (RE_Storage_Offset), Loc),
7188 Expression => Dope_Expr));
7190 -- Shift the address from the start of the dope vector to the
7191 -- start of the elements:
7195 -- Note that this is done through a wrapper routine since RTSfind
7196 -- cannot retrieve operations with string names of the form "+".
7199 Make_Function_Call (Loc,
7201 New_Reference_To (RTE (RE_Add_Offset_To_Address), Loc),
7202 Parameter_Associations => New_List (
7204 New_Reference_To (Dope_Id, Loc)));
7208 -- Create the block and the finalization call
7211 Make_Block_Statement (Loc,
7212 Declarations => Decls,
7214 Handled_Statement_Sequence =>
7215 Make_Handled_Sequence_Of_Statements (Loc,
7216 Statements => New_List (
7219 Make_Explicit_Dereference (Loc,
7220 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7221 Typ => Desg_Typ)))));
7222 end Make_Finalize_Address_Stmts;
7224 -------------------------------------
7225 -- Make_Handler_For_Ctrl_Operation --
7226 -------------------------------------
7230 -- when E : others =>
7231 -- Raise_From_Controlled_Operation (E, False);
7236 -- raise Program_Error [finalize raised exception];
7238 -- depending on whether Raise_From_Controlled_Operation is available
7240 function Make_Handler_For_Ctrl_Operation
7241 (Loc : Source_Ptr) return Node_Id
7244 -- Choice parameter (for the first case above)
7246 Raise_Node : Node_Id;
7247 -- Procedure call or raise statement
7250 -- Standard runtime, .NET/JVM targets: add choice parameter E and pass
7251 -- it to Raise_From_Controlled_Operation so that the original exception
7252 -- name and message can be recorded in the exception message for
7255 if RTE_Available (RE_Raise_From_Controlled_Operation) then
7256 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7258 Make_Procedure_Call_Statement (Loc,
7261 (RTE (RE_Raise_From_Controlled_Operation), Loc),
7262 Parameter_Associations => New_List (
7263 New_Reference_To (E_Occ, Loc),
7264 New_Reference_To (Standard_False, Loc)));
7266 -- Restricted runtime: exception messages are not supported
7271 Make_Raise_Program_Error (Loc,
7272 Reason => PE_Finalize_Raised_Exception);
7276 Make_Implicit_Exception_Handler (Loc,
7277 Exception_Choices => New_List (Make_Others_Choice (Loc)),
7278 Choice_Parameter => E_Occ,
7279 Statements => New_List (Raise_Node));
7280 end Make_Handler_For_Ctrl_Operation;
7282 --------------------
7283 -- Make_Init_Call --
7284 --------------------
7286 function Make_Init_Call
7288 Typ : Entity_Id) return Node_Id
7290 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7297 -- Deal with the type and object reference. Depending on the context, an
7298 -- object reference may need several conversions.
7300 if Is_Concurrent_Type (Typ) then
7302 Utyp := Corresponding_Record_Type (Typ);
7303 Ref := Convert_Concurrent (Obj_Ref, Typ);
7305 elsif Is_Private_Type (Typ)
7306 and then Present (Full_View (Typ))
7307 and then Is_Concurrent_Type (Underlying_Type (Typ))
7310 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7311 Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7319 Set_Assignment_OK (Ref);
7321 Utyp := Underlying_Type (Base_Type (Utyp));
7323 -- Deal with non-tagged derivation of private views
7325 if Is_Untagged_Derivation (Typ)
7326 and then not Is_Conc
7328 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7329 Ref := Unchecked_Convert_To (Utyp, Ref);
7331 -- The following is to prevent problems with UC see 1.156 RH ???
7333 Set_Assignment_OK (Ref);
7336 -- If the underlying_type is a subtype, then we are dealing with the
7337 -- completion of a private type. We need to access the base type and
7338 -- generate a conversion to it.
7340 if Utyp /= Base_Type (Utyp) then
7341 pragma Assert (Is_Private_Type (Typ));
7342 Utyp := Base_Type (Utyp);
7343 Ref := Unchecked_Convert_To (Utyp, Ref);
7346 -- Select the appropriate version of initialize
7348 if Has_Controlled_Component (Utyp) then
7349 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7351 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7352 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7355 -- The object reference may need another conversion depending on the
7356 -- type of the formal and that of the actual.
7358 Ref := Convert_View (Proc, Ref);
7361 -- [Deep_]Initialize (Ref);
7364 Make_Procedure_Call_Statement (Loc,
7366 New_Reference_To (Proc, Loc),
7367 Parameter_Associations => New_List (Ref));
7370 ------------------------------
7371 -- Make_Local_Deep_Finalize --
7372 ------------------------------
7374 function Make_Local_Deep_Finalize
7376 Nam : Entity_Id) return Node_Id
7378 Loc : constant Source_Ptr := Sloc (Typ);
7382 Formals := New_List (
7386 Make_Parameter_Specification (Loc,
7387 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7389 Out_Present => True,
7390 Parameter_Type => New_Reference_To (Typ, Loc)),
7392 -- F : Boolean := True
7394 Make_Parameter_Specification (Loc,
7395 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7396 Parameter_Type => New_Reference_To (Standard_Boolean, Loc),
7397 Expression => New_Reference_To (Standard_True, Loc)));
7399 -- Add the necessary number of counters to represent the initialization
7400 -- state of an object.
7403 Make_Subprogram_Body (Loc,
7405 Make_Procedure_Specification (Loc,
7406 Defining_Unit_Name => Nam,
7407 Parameter_Specifications => Formals),
7409 Declarations => No_List,
7411 Handled_Statement_Sequence =>
7412 Make_Handled_Sequence_Of_Statements (Loc,
7413 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7414 end Make_Local_Deep_Finalize;
7416 ----------------------------------------
7417 -- Make_Set_Finalize_Address_Ptr_Call --
7418 ----------------------------------------
7420 function Make_Set_Finalize_Address_Ptr_Call
7423 Ptr_Typ : Entity_Id) return Node_Id
7425 Desig_Typ : constant Entity_Id :=
7426 Available_View (Designated_Type (Ptr_Typ));
7430 -- If the context is a class-wide allocator, we use the class-wide type
7431 -- to obtain the proper Finalize_Address routine.
7433 if Is_Class_Wide_Type (Desig_Typ) then
7439 if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
7440 Utyp := Full_View (Utyp);
7443 if Is_Concurrent_Type (Utyp) then
7444 Utyp := Corresponding_Record_Type (Utyp);
7448 Utyp := Underlying_Type (Base_Type (Utyp));
7450 -- Deal with non-tagged derivation of private views. If the parent is
7451 -- now known to be protected, the finalization routine is the one
7452 -- defined on the corresponding record of the ancestor (corresponding
7453 -- records do not automatically inherit operations, but maybe they
7456 if Is_Untagged_Derivation (Typ) then
7457 if Is_Protected_Type (Typ) then
7458 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7460 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7462 if Is_Protected_Type (Utyp) then
7463 Utyp := Corresponding_Record_Type (Utyp);
7468 -- If the underlying_type is a subtype, we are dealing with the
7469 -- completion of a private type. We need to access the base type and
7470 -- generate a conversion to it.
7472 if Utyp /= Base_Type (Utyp) then
7473 pragma Assert (Is_Private_Type (Typ));
7475 Utyp := Base_Type (Utyp);
7479 -- Set_Finalize_Address_Ptr
7480 -- (<Ptr_Typ>FC, <Utyp>FD'Unrestricted_Access);
7483 Make_Procedure_Call_Statement (Loc,
7485 New_Reference_To (RTE (RE_Set_Finalize_Address_Ptr), Loc),
7487 Parameter_Associations => New_List (
7488 New_Reference_To (Associated_Collection (Ptr_Typ), Loc),
7490 Make_Attribute_Reference (Loc,
7492 New_Reference_To (TSS (Utyp, TSS_Finalize_Address), Loc),
7493 Attribute_Name => Name_Unrestricted_Access)));
7494 end Make_Set_Finalize_Address_Ptr_Call;
7496 --------------------------
7497 -- Make_Transient_Block --
7498 --------------------------
7500 function Make_Transient_Block
7503 Par : Node_Id) return Node_Id
7505 Decls : constant List_Id := New_List;
7506 Instrs : constant List_Id := New_List (Action);
7511 -- Case where only secondary stack use is involved
7513 if VM_Target = No_VM
7514 and then Uses_Sec_Stack (Current_Scope)
7515 and then Nkind (Action) /= N_Simple_Return_Statement
7516 and then Nkind (Par) /= N_Exception_Handler
7522 S := Scope (Current_Scope);
7524 -- At the outer level, no need to release the sec stack
7526 if S = Standard_Standard then
7527 Set_Uses_Sec_Stack (Current_Scope, False);
7530 -- In a function, only release the sec stack if the
7531 -- function does not return on the sec stack otherwise
7532 -- the result may be lost. The caller is responsible for
7535 elsif Ekind (S) = E_Function then
7536 Set_Uses_Sec_Stack (Current_Scope, False);
7538 if not Requires_Transient_Scope (Etype (S)) then
7539 Set_Uses_Sec_Stack (S, True);
7540 Check_Restriction (No_Secondary_Stack, Action);
7545 -- In a loop or entry we should install a block encompassing
7546 -- all the construct. For now just release right away.
7548 elsif Ekind_In (S, E_Entry, E_Loop) then
7551 -- In a procedure or a block, we release on exit of the
7552 -- procedure or block. ??? memory leak can be created by
7555 elsif Ekind_In (S, E_Block, E_Procedure) then
7556 Set_Uses_Sec_Stack (S, True);
7557 Check_Restriction (No_Secondary_Stack, Action);
7558 Set_Uses_Sec_Stack (Current_Scope, False);
7568 -- Create the transient block. Set the parent now since the block itself
7569 -- is not part of the tree.
7572 Make_Block_Statement (Loc,
7573 Identifier => New_Reference_To (Current_Scope, Loc),
7574 Declarations => Decls,
7575 Handled_Statement_Sequence =>
7576 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7577 Has_Created_Identifier => True);
7578 Set_Parent (Block, Par);
7580 -- Insert actions stuck in the transient scopes as well as all freezing
7581 -- nodes needed by those actions.
7583 Insert_Actions_In_Scope_Around (Action);
7585 Insert := Prev (Action);
7586 if Present (Insert) then
7587 Freeze_All (First_Entity (Current_Scope), Insert);
7590 -- When the transient scope was established, we pushed the entry for
7591 -- the transient scope onto the scope stack, so that the scope was
7592 -- active for the installation of finalizable entities etc. Now we
7593 -- must remove this entry, since we have constructed a proper block.
7598 end Make_Transient_Block;
7600 ------------------------
7601 -- Node_To_Be_Wrapped --
7602 ------------------------
7604 function Node_To_Be_Wrapped return Node_Id is
7606 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
7607 end Node_To_Be_Wrapped;
7609 ----------------------------
7610 -- Set_Node_To_Be_Wrapped --
7611 ----------------------------
7613 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
7615 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
7616 end Set_Node_To_Be_Wrapped;
7618 ----------------------------------
7619 -- Store_After_Actions_In_Scope --
7620 ----------------------------------
7622 procedure Store_After_Actions_In_Scope (L : List_Id) is
7623 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7626 if Present (SE.Actions_To_Be_Wrapped_After) then
7627 Insert_List_Before_And_Analyze (
7628 First (SE.Actions_To_Be_Wrapped_After), L);
7631 SE.Actions_To_Be_Wrapped_After := L;
7633 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7634 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7636 Set_Parent (L, SE.Node_To_Be_Wrapped);
7641 end Store_After_Actions_In_Scope;
7643 -----------------------------------
7644 -- Store_Before_Actions_In_Scope --
7645 -----------------------------------
7647 procedure Store_Before_Actions_In_Scope (L : List_Id) is
7648 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7651 if Present (SE.Actions_To_Be_Wrapped_Before) then
7652 Insert_List_After_And_Analyze (
7653 Last (SE.Actions_To_Be_Wrapped_Before), L);
7656 SE.Actions_To_Be_Wrapped_Before := L;
7658 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7659 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7661 Set_Parent (L, SE.Node_To_Be_Wrapped);
7666 end Store_Before_Actions_In_Scope;
7668 --------------------------------
7669 -- Wrap_Transient_Declaration --
7670 --------------------------------
7672 -- If a transient scope has been established during the processing of the
7673 -- Expression of an Object_Declaration, it is not possible to wrap the
7674 -- declaration into a transient block as usual case, otherwise the object
7675 -- would be itself declared in the wrong scope. Therefore, all entities (if
7676 -- any) defined in the transient block are moved to the proper enclosing
7677 -- scope, furthermore, if they are controlled variables they are finalized
7678 -- right after the declaration. The finalization list of the transient
7679 -- scope is defined as a renaming of the enclosing one so during their
7680 -- initialization they will be attached to the proper finalization list.
7681 -- For instance, the following declaration :
7683 -- X : Typ := F (G (A), G (B));
7685 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7686 -- is expanded into :
7688 -- X : Typ := [ complex Expression-Action ];
7689 -- [Deep_]Finalize (_v1);
7690 -- [Deep_]Finalize (_v2);
7692 procedure Wrap_Transient_Declaration (N : Node_Id) is
7699 Encl_S := Scope (S);
7701 -- Insert Actions kept in the Scope stack
7703 Insert_Actions_In_Scope_Around (N);
7705 -- If the declaration is consuming some secondary stack, mark the
7706 -- enclosing scope appropriately.
7708 Uses_SS := Uses_Sec_Stack (S);
7711 -- Put the local entities back in the enclosing scope, and set the
7712 -- Is_Public flag appropriately.
7714 Transfer_Entities (S, Encl_S);
7716 -- Mark the enclosing dynamic scope so that the sec stack will be
7717 -- released upon its exit unless this is a function that returns on
7718 -- the sec stack in which case this will be done by the caller.
7720 if VM_Target = No_VM and then Uses_SS then
7721 S := Enclosing_Dynamic_Scope (S);
7723 if Ekind (S) = E_Function
7724 and then Requires_Transient_Scope (Etype (S))
7728 Set_Uses_Sec_Stack (S);
7729 Check_Restriction (No_Secondary_Stack, N);
7732 end Wrap_Transient_Declaration;
7734 -------------------------------
7735 -- Wrap_Transient_Expression --
7736 -------------------------------
7738 procedure Wrap_Transient_Expression (N : Node_Id) is
7739 Expr : constant Node_Id := Relocate_Node (N);
7740 Loc : constant Source_Ptr := Sloc (N);
7741 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
7742 Typ : constant Entity_Id := Etype (N);
7749 -- M : constant Mark_Id := SS_Mark;
7750 -- procedure Finalizer is ... (See Build_Finalizer)
7759 Insert_Actions (N, New_List (
7760 Make_Object_Declaration (Loc,
7761 Defining_Identifier => Temp,
7762 Object_Definition => New_Reference_To (Typ, Loc)),
7764 Make_Transient_Block (Loc,
7766 Make_Assignment_Statement (Loc,
7767 Name => New_Reference_To (Temp, Loc),
7768 Expression => Expr),
7769 Par => Parent (N))));
7771 Rewrite (N, New_Reference_To (Temp, Loc));
7772 Analyze_And_Resolve (N, Typ);
7773 end Wrap_Transient_Expression;
7775 ------------------------------
7776 -- Wrap_Transient_Statement --
7777 ------------------------------
7779 procedure Wrap_Transient_Statement (N : Node_Id) is
7780 Loc : constant Source_Ptr := Sloc (N);
7781 New_Stmt : constant Node_Id := Relocate_Node (N);
7786 -- M : constant Mark_Id := SS_Mark;
7787 -- procedure Finalizer is ... (See Build_Finalizer)
7797 Make_Transient_Block (Loc,
7799 Par => Parent (N)));
7801 -- With the scope stack back to normal, we can call analyze on the
7802 -- resulting block. At this point, the transient scope is being
7803 -- treated like a perfectly normal scope, so there is nothing
7804 -- special about it.
7806 -- Note: Wrap_Transient_Statement is called with the node already
7807 -- analyzed (i.e. Analyzed (N) is True). This is important, since
7808 -- otherwise we would get a recursive processing of the node when
7809 -- we do this Analyze call.
7812 end Wrap_Transient_Statement;