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, Make_Deep_Array_Body and
435 -- Make_Deep_Record_Body. 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_Master --
802 -------------------------------
804 procedure Build_Finalization_Master
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_Master
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
850 -- finalization master.
852 elsif Present (Finalization_Master (Typ)) then
855 -- Do not process types that return on the secondary stack
857 elsif Present (Associated_Storage_Pool (Typ))
858 and then Is_RTE (Associated_Storage_Pool (Typ), RE_SS_Pool)
862 -- Do not process types which may never allocate an object
864 elsif No_Pool_Assigned (Typ) then
867 -- Do not process access types coming from Ada.Unchecked_Deallocation
868 -- instances. Even though the designated type may be controlled, the
869 -- access type will never participate in allocation.
871 elsif In_Deallocation_Instance (Typ) then
874 -- Ignore the general use of anonymous access types unless the context
875 -- requires a finalization master.
877 elsif Ekind (Typ) = E_Anonymous_Access_Type
878 and then No (Ins_Node)
882 -- Do not process non-library access types when restriction No_Nested_
883 -- Finalization is in effect since masters are controlled objects.
885 elsif Restriction_Active (No_Nested_Finalization)
886 and then not Is_Library_Level_Entity (Typ)
890 -- For .NET/JVM targets, allow the processing of access-to-controlled
891 -- types where the designated type is explicitly derived from [Limited_]
894 elsif VM_Target /= No_VM
895 and then not Is_Controlled (Desig_Typ)
901 Loc : constant Source_Ptr := Sloc (Typ);
902 Actions : constant List_Id := New_List;
903 Fin_Mas_Id : Entity_Id;
905 Ptr_Typ : Entity_Id := Typ;
908 -- Access subtypes must use the storage pool of their base type
910 if Ekind (Ptr_Typ) = E_Access_Subtype then
911 Ptr_Typ := Base_Type (Ptr_Typ);
915 -- Fnn : aliased Finalization_Master;
917 -- Source access types use fixed master names since the master is
918 -- inserted in the same source unit only once. The only exception to
919 -- this are instances using the same access type as generic actual.
921 if Comes_From_Source (Ptr_Typ)
922 and then not Inside_A_Generic
925 Make_Defining_Identifier (Loc,
926 Chars => New_External_Name (Chars (Ptr_Typ), "FM"));
928 -- Internally generated access types use temporaries as their names
929 -- due to possible collision with identical names coming from other
933 Fin_Mas_Id := Make_Temporary (Loc, 'F');
937 Make_Object_Declaration (Loc,
938 Defining_Identifier => Fin_Mas_Id,
939 Aliased_Present => True,
941 New_Reference_To (RTE (RE_Finalization_Master), Loc)));
943 -- Storage pool selection and attribute decoration of the generated
944 -- master. Since .NET/JVM compilers do not support pools, this step
947 if VM_Target = No_VM then
949 -- If the access type has a user-defined pool, use it as the base
950 -- storage medium for the finalization pool.
952 if Present (Associated_Storage_Pool (Ptr_Typ)) then
953 Pool_Id := Associated_Storage_Pool (Ptr_Typ);
955 -- The default choice is the global pool
958 Pool_Id := Get_Global_Pool_For_Access_Type (Ptr_Typ);
959 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
963 -- Set_Base_Pool (Fnn, Pool_Id'Unchecked_Access);
966 Make_Procedure_Call_Statement (Loc,
968 New_Reference_To (RTE (RE_Set_Base_Pool), Loc),
969 Parameter_Associations => New_List (
970 New_Reference_To (Fin_Mas_Id, Loc),
971 Make_Attribute_Reference (Loc,
972 Prefix => New_Reference_To (Pool_Id, Loc),
973 Attribute_Name => Name_Unrestricted_Access))));
976 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
978 -- A finalization master created for an anonymous access type must be
979 -- inserted before a context-dependent node.
981 if Present (Ins_Node) then
982 Push_Scope (Encl_Scope);
984 -- Treat use clauses as declarations and insert directly in front
987 if Nkind_In (Ins_Node, N_Use_Package_Clause,
990 Insert_List_Before_And_Analyze (Ins_Node, Actions);
992 Insert_Actions (Ins_Node, Actions);
997 elsif Ekind (Typ) = E_Access_Subtype
998 or else (Ekind (Desig_Typ) = E_Incomplete_Type
999 and then Has_Completion_In_Body (Desig_Typ))
1001 Insert_Actions (Parent (Typ), Actions);
1003 -- If the designated type is not yet frozen, then append the actions
1004 -- to that type's freeze actions. The actions need to be appended to
1005 -- whichever type is frozen later, similarly to what Freeze_Type does
1006 -- for appending the storage pool declaration for an access type.
1007 -- Otherwise, the call to Set_Storage_Pool_Ptr might reference the
1008 -- pool object before it's declared. However, it's not clear that
1009 -- this is exactly the right test to accomplish that here. ???
1011 elsif Present (Freeze_Node (Desig_Typ))
1012 and then not Analyzed (Freeze_Node (Desig_Typ))
1014 Append_Freeze_Actions (Desig_Typ, Actions);
1016 elsif Present (Freeze_Node (Typ))
1017 and then not Analyzed (Freeze_Node (Typ))
1019 Append_Freeze_Actions (Typ, Actions);
1021 -- If there's a pool created locally for the access type, then we
1022 -- need to ensure that the master gets created after the pool object,
1023 -- because otherwise we can have a forward reference, so we force the
1024 -- master actions to be inserted and analyzed after the pool entity.
1025 -- Note that both the access type and its designated type may have
1026 -- already been frozen and had their freezing actions analyzed at
1027 -- this point. (This seems a little unclean.???)
1029 elsif VM_Target = No_VM
1030 and then Scope (Pool_Id) = Scope (Typ)
1032 Insert_List_After_And_Analyze (Parent (Pool_Id), Actions);
1035 Insert_Actions (Parent (Typ), Actions);
1038 end Build_Finalization_Master;
1040 ---------------------
1041 -- Build_Finalizer --
1042 ---------------------
1044 procedure Build_Finalizer
1046 Clean_Stmts : List_Id;
1047 Mark_Id : Entity_Id;
1048 Top_Decls : List_Id;
1049 Defer_Abort : Boolean;
1050 Fin_Id : out Entity_Id)
1052 Acts_As_Clean : constant Boolean :=
1055 (Present (Clean_Stmts)
1056 and then Is_Non_Empty_List (Clean_Stmts));
1057 Exceptions_OK : constant Boolean :=
1058 not Restriction_Active (No_Exception_Propagation);
1059 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1060 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1061 For_Package : constant Boolean :=
1062 For_Package_Body or else For_Package_Spec;
1063 Loc : constant Source_Ptr := Sloc (N);
1065 -- NOTE: Local variable declarations are conservative and do not create
1066 -- structures right from the start. Entities and lists are created once
1067 -- it has been established that N has at least one controlled object.
1069 Abort_Id : Entity_Id := Empty;
1070 -- Entity of local flag. The flag is set when finalization is triggered
1073 Components_Built : Boolean := False;
1074 -- A flag used to avoid double initialization of entities and lists. If
1075 -- the flag is set then the following variables have been initialized:
1085 Counter_Id : Entity_Id := Empty;
1086 Counter_Val : Int := 0;
1087 -- Name and value of the state counter
1089 Decls : List_Id := No_List;
1090 -- Declarative region of N (if available). If N is a package declaration
1091 -- Decls denotes the visible declarations.
1093 E_Id : Entity_Id := Empty;
1094 -- Entity of the local exception occurence. The first exception which
1095 -- occurred during finalization is stored in E_Id and later reraised.
1097 Finalizer_Decls : List_Id := No_List;
1098 -- Local variable declarations. This list holds the label declarations
1099 -- of all jump block alternatives as well as the declaration of the
1100 -- local exception occurence and the raised flag.
1102 -- E : Exception_Occurrence;
1103 -- Raised : Boolean := False;
1104 -- L<counter value> : label;
1106 Finalizer_Insert_Nod : Node_Id := Empty;
1107 -- Insertion point for the finalizer body. Depending on the context
1108 -- (Nkind of N) and the individual grouping of controlled objects, this
1109 -- node may denote a package declaration or body, package instantiation,
1110 -- block statement or a counter update statement.
1112 Finalizer_Stmts : List_Id := No_List;
1113 -- The statement list of the finalizer body. It contains the following:
1115 -- Abort_Defer; -- Added if abort is allowed
1116 -- <call to Prev_At_End> -- Added if exists
1117 -- <cleanup statements> -- Added if Acts_As_Clean
1118 -- <jump block> -- Added if Has_Ctrl_Objs
1119 -- <finalization statements> -- Added if Has_Ctrl_Objs
1120 -- <stack release> -- Added if Mark_Id exists
1121 -- Abort_Undefer; -- Added if abort is allowed
1123 Has_Ctrl_Objs : Boolean := False;
1124 -- A general flag which denotes whether N has at least one controlled
1127 Has_Tagged_Types : Boolean := False;
1128 -- A general flag which indicates whether N has at least one library-
1129 -- level tagged type declaration.
1131 HSS : Node_Id := Empty;
1132 -- The sequence of statements of N (if available)
1134 Jump_Alts : List_Id := No_List;
1135 -- Jump block alternatives. Depending on the value of the state counter,
1136 -- the control flow jumps to a sequence of finalization statements. This
1137 -- list contains the following:
1139 -- when <counter value> =>
1140 -- goto L<counter value>;
1142 Jump_Block_Insert_Nod : Node_Id := Empty;
1143 -- Specific point in the finalizer statements where the jump block is
1146 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1147 -- The last controlled construct encountered when processing the top
1148 -- level lists of N. This can be a nested package, an instantiation or
1149 -- an object declaration.
1151 Prev_At_End : Entity_Id := Empty;
1152 -- The previous at end procedure of the handled statements block of N
1154 Priv_Decls : List_Id := No_List;
1155 -- The private declarations of N if N is a package declaration
1157 Raised_Id : Entity_Id := Empty;
1158 -- Entity for the raised flag. Along with E_Id, the flag is used in the
1159 -- propagation of exceptions which occur during finalization.
1161 Spec_Id : Entity_Id := Empty;
1162 Spec_Decls : List_Id := Top_Decls;
1163 Stmts : List_Id := No_List;
1165 Tagged_Type_Stmts : List_Id := No_List;
1166 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1167 -- tagged types found in N.
1169 -----------------------
1170 -- Local subprograms --
1171 -----------------------
1173 procedure Build_Components;
1174 -- Create all entites and initialize all lists used in the creation of
1177 procedure Create_Finalizer;
1178 -- Create the spec and body of the finalizer and insert them in the
1179 -- proper place in the tree depending on the context.
1181 procedure Process_Declarations
1183 Preprocess : Boolean := False;
1184 Top_Level : Boolean := False);
1185 -- Inspect a list of declarations or statements which may contain
1186 -- objects that need finalization. When flag Preprocess is set, the
1187 -- routine will simply count the total number of controlled objects in
1188 -- Decls. Flag Top_Level denotes whether the processing is done for
1189 -- objects in nested package declarations or instances.
1191 procedure Process_Object_Declaration
1193 Has_No_Init : Boolean := False;
1194 Is_Protected : Boolean := False);
1195 -- Generate all the machinery associated with the finalization of a
1196 -- single object. Flag Has_No_Init is used to denote certain contexts
1197 -- where Decl does not have initialization call(s). Flag Is_Protected
1198 -- is set when Decl denotes a simple protected object.
1200 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1201 -- Generate all the code necessary to unregister the external tag of a
1204 ----------------------
1205 -- Build_Components --
1206 ----------------------
1208 procedure Build_Components is
1209 Counter_Decl : Node_Id;
1210 Counter_Typ : Entity_Id;
1211 Counter_Typ_Decl : Node_Id;
1214 pragma Assert (Present (Decls));
1216 -- This routine might be invoked several times when dealing with
1217 -- constructs that have two lists (either two declarative regions
1218 -- or declarations and statements). Avoid double initialization.
1220 if Components_Built then
1224 Components_Built := True;
1226 if Has_Ctrl_Objs then
1228 -- Create entities for the counter, its type, the local exception
1229 -- and the raised flag.
1231 Counter_Id := Make_Temporary (Loc, 'C');
1232 Counter_Typ := Make_Temporary (Loc, 'T');
1234 if Exceptions_OK then
1235 Abort_Id := Make_Temporary (Loc, 'A');
1236 E_Id := Make_Temporary (Loc, 'E');
1237 Raised_Id := Make_Temporary (Loc, 'R');
1240 -- Since the total number of controlled objects is always known,
1241 -- build a subtype of Natural with precise bounds. This allows
1242 -- the backend to optimize the case statement. Generate:
1244 -- subtype Tnn is Natural range 0 .. Counter_Val;
1247 Make_Subtype_Declaration (Loc,
1248 Defining_Identifier => Counter_Typ,
1249 Subtype_Indication =>
1250 Make_Subtype_Indication (Loc,
1251 Subtype_Mark => New_Reference_To (Standard_Natural, Loc),
1253 Make_Range_Constraint (Loc,
1257 Make_Integer_Literal (Loc, Uint_0),
1259 Make_Integer_Literal (Loc, Counter_Val)))));
1261 -- Generate the declaration of the counter itself:
1263 -- Counter : Integer := 0;
1266 Make_Object_Declaration (Loc,
1267 Defining_Identifier => Counter_Id,
1268 Object_Definition => New_Reference_To (Counter_Typ, Loc),
1269 Expression => Make_Integer_Literal (Loc, 0));
1271 -- Set the type of the counter explicitly to prevent errors when
1272 -- examining object declarations later on.
1274 Set_Etype (Counter_Id, Counter_Typ);
1276 -- The counter and its type are inserted before the source
1277 -- declarations of N.
1279 Prepend_To (Decls, Counter_Decl);
1280 Prepend_To (Decls, Counter_Typ_Decl);
1282 -- The counter and its associated type must be manually analized
1283 -- since N has already been analyzed. Use the scope of the spec
1284 -- when inserting in a package.
1287 Push_Scope (Spec_Id);
1288 Analyze (Counter_Typ_Decl);
1289 Analyze (Counter_Decl);
1293 Analyze (Counter_Typ_Decl);
1294 Analyze (Counter_Decl);
1297 Finalizer_Decls := New_List;
1298 Jump_Alts := New_List;
1301 -- If the context requires additional clean up, the finalization
1302 -- machinery is added after the clean up code.
1304 if Acts_As_Clean then
1305 Finalizer_Stmts := Clean_Stmts;
1306 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1308 Finalizer_Stmts := New_List;
1311 if Has_Tagged_Types then
1312 Tagged_Type_Stmts := New_List;
1314 end Build_Components;
1316 ----------------------
1317 -- Create_Finalizer --
1318 ----------------------
1320 procedure Create_Finalizer is
1321 Body_Id : Entity_Id;
1324 Jump_Block : Node_Id;
1326 Label_Id : Entity_Id;
1328 function New_Finalizer_Name return Name_Id;
1329 -- Create a fully qualified name of a package spec or body finalizer.
1330 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1332 ------------------------
1333 -- New_Finalizer_Name --
1334 ------------------------
1336 function New_Finalizer_Name return Name_Id is
1337 procedure New_Finalizer_Name (Id : Entity_Id);
1338 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1339 -- has a non-standard scope, process the scope first.
1341 ------------------------
1342 -- New_Finalizer_Name --
1343 ------------------------
1345 procedure New_Finalizer_Name (Id : Entity_Id) is
1347 if Scope (Id) = Standard_Standard then
1348 Get_Name_String (Chars (Id));
1351 New_Finalizer_Name (Scope (Id));
1352 Add_Str_To_Name_Buffer ("__");
1353 Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1355 end New_Finalizer_Name;
1357 -- Start of processing for New_Finalizer_Name
1360 -- Create the fully qualified name of the enclosing scope
1362 New_Finalizer_Name (Spec_Id);
1365 -- __finalize_[spec|body]
1367 Add_Str_To_Name_Buffer ("__finalize_");
1369 if For_Package_Spec then
1370 Add_Str_To_Name_Buffer ("spec");
1372 Add_Str_To_Name_Buffer ("body");
1376 end New_Finalizer_Name;
1378 -- Start of processing for Create_Finalizer
1381 -- Step 1: Creation of the finalizer name
1383 -- Packages must use a distinct name for their finalizers since the
1384 -- binder will have to generate calls to them by name. The name is
1385 -- of the following form:
1387 -- xx__yy__finalize_[spec|body]
1390 Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1391 Set_Has_Qualified_Name (Fin_Id);
1392 Set_Has_Fully_Qualified_Name (Fin_Id);
1394 -- The default name is _finalizer
1398 Make_Defining_Identifier (Loc,
1399 Chars => New_External_Name (Name_uFinalizer));
1402 -- Step 2: Creation of the finalizer specification
1405 -- procedure Fin_Id;
1408 Make_Subprogram_Declaration (Loc,
1410 Make_Procedure_Specification (Loc,
1411 Defining_Unit_Name => Fin_Id));
1413 -- Step 3: Creation of the finalizer body
1415 if Has_Ctrl_Objs then
1417 -- Add L0, the default destination to the jump block
1419 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1420 Set_Entity (Label_Id,
1421 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1422 Label := Make_Label (Loc, Label_Id);
1427 Prepend_To (Finalizer_Decls,
1428 Make_Implicit_Label_Declaration (Loc,
1429 Defining_Identifier => Entity (Label_Id),
1430 Label_Construct => Label));
1436 Append_To (Jump_Alts,
1437 Make_Case_Statement_Alternative (Loc,
1438 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1439 Statements => New_List (
1440 Make_Goto_Statement (Loc,
1441 Name => New_Reference_To (Entity (Label_Id), Loc)))));
1446 Append_To (Finalizer_Stmts, Label);
1448 -- The local exception does not need to be reraised for library-
1449 -- level finalizers. Generate:
1452 -- Raise_From_Controlled_Operation (E, Abort);
1456 and then Exceptions_OK
1458 Append_To (Finalizer_Stmts,
1459 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
1462 -- Create the jump block which controls the finalization flow
1463 -- depending on the value of the state counter.
1466 Make_Case_Statement (Loc,
1467 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
1468 Alternatives => Jump_Alts);
1471 and then Present (Jump_Block_Insert_Nod)
1473 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1475 Prepend_To (Finalizer_Stmts, Jump_Block);
1479 -- Add the library-level tagged type unregistration machinery before
1480 -- the jump block circuitry. This ensures that external tags will be
1481 -- removed even if a finalization exception occurs at some point.
1483 if Has_Tagged_Types then
1484 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1487 -- Add a call to the previous At_End handler if it exists. The call
1488 -- must always precede the jump block.
1490 if Present (Prev_At_End) then
1491 Prepend_To (Finalizer_Stmts,
1492 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1494 -- Clear the At_End handler since we have already generated the
1495 -- proper replacement call for it.
1497 Set_At_End_Proc (HSS, Empty);
1500 -- Release the secondary stack mark
1502 if Present (Mark_Id) then
1503 Append_To (Finalizer_Stmts,
1504 Make_Procedure_Call_Statement (Loc,
1506 New_Reference_To (RTE (RE_SS_Release), Loc),
1507 Parameter_Associations => New_List (
1508 New_Reference_To (Mark_Id, Loc))));
1511 -- Protect the statements with abort defer/undefer. This is only when
1512 -- aborts are allowed and the clean up statements require deferral or
1513 -- there are controlled objects to be finalized.
1517 (Defer_Abort or else Has_Ctrl_Objs)
1519 Prepend_To (Finalizer_Stmts,
1520 Make_Procedure_Call_Statement (Loc,
1521 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc)));
1523 Append_To (Finalizer_Stmts,
1524 Make_Procedure_Call_Statement (Loc,
1525 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
1529 -- procedure Fin_Id is
1530 -- Abort : constant Boolean :=
1531 -- Exception_Occurrence (Get_Current_Excep.all.all) =
1532 -- Standard'Abort_Signal'Identity;
1534 -- Abort : constant Boolean := False; -- no abort
1536 -- E : Exception_Occurrence; -- All added if flag
1537 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1543 -- Abort_Defer; -- Added if abort is allowed
1544 -- <call to Prev_At_End> -- Added if exists
1545 -- <cleanup statements> -- Added if Acts_As_Clean
1546 -- <jump block> -- Added if Has_Ctrl_Objs
1547 -- <finalization statements> -- Added if Has_Ctrl_Objs
1548 -- <stack release> -- Added if Mark_Id exists
1549 -- Abort_Undefer; -- Added if abort is allowed
1553 and then Exceptions_OK
1555 Prepend_List_To (Finalizer_Decls,
1556 Build_Object_Declarations
1557 (Loc, Abort_Id, E_Id, Raised_Id, For_Package));
1560 -- Create the body of the finalizer
1562 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1565 Set_Has_Qualified_Name (Body_Id);
1566 Set_Has_Fully_Qualified_Name (Body_Id);
1570 Make_Subprogram_Body (Loc,
1572 Make_Procedure_Specification (Loc,
1573 Defining_Unit_Name => Body_Id),
1575 Declarations => Finalizer_Decls,
1577 Handled_Statement_Sequence =>
1578 Make_Handled_Sequence_Of_Statements (Loc, Finalizer_Stmts));
1580 -- Step 4: Spec and body insertion, analysis
1584 -- If the package spec has private declarations, the finalizer
1585 -- body must be added to the end of the list in order to have
1586 -- visibility of all private controlled objects.
1588 if For_Package_Spec then
1589 if Present (Priv_Decls) then
1590 Append_To (Priv_Decls, Fin_Spec);
1591 Append_To (Priv_Decls, Fin_Body);
1593 Append_To (Decls, Fin_Spec);
1594 Append_To (Decls, Fin_Body);
1597 -- For package bodies, both the finalizer spec and body are
1598 -- inserted at the end of the package declarations.
1601 Append_To (Decls, Fin_Spec);
1602 Append_To (Decls, Fin_Body);
1605 -- Push the name of the package
1607 Push_Scope (Spec_Id);
1615 -- Create the spec for the finalizer. The At_End handler must be
1616 -- able to call the body which resides in a nested structure.
1620 -- procedure Fin_Id; -- Spec
1622 -- <objects and possibly statements>
1623 -- procedure Fin_Id is ... -- Body
1626 -- Fin_Id; -- At_End handler
1629 pragma Assert (Present (Spec_Decls));
1631 Append_To (Spec_Decls, Fin_Spec);
1634 -- When the finalizer acts solely as a clean up routine, the body
1635 -- is inserted right after the spec.
1638 and then not Has_Ctrl_Objs
1640 Insert_After (Fin_Spec, Fin_Body);
1642 -- In all other cases the body is inserted after either:
1644 -- 1) The counter update statement of the last controlled object
1645 -- 2) The last top level nested controlled package
1646 -- 3) The last top level controlled instantiation
1649 -- Manually freeze the spec. This is somewhat of a hack because
1650 -- a subprogram is frozen when its body is seen and the freeze
1651 -- node appears right before the body. However, in this case,
1652 -- the spec must be frozen earlier since the At_End handler
1653 -- must be able to call it.
1656 -- procedure Fin_Id; -- Spec
1657 -- [Fin_Id] -- Freeze node
1661 -- Fin_Id; -- At_End handler
1664 Ensure_Freeze_Node (Fin_Id);
1665 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1666 Set_Is_Frozen (Fin_Id);
1668 -- In the case where the last construct to contain a controlled
1669 -- object is either a nested package, an instantiation or a
1670 -- freeze node, the body must be inserted directly after the
1673 if Nkind_In (Last_Top_Level_Ctrl_Construct,
1675 N_Package_Declaration,
1678 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1681 Insert_After (Finalizer_Insert_Nod, Fin_Body);
1686 end Create_Finalizer;
1688 --------------------------
1689 -- Process_Declarations --
1690 --------------------------
1692 procedure Process_Declarations
1694 Preprocess : Boolean := False;
1695 Top_Level : Boolean := False)
1700 Obj_Typ : Entity_Id;
1701 Pack_Id : Entity_Id;
1705 Old_Counter_Val : Int;
1706 -- This variable is used to determine whether a nested package or
1707 -- instance contains at least one controlled object.
1709 procedure Processing_Actions
1710 (Has_No_Init : Boolean := False;
1711 Is_Protected : Boolean := False);
1712 -- Depending on the mode of operation of Process_Declarations, either
1713 -- increment the controlled object counter, set the controlled object
1714 -- flag and store the last top level construct or process the current
1715 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1716 -- the current declaration may not have initialization proc(s). Flag
1717 -- Is_Protected should be set when the current declaration denotes a
1718 -- simple protected object.
1720 ------------------------
1721 -- Processing_Actions --
1722 ------------------------
1724 procedure Processing_Actions
1725 (Has_No_Init : Boolean := False;
1726 Is_Protected : Boolean := False)
1729 -- Library-level tagged type
1731 if Nkind (Decl) = N_Full_Type_Declaration then
1733 Has_Tagged_Types := True;
1736 and then No (Last_Top_Level_Ctrl_Construct)
1738 Last_Top_Level_Ctrl_Construct := Decl;
1742 Process_Tagged_Type_Declaration (Decl);
1745 -- Controlled object declaration
1749 Counter_Val := Counter_Val + 1;
1750 Has_Ctrl_Objs := True;
1753 and then No (Last_Top_Level_Ctrl_Construct)
1755 Last_Top_Level_Ctrl_Construct := Decl;
1759 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
1762 end Processing_Actions;
1764 -- Start of processing for Process_Declarations
1767 if No (Decls) or else Is_Empty_List (Decls) then
1771 -- Process all declarations in reverse order
1773 Decl := Last_Non_Pragma (Decls);
1774 while Present (Decl) loop
1776 -- Library-level tagged types
1778 if Nkind (Decl) = N_Full_Type_Declaration then
1779 Typ := Defining_Identifier (Decl);
1781 if Is_Tagged_Type (Typ)
1782 and then Is_Library_Level_Entity (Typ)
1783 and then Convention (Typ) = Convention_Ada
1784 and then Present (Access_Disp_Table (Typ))
1785 and then RTE_Available (RE_Register_Tag)
1786 and then not No_Run_Time_Mode
1787 and then not Is_Abstract_Type (Typ)
1792 -- Regular object declarations
1794 elsif Nkind (Decl) = N_Object_Declaration then
1795 Obj_Id := Defining_Identifier (Decl);
1796 Obj_Typ := Base_Type (Etype (Obj_Id));
1797 Expr := Expression (Decl);
1799 -- Bypass any form of processing for objects which have their
1800 -- finalization disabled. This applies only to objects at the
1804 and then Finalize_Storage_Only (Obj_Typ)
1808 -- Transient variables are treated separately in order to
1809 -- minimize the size of the generated code. See Process_
1810 -- Transient_Objects.
1812 elsif Is_Processed_Transient (Obj_Id) then
1815 -- The object is of the form:
1816 -- Obj : Typ [:= Expr];
1818 -- Do not process the incomplete view of a deferred constant.
1819 -- Do not consider tag-to-class-wide conversions.
1821 elsif not Is_Imported (Obj_Id)
1822 and then Needs_Finalization (Obj_Typ)
1823 and then not (Ekind (Obj_Id) = E_Constant
1824 and then not Has_Completion (Obj_Id))
1825 and then not Is_Tag_To_CW_Conversion (Obj_Id)
1829 -- The object is of the form:
1830 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1832 -- Obj : Access_Typ :=
1833 -- BIP_Function_Call
1834 -- (..., BIPaccess => null, ...)'reference;
1836 elsif Is_Access_Type (Obj_Typ)
1837 and then Needs_Finalization
1838 (Available_View (Designated_Type (Obj_Typ)))
1839 and then Present (Expr)
1841 (Is_Null_Access_BIP_Func_Call (Expr)
1842 or else (Is_Non_BIP_Func_Call (Expr)
1844 Is_Related_To_Func_Return (Obj_Id)))
1846 Processing_Actions (Has_No_Init => True);
1848 -- Processing for "hook" objects generated for controlled
1849 -- transients declared inside an Expression_With_Actions.
1851 elsif Is_Access_Type (Obj_Typ)
1852 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1853 and then Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
1854 N_Object_Declaration
1855 and then Is_Finalizable_Transient
1856 (Return_Flag_Or_Transient_Decl (Obj_Id), Decl)
1858 Processing_Actions (Has_No_Init => True);
1860 -- Simple protected objects which use type System.Tasking.
1861 -- Protected_Objects.Protection to manage their locks should
1862 -- be treated as controlled since they require manual cleanup.
1863 -- The only exception is illustrated in the following example:
1866 -- type Ctrl is new Controlled ...
1867 -- procedure Finalize (Obj : in out Ctrl);
1871 -- package body Pkg is
1872 -- protected Prot is
1873 -- procedure Do_Something (Obj : in out Ctrl);
1876 -- protected body Prot is
1877 -- procedure Do_Something (Obj : in out Ctrl) is ...
1880 -- procedure Finalize (Obj : in out Ctrl) is
1882 -- Prot.Do_Something (Obj);
1886 -- Since for the most part entities in package bodies depend on
1887 -- those in package specs, Prot's lock should be cleaned up
1888 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1889 -- This act however attempts to invoke Do_Something and fails
1890 -- because the lock has disappeared.
1892 elsif Ekind (Obj_Id) = E_Variable
1893 and then not In_Library_Level_Package_Body (Obj_Id)
1895 (Is_Simple_Protected_Type (Obj_Typ)
1896 or else Has_Simple_Protected_Object (Obj_Typ))
1898 Processing_Actions (Is_Protected => True);
1901 -- Specific cases of object renamings
1903 elsif Nkind (Decl) = N_Object_Renaming_Declaration
1904 and then Nkind (Name (Decl)) = N_Explicit_Dereference
1905 and then Nkind (Prefix (Name (Decl))) = N_Identifier
1907 Obj_Id := Defining_Identifier (Decl);
1908 Obj_Typ := Base_Type (Etype (Obj_Id));
1910 -- Bypass any form of processing for objects which have their
1911 -- finalization disabled. This applies only to objects at the
1915 and then Finalize_Storage_Only (Obj_Typ)
1919 -- Return object of a build-in-place function. This case is
1920 -- recognized and marked by the expansion of an extended return
1921 -- statement (see Expand_N_Extended_Return_Statement).
1923 elsif Needs_Finalization (Obj_Typ)
1924 and then Is_Return_Object (Obj_Id)
1925 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1927 Processing_Actions (Has_No_Init => True);
1930 -- Inspect the freeze node of an access-to-controlled type and
1931 -- look for a delayed finalization master. This case arises when
1932 -- the freeze actions are inserted at a later time than the
1933 -- expansion of the context. Since Build_Finalizer is never called
1934 -- on a single construct twice, the master will be ultimately
1935 -- left out and never finalized. This is also needed for freeze
1936 -- actions of designated types themselves, since in some cases the
1937 -- finalization master is associated with a designated type's
1938 -- freeze node rather than that of the access type (see handling
1939 -- for freeze actions in Build_Finalization_Master).
1941 elsif Nkind (Decl) = N_Freeze_Entity
1942 and then Present (Actions (Decl))
1944 Typ := Entity (Decl);
1946 if (Is_Access_Type (Typ)
1947 and then not Is_Access_Subprogram_Type (Typ)
1948 and then Needs_Finalization
1949 (Available_View (Designated_Type (Typ))))
1950 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
1952 Old_Counter_Val := Counter_Val;
1954 -- Freeze nodes are considered to be identical to packages
1955 -- and blocks in terms of nesting. The difference is that
1956 -- a finalization master created inside the freeze node is
1957 -- at the same nesting level as the node itself.
1959 Process_Declarations (Actions (Decl), Preprocess);
1961 -- The freeze node contains a finalization master
1965 and then No (Last_Top_Level_Ctrl_Construct)
1966 and then Counter_Val > Old_Counter_Val
1968 Last_Top_Level_Ctrl_Construct := Decl;
1972 -- Nested package declarations, avoid generics
1974 elsif Nkind (Decl) = N_Package_Declaration then
1975 Spec := Specification (Decl);
1976 Pack_Id := Defining_Unit_Name (Spec);
1978 if Nkind (Pack_Id) = N_Defining_Program_Unit_Name then
1979 Pack_Id := Defining_Identifier (Pack_Id);
1982 if Ekind (Pack_Id) /= E_Generic_Package then
1983 Old_Counter_Val := Counter_Val;
1984 Process_Declarations
1985 (Private_Declarations (Spec), Preprocess);
1986 Process_Declarations
1987 (Visible_Declarations (Spec), Preprocess);
1989 -- Either the visible or the private declarations contain a
1990 -- controlled object. The nested package declaration is the
1991 -- last such construct.
1995 and then No (Last_Top_Level_Ctrl_Construct)
1996 and then Counter_Val > Old_Counter_Val
1998 Last_Top_Level_Ctrl_Construct := Decl;
2002 -- Nested package bodies, avoid generics
2004 elsif Nkind (Decl) = N_Package_Body then
2005 Spec := Corresponding_Spec (Decl);
2007 if Ekind (Spec) /= E_Generic_Package then
2008 Old_Counter_Val := Counter_Val;
2009 Process_Declarations (Declarations (Decl), Preprocess);
2011 -- The nested package body is the last construct to contain
2012 -- a controlled object.
2016 and then No (Last_Top_Level_Ctrl_Construct)
2017 and then Counter_Val > Old_Counter_Val
2019 Last_Top_Level_Ctrl_Construct := Decl;
2023 -- Handle a rare case caused by a controlled transient variable
2024 -- created as part of a record init proc. The variable is wrapped
2025 -- in a block, but the block is not associated with a transient
2028 elsif Nkind (Decl) = N_Block_Statement
2029 and then Inside_Init_Proc
2031 Old_Counter_Val := Counter_Val;
2033 if Present (Handled_Statement_Sequence (Decl)) then
2034 Process_Declarations
2035 (Statements (Handled_Statement_Sequence (Decl)),
2039 Process_Declarations (Declarations (Decl), Preprocess);
2041 -- Either the declaration or statement list of the block has a
2042 -- controlled object.
2046 and then No (Last_Top_Level_Ctrl_Construct)
2047 and then Counter_Val > Old_Counter_Val
2049 Last_Top_Level_Ctrl_Construct := Decl;
2053 Prev_Non_Pragma (Decl);
2055 end Process_Declarations;
2057 --------------------------------
2058 -- Process_Object_Declaration --
2059 --------------------------------
2061 procedure Process_Object_Declaration
2063 Has_No_Init : Boolean := False;
2064 Is_Protected : Boolean := False)
2066 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2067 Loc : constant Source_Ptr := Sloc (Decl);
2069 Count_Ins : Node_Id;
2071 Fin_Stmts : List_Id;
2074 Label_Id : Entity_Id;
2076 Obj_Typ : Entity_Id;
2078 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2079 -- Once it has been established that the current object is in fact a
2080 -- return object of build-in-place function Func_Id, generate the
2081 -- following cleanup code:
2083 -- if BIPallocfrom > Secondary_Stack'Pos
2084 -- and then BIPfinalizationmaster /= null
2087 -- type Ptr_Typ is access Obj_Typ;
2088 -- for Ptr_Typ'Storage_Pool
2089 -- use Base_Pool (BIPfinalizationmaster);
2092 -- Free (Ptr_Typ (Temp));
2096 -- Obj_Typ is the type of the current object, Temp is the original
2097 -- allocation which Obj_Id renames.
2099 procedure Find_Last_Init
2102 Last_Init : out Node_Id;
2103 Body_Insert : out Node_Id);
2104 -- An object declaration has at least one and at most two init calls:
2105 -- that of the type and the user-defined initialize. Given an object
2106 -- declaration, Last_Init denotes the last initialization call which
2107 -- follows the declaration. Body_Insert denotes the place where the
2108 -- finalizer body could be potentially inserted.
2110 -----------------------------
2111 -- Build_BIP_Cleanup_Stmts --
2112 -----------------------------
2114 function Build_BIP_Cleanup_Stmts
2115 (Func_Id : Entity_Id) return Node_Id
2117 Decls : constant List_Id := New_List;
2118 Fin_Mas_Id : constant Entity_Id :=
2119 Build_In_Place_Formal
2120 (Func_Id, BIP_Finalization_Master);
2121 Obj_Typ : constant Entity_Id := Etype (Func_Id);
2122 Temp_Id : constant Entity_Id :=
2123 Entity (Prefix (Name (Parent (Obj_Id))));
2127 Free_Stmt : Node_Id;
2128 Pool_Id : Entity_Id;
2129 Ptr_Typ : Entity_Id;
2133 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2135 Pool_Id := Make_Temporary (Loc, 'P');
2138 Make_Object_Renaming_Declaration (Loc,
2139 Defining_Identifier => Pool_Id,
2141 New_Reference_To (RTE (RE_Root_Storage_Pool), Loc),
2143 Make_Explicit_Dereference (Loc,
2145 Make_Function_Call (Loc,
2147 New_Reference_To (RTE (RE_Base_Pool), Loc),
2148 Parameter_Associations => New_List (
2149 Make_Explicit_Dereference (Loc,
2150 Prefix => New_Reference_To (Fin_Mas_Id, Loc)))))));
2152 -- Create an access type which uses the storage pool of the
2153 -- caller's finalization master.
2156 -- type Ptr_Typ is access Obj_Typ;
2158 Ptr_Typ := Make_Temporary (Loc, 'P');
2161 Make_Full_Type_Declaration (Loc,
2162 Defining_Identifier => Ptr_Typ,
2164 Make_Access_To_Object_Definition (Loc,
2165 Subtype_Indication => New_Reference_To (Obj_Typ, Loc))));
2167 -- Perform minor decoration in order to set the master and the
2168 -- storage pool attributes.
2170 Set_Ekind (Ptr_Typ, E_Access_Type);
2171 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
2172 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2174 -- Create an explicit free statement. Note that the free uses the
2175 -- caller's pool expressed as a renaming.
2178 Make_Free_Statement (Loc,
2180 Unchecked_Convert_To (Ptr_Typ,
2181 New_Reference_To (Temp_Id, Loc)));
2183 Set_Storage_Pool (Free_Stmt, Pool_Id);
2185 -- Create a block to house the dummy type and the instantiation as
2186 -- well as to perform the cleanup the temporary.
2192 -- Free (Ptr_Typ (Temp_Id));
2196 Make_Block_Statement (Loc,
2197 Declarations => Decls,
2198 Handled_Statement_Sequence =>
2199 Make_Handled_Sequence_Of_Statements (Loc,
2200 Statements => New_List (Free_Stmt)));
2203 -- if BIPfinalizationmaster /= null then
2207 Left_Opnd => New_Reference_To (Fin_Mas_Id, Loc),
2208 Right_Opnd => Make_Null (Loc));
2210 -- For constrained or tagged results escalate the condition to
2211 -- include the allocation format. Generate:
2213 -- if BIPallocform > Secondary_Stack'Pos
2214 -- and then BIPfinalizationmaster /= null
2217 if not Is_Constrained (Obj_Typ)
2218 or else Is_Tagged_Type (Obj_Typ)
2221 Alloc : constant Entity_Id :=
2222 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2228 Left_Opnd => New_Reference_To (Alloc, Loc),
2230 Make_Integer_Literal (Loc,
2232 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2234 Right_Opnd => Cond);
2244 Make_If_Statement (Loc,
2246 Then_Statements => New_List (Free_Blk));
2247 end Build_BIP_Cleanup_Stmts;
2249 --------------------
2250 -- Find_Last_Init --
2251 --------------------
2253 procedure Find_Last_Init
2256 Last_Init : out Node_Id;
2257 Body_Insert : out Node_Id)
2259 Nod_1 : Node_Id := Empty;
2260 Nod_2 : Node_Id := Empty;
2263 function Is_Init_Call
2265 Typ : Entity_Id) return Boolean;
2266 -- Given an arbitrary node, determine whether N is a procedure
2267 -- call and if it is, try to match the name of the call with the
2268 -- [Deep_]Initialize proc of Typ.
2270 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
2271 -- Given a statement which is part of a list, return the next
2272 -- real statement while skipping over dynamic elab checks.
2278 function Is_Init_Call
2280 Typ : Entity_Id) return Boolean
2283 -- A call to [Deep_]Initialize is always direct
2285 if Nkind (N) = N_Procedure_Call_Statement
2286 and then Nkind (Name (N)) = N_Identifier
2289 Call_Ent : constant Entity_Id := Entity (Name (N));
2290 Deep_Init : constant Entity_Id :=
2291 TSS (Typ, TSS_Deep_Initialize);
2292 Init : Entity_Id := Empty;
2295 -- A type may have controlled components but not be
2298 if Is_Controlled (Typ) then
2299 Init := Find_Prim_Op (Typ, Name_Initialize);
2303 (Present (Deep_Init)
2304 and then Call_Ent = Deep_Init)
2307 and then Call_Ent = Init);
2314 -----------------------------
2315 -- Next_Suitable_Statement --
2316 -----------------------------
2318 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
2319 Result : Node_Id := Next (Stmt);
2322 -- Skip over access-before-elaboration checks
2324 if Dynamic_Elaboration_Checks
2325 and then Nkind (Result) = N_Raise_Program_Error
2327 Result := Next (Result);
2331 end Next_Suitable_Statement;
2333 -- Start of processing for Find_Last_Init
2337 Body_Insert := Empty;
2339 -- Object renamings and objects associated with controlled
2340 -- function results do not have initialization calls.
2346 if Is_Concurrent_Type (Typ) then
2347 Utyp := Corresponding_Record_Type (Typ);
2352 -- The init procedures are arranged as follows:
2354 -- Object : Controlled_Type;
2355 -- Controlled_TypeIP (Object);
2356 -- [[Deep_]Initialize (Object);]
2358 -- where the user-defined initialize may be optional or may appear
2359 -- inside a block when abort deferral is needed.
2361 Nod_1 := Next_Suitable_Statement (Decl);
2362 if Present (Nod_1) then
2363 Nod_2 := Next_Suitable_Statement (Nod_1);
2365 -- The statement following an object declaration is always a
2366 -- call to the type init proc.
2371 -- Optional user-defined init or deep init processing
2373 if Present (Nod_2) then
2375 -- The statement following the type init proc may be a block
2376 -- statement in cases where abort deferral is required.
2378 if Nkind (Nod_2) = N_Block_Statement then
2380 HSS : constant Node_Id :=
2381 Handled_Statement_Sequence (Nod_2);
2386 and then Present (Statements (HSS))
2388 Stmt := First (Statements (HSS));
2390 -- Examine individual block statements and locate the
2391 -- call to [Deep_]Initialze.
2393 while Present (Stmt) loop
2394 if Is_Init_Call (Stmt, Utyp) then
2396 Body_Insert := Nod_2;
2406 elsif Is_Init_Call (Nod_2, Utyp) then
2412 -- Start of processing for Process_Object_Declaration
2415 Obj_Ref := New_Reference_To (Obj_Id, Loc);
2416 Obj_Typ := Base_Type (Etype (Obj_Id));
2418 -- Handle access types
2420 if Is_Access_Type (Obj_Typ) then
2421 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2422 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2425 Set_Etype (Obj_Ref, Obj_Typ);
2427 -- Set a new value for the state counter and insert the statement
2428 -- after the object declaration. Generate:
2430 -- Counter := <value>;
2433 Make_Assignment_Statement (Loc,
2434 Name => New_Reference_To (Counter_Id, Loc),
2435 Expression => Make_Integer_Literal (Loc, Counter_Val));
2437 -- Insert the counter after all initialization has been done. The
2438 -- place of insertion depends on the context. When dealing with a
2439 -- controlled function, the counter is inserted directly after the
2440 -- declaration because such objects lack init calls.
2442 Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
2444 Insert_After (Count_Ins, Inc_Decl);
2447 -- If the current declaration is the last in the list, the finalizer
2448 -- body needs to be inserted after the set counter statement for the
2449 -- current object declaration. This is complicated by the fact that
2450 -- the set counter statement may appear in abort deferred block. In
2451 -- that case, the proper insertion place is after the block.
2453 if No (Finalizer_Insert_Nod) then
2455 -- Insertion after an abort deffered block
2457 if Present (Body_Ins) then
2458 Finalizer_Insert_Nod := Body_Ins;
2460 Finalizer_Insert_Nod := Inc_Decl;
2464 -- Create the associated label with this object, generate:
2466 -- L<counter> : label;
2469 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2470 Set_Entity (Label_Id,
2471 Make_Defining_Identifier (Loc, Chars (Label_Id)));
2472 Label := Make_Label (Loc, Label_Id);
2474 Prepend_To (Finalizer_Decls,
2475 Make_Implicit_Label_Declaration (Loc,
2476 Defining_Identifier => Entity (Label_Id),
2477 Label_Construct => Label));
2479 -- Create the associated jump with this object, generate:
2481 -- when <counter> =>
2484 Prepend_To (Jump_Alts,
2485 Make_Case_Statement_Alternative (Loc,
2486 Discrete_Choices => New_List (
2487 Make_Integer_Literal (Loc, Counter_Val)),
2488 Statements => New_List (
2489 Make_Goto_Statement (Loc,
2490 Name => New_Reference_To (Entity (Label_Id), Loc)))));
2492 -- Insert the jump destination, generate:
2496 Append_To (Finalizer_Stmts, Label);
2498 -- Processing for simple protected objects. Such objects require
2499 -- manual finalization of their lock managers.
2501 if Is_Protected then
2502 Fin_Stmts := No_List;
2504 if Is_Simple_Protected_Type (Obj_Typ) then
2505 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
2506 if Present (Fin_Call) then
2507 Fin_Stmts := New_List (Fin_Call);
2510 elsif Has_Simple_Protected_Object (Obj_Typ) then
2511 if Is_Record_Type (Obj_Typ) then
2512 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2514 elsif Is_Array_Type (Obj_Typ) then
2515 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2521 -- System.Tasking.Protected_Objects.Finalize_Protection
2529 if Present (Fin_Stmts) then
2530 Append_To (Finalizer_Stmts,
2531 Make_Block_Statement (Loc,
2532 Handled_Statement_Sequence =>
2533 Make_Handled_Sequence_Of_Statements (Loc,
2534 Statements => Fin_Stmts,
2536 Exception_Handlers => New_List (
2537 Make_Exception_Handler (Loc,
2538 Exception_Choices => New_List (
2539 Make_Others_Choice (Loc)),
2541 Statements => New_List (
2542 Make_Null_Statement (Loc)))))));
2545 -- Processing for regular controlled objects
2549 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2551 -- begin -- Exception handlers allowed
2552 -- [Deep_]Finalize (Obj);
2555 -- when Id : others =>
2556 -- if not Raised then
2558 -- Save_Occurrence (E, Id);
2567 if Exceptions_OK then
2568 Fin_Stmts := New_List (
2569 Make_Block_Statement (Loc,
2570 Handled_Statement_Sequence =>
2571 Make_Handled_Sequence_Of_Statements (Loc,
2572 Statements => New_List (Fin_Call),
2574 Exception_Handlers => New_List (
2575 Build_Exception_Handler
2576 (Loc, E_Id, Raised_Id, For_Package)))));
2578 -- When exception handlers are prohibited, the finalization call
2579 -- appears unprotected. Any exception raised during finalization
2580 -- will bypass the circuitry which ensures the cleanup of all
2581 -- remaining objects.
2584 Fin_Stmts := New_List (Fin_Call);
2587 -- If we are dealing with a return object of a build-in-place
2588 -- function, generate the following cleanup statements:
2590 -- if BIPallocfrom > Secondary_Stack'Pos
2591 -- and then BIPfinalizationmaster /= null
2594 -- type Ptr_Typ is access Obj_Typ;
2595 -- for Ptr_Typ'Storage_Pool use
2596 -- Base_Pool (BIPfinalizationmaster.all).all;
2599 -- Free (Ptr_Typ (Temp));
2603 -- The generated code effectively detaches the temporary from the
2604 -- caller finalization master and deallocates the object. This is
2605 -- disabled on .NET/JVM because pools are not supported.
2607 if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2609 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2611 if Is_Build_In_Place_Function (Func_Id)
2612 and then Needs_BIP_Finalization_Master (Func_Id)
2614 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2619 if Ekind_In (Obj_Id, E_Constant, E_Variable)
2620 and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
2622 -- Return objects use a flag to aid their potential
2623 -- finalization when the enclosing function fails to return
2624 -- properly. Generate:
2627 -- <object finalization statements>
2630 if Is_Return_Object (Obj_Id) then
2631 Fin_Stmts := New_List (
2632 Make_If_Statement (Loc,
2637 (Return_Flag_Or_Transient_Decl (Obj_Id), Loc)),
2639 Then_Statements => Fin_Stmts));
2641 -- Temporaries created for the purpose of "exporting" a
2642 -- controlled transient out of an Expression_With_Actions (EWA)
2643 -- need guards. The following illustrates the usage of such
2646 -- Access_Typ : access [all] Obj_Typ;
2647 -- Temp : Access_Typ := null;
2648 -- <Counter> := ...;
2651 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2652 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2654 -- Temp := Ctrl_Trans'Unchecked_Access;
2657 -- The finalization machinery does not process EWA nodes as
2658 -- this may lead to premature finalization of expressions. Note
2659 -- that Temp is marked as being properly initialized regardless
2660 -- of whether the initialization of Ctrl_Trans succeeded. Since
2661 -- a failed initialization may leave Temp with a value of null,
2662 -- add a guard to handle this case:
2664 -- if Obj /= null then
2665 -- <object finalization statements>
2670 (Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
2671 N_Object_Declaration);
2673 Fin_Stmts := New_List (
2674 Make_If_Statement (Loc,
2677 Left_Opnd => New_Reference_To (Obj_Id, Loc),
2678 Right_Opnd => Make_Null (Loc)),
2680 Then_Statements => Fin_Stmts));
2685 Append_List_To (Finalizer_Stmts, Fin_Stmts);
2687 -- Since the declarations are examined in reverse, the state counter
2688 -- must be decremented in order to keep with the true position of
2691 Counter_Val := Counter_Val - 1;
2692 end Process_Object_Declaration;
2694 -------------------------------------
2695 -- Process_Tagged_Type_Declaration --
2696 -------------------------------------
2698 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2699 Typ : constant Entity_Id := Defining_Identifier (Decl);
2700 DT_Ptr : constant Entity_Id :=
2701 Node (First_Elmt (Access_Disp_Table (Typ)));
2704 -- Ada.Tags.Unregister_Tag (<Typ>P);
2706 Append_To (Tagged_Type_Stmts,
2707 Make_Procedure_Call_Statement (Loc,
2709 New_Reference_To (RTE (RE_Unregister_Tag), Loc),
2710 Parameter_Associations => New_List (
2711 New_Reference_To (DT_Ptr, Loc))));
2712 end Process_Tagged_Type_Declaration;
2714 -- Start of processing for Build_Finalizer
2719 -- Step 1: Extract all lists which may contain controlled objects or
2720 -- library-level tagged types.
2722 if For_Package_Spec then
2723 Decls := Visible_Declarations (Specification (N));
2724 Priv_Decls := Private_Declarations (Specification (N));
2726 -- Retrieve the package spec id
2728 Spec_Id := Defining_Unit_Name (Specification (N));
2730 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2731 Spec_Id := Defining_Identifier (Spec_Id);
2734 -- Accept statement, block, entry body, package body, protected body,
2735 -- subprogram body or task body.
2738 Decls := Declarations (N);
2739 HSS := Handled_Statement_Sequence (N);
2741 if Present (HSS) then
2742 if Present (Statements (HSS)) then
2743 Stmts := Statements (HSS);
2746 if Present (At_End_Proc (HSS)) then
2747 Prev_At_End := At_End_Proc (HSS);
2751 -- Retrieve the package spec id for package bodies
2753 if For_Package_Body then
2754 Spec_Id := Corresponding_Spec (N);
2758 -- Do not process nested packages since those are handled by the
2759 -- enclosing scope's finalizer. Do not process non-expanded package
2760 -- instantiations since those will be re-analyzed and re-expanded.
2764 (not Is_Library_Level_Entity (Spec_Id)
2766 -- Nested packages are considered to be library level entities,
2767 -- but do not need to be processed separately. True library level
2768 -- packages have a scope value of 1.
2770 or else Scope_Depth_Value (Spec_Id) /= Uint_1
2771 or else (Is_Generic_Instance (Spec_Id)
2772 and then Package_Instantiation (Spec_Id) /= N))
2777 -- Step 2: Object [pre]processing
2781 -- Preprocess the visible declarations now in order to obtain the
2782 -- correct number of controlled object by the time the private
2783 -- declarations are processed.
2785 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2787 -- From all the possible contexts, only package specifications may
2788 -- have private declarations.
2790 if For_Package_Spec then
2791 Process_Declarations
2792 (Priv_Decls, Preprocess => True, Top_Level => True);
2795 -- The current context may lack controlled objects, but require some
2796 -- other form of completion (task termination for instance). In such
2797 -- cases, the finalizer must be created and carry the additional
2800 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2804 -- The preprocessing has determined that the context has controlled
2805 -- objects or library-level tagged types.
2807 if Has_Ctrl_Objs or Has_Tagged_Types then
2809 -- Private declarations are processed first in order to preserve
2810 -- possible dependencies between public and private objects.
2812 if For_Package_Spec then
2813 Process_Declarations (Priv_Decls);
2816 Process_Declarations (Decls);
2822 -- Preprocess both declarations and statements
2824 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2825 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
2827 -- At this point it is known that N has controlled objects. Ensure
2828 -- that N has a declarative list since the finalizer spec will be
2831 if Has_Ctrl_Objs and then No (Decls) then
2832 Set_Declarations (N, New_List);
2833 Decls := Declarations (N);
2834 Spec_Decls := Decls;
2837 -- The current context may lack controlled objects, but require some
2838 -- other form of completion (task termination for instance). In such
2839 -- cases, the finalizer must be created and carry the additional
2842 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2846 if Has_Ctrl_Objs or Has_Tagged_Types then
2847 Process_Declarations (Stmts);
2848 Process_Declarations (Decls);
2852 -- Step 3: Finalizer creation
2854 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2857 end Build_Finalizer;
2859 --------------------------
2860 -- Build_Finalizer_Call --
2861 --------------------------
2863 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
2864 Loc : constant Source_Ptr := Sloc (N);
2865 HSS : Node_Id := Handled_Statement_Sequence (N);
2867 Is_Prot_Body : constant Boolean :=
2868 Nkind (N) = N_Subprogram_Body
2869 and then Is_Protected_Subprogram_Body (N);
2870 -- Determine whether N denotes the protected version of a subprogram
2871 -- which belongs to a protected type.
2874 -- The At_End handler should have been assimilated by the finalizer
2876 pragma Assert (No (At_End_Proc (HSS)));
2878 -- If the construct to be cleaned up is a protected subprogram body, the
2879 -- finalizer call needs to be associated with the block which wraps the
2880 -- unprotected version of the subprogram. The following illustrates this
2883 -- procedure Prot_SubpP is
2884 -- procedure finalizer is
2886 -- Service_Entries (Prot_Obj);
2893 -- Prot_SubpN (Prot_Obj);
2899 if Is_Prot_Body then
2900 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
2902 -- An At_End handler and regular exception handlers cannot coexist in
2903 -- the same statement sequence. Wrap the original statements in a block.
2905 elsif Present (Exception_Handlers (HSS)) then
2907 End_Lab : constant Node_Id := End_Label (HSS);
2912 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
2914 Set_Handled_Statement_Sequence (N,
2915 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
2917 HSS := Handled_Statement_Sequence (N);
2918 Set_End_Label (HSS, End_Lab);
2922 Set_At_End_Proc (HSS, New_Reference_To (Fin_Id, Loc));
2924 Analyze (At_End_Proc (HSS));
2925 Expand_At_End_Handler (HSS, Empty);
2926 end Build_Finalizer_Call;
2928 ---------------------
2929 -- Build_Late_Proc --
2930 ---------------------
2932 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
2934 for Final_Prim in Name_Of'Range loop
2935 if Name_Of (Final_Prim) = Nam then
2938 (Prim => Final_Prim,
2940 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
2943 end Build_Late_Proc;
2945 -------------------------------
2946 -- Build_Object_Declarations --
2947 -------------------------------
2949 function Build_Object_Declarations
2951 Abort_Id : Entity_Id;
2953 Raised_Id : Entity_Id;
2954 For_Package : Boolean := False) return List_Id
2961 if Restriction_Active (No_Exception_Propagation) then
2965 pragma Assert (Present (Abort_Id));
2966 pragma Assert (Present (E_Id));
2967 pragma Assert (Present (Raised_Id));
2971 -- In certain scenarios, finalization can be triggered by an abort. If
2972 -- the finalization itself fails and raises an exception, the resulting
2973 -- Program_Error must be supressed and replaced by an abort signal. In
2974 -- order to detect this scenario, save the state of entry into the
2975 -- finalization code.
2977 -- No need to do this for VM case, since VM version of Ada.Exceptions
2978 -- does not include routine Raise_From_Controlled_Operation which is the
2979 -- the sole user of flag Abort.
2981 -- This is not needed for library-level finalizers as they are called
2982 -- by the environment task and cannot be aborted.
2985 and then VM_Target = No_VM
2986 and then not For_Package
2989 Temp_Id : constant Entity_Id := Make_Temporary (Loc, 'E');
2993 -- Temp : constant Exception_Occurrence_Access :=
2994 -- Get_Current_Excep.all;
2997 Make_Object_Declaration (Loc,
2998 Defining_Identifier => Temp_Id,
2999 Constant_Present => True,
3000 Object_Definition =>
3001 New_Reference_To (RTE (RE_Exception_Occurrence_Access), Loc),
3003 Make_Function_Call (Loc,
3005 Make_Explicit_Dereference (Loc,
3008 (RTE (RE_Get_Current_Excep), Loc)))));
3012 -- and then Exception_Identity (Temp.all) =
3013 -- Standard'Abort_Signal'Identity;
3019 Left_Opnd => New_Reference_To (Temp_Id, Loc),
3020 Right_Opnd => Make_Null (Loc)),
3025 Make_Function_Call (Loc,
3027 New_Reference_To (RTE (RE_Exception_Identity), Loc),
3028 Parameter_Associations => New_List (
3029 Make_Explicit_Dereference (Loc,
3030 Prefix => New_Reference_To (Temp_Id, Loc)))),
3033 Make_Attribute_Reference (Loc,
3035 New_Reference_To (Stand.Abort_Signal, Loc),
3036 Attribute_Name => Name_Identity)));
3039 -- No abort or .NET/JVM
3042 A_Expr := New_Reference_To (Standard_False, Loc);
3046 -- Abort_Id : constant Boolean := <A_Expr>;
3049 Make_Object_Declaration (Loc,
3050 Defining_Identifier => Abort_Id,
3051 Constant_Present => True,
3052 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3053 Expression => A_Expr));
3056 -- E_Id : Exception_Occurrence;
3059 Make_Object_Declaration (Loc,
3060 Defining_Identifier => E_Id,
3061 Object_Definition =>
3062 New_Reference_To (RTE (RE_Exception_Occurrence), Loc));
3063 Set_No_Initialization (E_Decl);
3065 Append_To (Result, E_Decl);
3068 -- Raised_Id : Boolean := False;
3071 Make_Object_Declaration (Loc,
3072 Defining_Identifier => Raised_Id,
3073 Object_Definition => New_Reference_To (Standard_Boolean, Loc),
3074 Expression => New_Reference_To (Standard_False, Loc)));
3077 end Build_Object_Declarations;
3079 ---------------------------
3080 -- Build_Raise_Statement --
3081 ---------------------------
3083 function Build_Raise_Statement
3085 Abort_Id : Entity_Id;
3087 Raised_Id : Entity_Id) return Node_Id
3090 Proc_Id : Entity_Id;
3093 -- The default parameter is the local exception occurrence
3095 Params := New_List (New_Reference_To (E_Id, Loc));
3097 -- Standard run-time, .NET/JVM targets, this case handles finalization
3098 -- exceptions raised during an abort.
3100 if RTE_Available (RE_Raise_From_Controlled_Operation) then
3101 Proc_Id := RTE (RE_Raise_From_Controlled_Operation);
3102 Append_To (Params, New_Reference_To (Abort_Id, Loc));
3104 -- Restricted runtime: exception messages are not supported and hence
3105 -- Raise_From_Controlled_Operation is not supported.
3108 Proc_Id := RTE (RE_Reraise_Occurrence);
3112 -- if Raised_Id then
3113 -- <Proc_Id> (<Params>);
3117 Make_If_Statement (Loc,
3118 Condition => New_Reference_To (Raised_Id, Loc),
3119 Then_Statements => New_List (
3120 Make_Procedure_Call_Statement (Loc,
3121 Name => New_Reference_To (Proc_Id, Loc),
3122 Parameter_Associations => Params)));
3123 end Build_Raise_Statement;
3125 -----------------------------
3126 -- Build_Record_Deep_Procs --
3127 -----------------------------
3129 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3133 (Prim => Initialize_Case,
3135 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3137 if not Is_Immutably_Limited_Type (Typ) then
3140 (Prim => Adjust_Case,
3142 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3147 (Prim => Finalize_Case,
3149 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3151 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3152 -- .NET do not support address arithmetic and unchecked conversions.
3154 if VM_Target = No_VM then
3157 (Prim => Address_Case,
3159 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3161 end Build_Record_Deep_Procs;
3167 function Cleanup_Array
3170 Typ : Entity_Id) return List_Id
3172 Loc : constant Source_Ptr := Sloc (N);
3173 Index_List : constant List_Id := New_List;
3175 function Free_Component return List_Id;
3176 -- Generate the code to finalize the task or protected subcomponents
3177 -- of a single component of the array.
3179 function Free_One_Dimension (Dim : Int) return List_Id;
3180 -- Generate a loop over one dimension of the array
3182 --------------------
3183 -- Free_Component --
3184 --------------------
3186 function Free_Component return List_Id is
3187 Stmts : List_Id := New_List;
3189 C_Typ : constant Entity_Id := Component_Type (Typ);
3192 -- Component type is known to contain tasks or protected objects
3195 Make_Indexed_Component (Loc,
3196 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3197 Expressions => Index_List);
3199 Set_Etype (Tsk, C_Typ);
3201 if Is_Task_Type (C_Typ) then
3202 Append_To (Stmts, Cleanup_Task (N, Tsk));
3204 elsif Is_Simple_Protected_Type (C_Typ) then
3205 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3207 elsif Is_Record_Type (C_Typ) then
3208 Stmts := Cleanup_Record (N, Tsk, C_Typ);
3210 elsif Is_Array_Type (C_Typ) then
3211 Stmts := Cleanup_Array (N, Tsk, C_Typ);
3217 ------------------------
3218 -- Free_One_Dimension --
3219 ------------------------
3221 function Free_One_Dimension (Dim : Int) return List_Id is
3225 if Dim > Number_Dimensions (Typ) then
3226 return Free_Component;
3228 -- Here we generate the required loop
3231 Index := Make_Temporary (Loc, 'J');
3232 Append (New_Reference_To (Index, Loc), Index_List);
3235 Make_Implicit_Loop_Statement (N,
3236 Identifier => Empty,
3238 Make_Iteration_Scheme (Loc,
3239 Loop_Parameter_Specification =>
3240 Make_Loop_Parameter_Specification (Loc,
3241 Defining_Identifier => Index,
3242 Discrete_Subtype_Definition =>
3243 Make_Attribute_Reference (Loc,
3244 Prefix => Duplicate_Subexpr (Obj),
3245 Attribute_Name => Name_Range,
3246 Expressions => New_List (
3247 Make_Integer_Literal (Loc, Dim))))),
3248 Statements => Free_One_Dimension (Dim + 1)));
3250 end Free_One_Dimension;
3252 -- Start of processing for Cleanup_Array
3255 return Free_One_Dimension (1);
3258 --------------------
3259 -- Cleanup_Record --
3260 --------------------
3262 function Cleanup_Record
3265 Typ : Entity_Id) return List_Id
3267 Loc : constant Source_Ptr := Sloc (N);
3270 Stmts : constant List_Id := New_List;
3271 U_Typ : constant Entity_Id := Underlying_Type (Typ);
3274 if Has_Discriminants (U_Typ)
3275 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3277 Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3280 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3282 -- For now, do not attempt to free a component that may appear in a
3283 -- variant, and instead issue a warning. Doing this "properly" would
3284 -- require building a case statement and would be quite a mess. Note
3285 -- that the RM only requires that free "work" for the case of a task
3286 -- access value, so already we go way beyond this in that we deal
3287 -- with the array case and non-discriminated record cases.
3290 ("task/protected object in variant record will not be freed?", N);
3291 return New_List (Make_Null_Statement (Loc));
3294 Comp := First_Component (Typ);
3295 while Present (Comp) loop
3296 if Has_Task (Etype (Comp))
3297 or else Has_Simple_Protected_Object (Etype (Comp))
3300 Make_Selected_Component (Loc,
3301 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3302 Selector_Name => New_Occurrence_Of (Comp, Loc));
3303 Set_Etype (Tsk, Etype (Comp));
3305 if Is_Task_Type (Etype (Comp)) then
3306 Append_To (Stmts, Cleanup_Task (N, Tsk));
3308 elsif Is_Simple_Protected_Type (Etype (Comp)) then
3309 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3311 elsif Is_Record_Type (Etype (Comp)) then
3313 -- Recurse, by generating the prefix of the argument to
3314 -- the eventual cleanup call.
3316 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3318 elsif Is_Array_Type (Etype (Comp)) then
3319 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3323 Next_Component (Comp);
3329 ------------------------------
3330 -- Cleanup_Protected_Object --
3331 ------------------------------
3333 function Cleanup_Protected_Object
3335 Ref : Node_Id) return Node_Id
3337 Loc : constant Source_Ptr := Sloc (N);
3340 -- For restricted run-time libraries (Ravenscar), tasks are
3341 -- non-terminating, and protected objects can only appear at library
3342 -- level, so we do not want finalization of protected objects.
3344 if Restricted_Profile then
3349 Make_Procedure_Call_Statement (Loc,
3351 New_Reference_To (RTE (RE_Finalize_Protection), Loc),
3352 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3354 end Cleanup_Protected_Object;
3360 function Cleanup_Task
3362 Ref : Node_Id) return Node_Id
3364 Loc : constant Source_Ptr := Sloc (N);
3367 -- For restricted run-time libraries (Ravenscar), tasks are
3368 -- non-terminating and they can only appear at library level, so we do
3369 -- not want finalization of task objects.
3371 if Restricted_Profile then
3376 Make_Procedure_Call_Statement (Loc,
3378 New_Reference_To (RTE (RE_Free_Task), Loc),
3379 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3383 ------------------------------
3384 -- Check_Visibly_Controlled --
3385 ------------------------------
3387 procedure Check_Visibly_Controlled
3388 (Prim : Final_Primitives;
3390 E : in out Entity_Id;
3391 Cref : in out Node_Id)
3393 Parent_Type : Entity_Id;
3397 if Is_Derived_Type (Typ)
3398 and then Comes_From_Source (E)
3399 and then not Present (Overridden_Operation (E))
3401 -- We know that the explicit operation on the type does not override
3402 -- the inherited operation of the parent, and that the derivation
3403 -- is from a private type that is not visibly controlled.
3405 Parent_Type := Etype (Typ);
3406 Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3408 if Present (Op) then
3411 -- Wrap the object to be initialized into the proper
3412 -- unchecked conversion, to be compatible with the operation
3415 if Nkind (Cref) = N_Unchecked_Type_Conversion then
3416 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3418 Cref := Unchecked_Convert_To (Parent_Type, Cref);
3422 end Check_Visibly_Controlled;
3424 -------------------------------
3425 -- CW_Or_Has_Controlled_Part --
3426 -------------------------------
3428 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3430 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3431 end CW_Or_Has_Controlled_Part;
3437 function Convert_View
3440 Ind : Pos := 1) return Node_Id
3442 Fent : Entity_Id := First_Entity (Proc);
3447 for J in 2 .. Ind loop
3451 Ftyp := Etype (Fent);
3453 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3454 Atyp := Entity (Subtype_Mark (Arg));
3456 Atyp := Etype (Arg);
3459 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3460 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3463 and then Present (Atyp)
3464 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3465 and then Base_Type (Underlying_Type (Atyp)) =
3466 Base_Type (Underlying_Type (Ftyp))
3468 return Unchecked_Convert_To (Ftyp, Arg);
3470 -- If the argument is already a conversion, as generated by
3471 -- Make_Init_Call, set the target type to the type of the formal
3472 -- directly, to avoid spurious typing problems.
3474 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3475 and then not Is_Class_Wide_Type (Atyp)
3477 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3478 Set_Etype (Arg, Ftyp);
3486 ------------------------
3487 -- Enclosing_Function --
3488 ------------------------
3490 function Enclosing_Function (E : Entity_Id) return Entity_Id is
3491 Func_Id : Entity_Id;
3495 while Present (Func_Id)
3496 and then Func_Id /= Standard_Standard
3498 if Ekind (Func_Id) = E_Function then
3502 Func_Id := Scope (Func_Id);
3506 end Enclosing_Function;
3508 -------------------------------
3509 -- Establish_Transient_Scope --
3510 -------------------------------
3512 -- This procedure is called each time a transient block has to be inserted
3513 -- that is to say for each call to a function with unconstrained or tagged
3514 -- result. It creates a new scope on the stack scope in order to enclose
3515 -- all transient variables generated
3517 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3518 Loc : constant Source_Ptr := Sloc (N);
3519 Wrap_Node : Node_Id;
3522 -- Do not create a transient scope if we are already inside one
3524 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3525 if Scope_Stack.Table (S).Is_Transient then
3527 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3532 -- If we have encountered Standard there are no enclosing
3533 -- transient scopes.
3535 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3540 Wrap_Node := Find_Node_To_Be_Wrapped (N);
3542 -- Case of no wrap node, false alert, no transient scope needed
3544 if No (Wrap_Node) then
3547 -- If the node to wrap is an iteration_scheme, the expression is
3548 -- one of the bounds, and the expansion will make an explicit
3549 -- declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3550 -- so do not apply any transformations here.
3552 elsif Nkind (Wrap_Node) = N_Iteration_Scheme then
3555 -- In formal verification mode, if the node to wrap is a pragma check,
3556 -- this node and enclosed expression are not expanded, so do not apply
3557 -- any transformations here.
3560 and then Nkind (Wrap_Node) = N_Pragma
3561 and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
3566 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3567 Set_Scope_Is_Transient;
3570 Set_Uses_Sec_Stack (Current_Scope);
3571 Check_Restriction (No_Secondary_Stack, N);
3574 Set_Etype (Current_Scope, Standard_Void_Type);
3575 Set_Node_To_Be_Wrapped (Wrap_Node);
3577 if Debug_Flag_W then
3578 Write_Str (" <Transient>");
3582 end Establish_Transient_Scope;
3584 ----------------------------
3585 -- Expand_Cleanup_Actions --
3586 ----------------------------
3588 procedure Expand_Cleanup_Actions (N : Node_Id) is
3589 Scop : constant Entity_Id := Current_Scope;
3591 Is_Asynchronous_Call : constant Boolean :=
3592 Nkind (N) = N_Block_Statement
3593 and then Is_Asynchronous_Call_Block (N);
3594 Is_Master : constant Boolean :=
3595 Nkind (N) /= N_Entry_Body
3596 and then Is_Task_Master (N);
3597 Is_Protected_Body : constant Boolean :=
3598 Nkind (N) = N_Subprogram_Body
3599 and then Is_Protected_Subprogram_Body (N);
3600 Is_Task_Allocation : constant Boolean :=
3601 Nkind (N) = N_Block_Statement
3602 and then Is_Task_Allocation_Block (N);
3603 Is_Task_Body : constant Boolean :=
3604 Nkind (Original_Node (N)) = N_Task_Body;
3605 Needs_Sec_Stack_Mark : constant Boolean :=
3606 Uses_Sec_Stack (Scop)
3608 not Sec_Stack_Needed_For_Return (Scop)
3609 and then VM_Target = No_VM;
3611 Actions_Required : constant Boolean :=
3612 Requires_Cleanup_Actions (N)
3613 or else Is_Asynchronous_Call
3615 or else Is_Protected_Body
3616 or else Is_Task_Allocation
3617 or else Is_Task_Body
3618 or else Needs_Sec_Stack_Mark;
3620 HSS : Node_Id := Handled_Statement_Sequence (N);
3623 procedure Wrap_HSS_In_Block;
3624 -- Move HSS inside a new block along with the original exception
3625 -- handlers. Make the newly generated block the sole statement of HSS.
3627 -----------------------
3628 -- Wrap_HSS_In_Block --
3629 -----------------------
3631 procedure Wrap_HSS_In_Block is
3636 -- Preserve end label to provide proper cross-reference information
3638 End_Lab := End_Label (HSS);
3640 Make_Block_Statement (Loc,
3641 Handled_Statement_Sequence => HSS);
3643 Set_Handled_Statement_Sequence (N,
3644 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3645 HSS := Handled_Statement_Sequence (N);
3647 Set_First_Real_Statement (HSS, Block);
3648 Set_End_Label (HSS, End_Lab);
3650 -- Comment needed here, see RH for 1.306 ???
3652 if Nkind (N) = N_Subprogram_Body then
3653 Set_Has_Nested_Block_With_Handler (Scop);
3655 end Wrap_HSS_In_Block;
3657 -- Start of processing for Expand_Cleanup_Actions
3660 -- The current construct does not need any form of servicing
3662 if not Actions_Required then
3665 -- If the current node is a rewritten task body and the descriptors have
3666 -- not been delayed (due to some nested instantiations), do not generate
3667 -- redundant cleanup actions.
3670 and then Nkind (N) = N_Subprogram_Body
3671 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3677 Decls : List_Id := Declarations (N);
3679 Mark : Entity_Id := Empty;
3680 New_Decls : List_Id;
3684 -- If we are generating expanded code for debugging purposes, use the
3685 -- Sloc of the point of insertion for the cleanup code. The Sloc will
3686 -- be updated subsequently to reference the proper line in .dg files.
3687 -- If we are not debugging generated code, use No_Location instead,
3688 -- so that no debug information is generated for the cleanup code.
3689 -- This makes the behavior of the NEXT command in GDB monotonic, and
3690 -- makes the placement of breakpoints more accurate.
3692 if Debug_Generated_Code then
3698 -- Set polling off. The finalization and cleanup code is executed
3699 -- with aborts deferred.
3701 Old_Poll := Polling_Required;
3702 Polling_Required := False;
3704 -- A task activation call has already been built for a task
3705 -- allocation block.
3707 if not Is_Task_Allocation then
3708 Build_Task_Activation_Call (N);
3712 Establish_Task_Master (N);
3715 New_Decls := New_List;
3717 -- If secondary stack is in use, generate:
3719 -- Mnn : constant Mark_Id := SS_Mark;
3721 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3722 -- secondary stack is never used on a VM.
3724 if Needs_Sec_Stack_Mark then
3725 Mark := Make_Temporary (Loc, 'M');
3727 Append_To (New_Decls,
3728 Make_Object_Declaration (Loc,
3729 Defining_Identifier => Mark,
3730 Object_Definition =>
3731 New_Reference_To (RTE (RE_Mark_Id), Loc),
3733 Make_Function_Call (Loc,
3734 Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
3736 Set_Uses_Sec_Stack (Scop, False);
3739 -- If exception handlers are present, wrap the sequence of statements
3740 -- in a block since it is not possible to have exception handlers and
3741 -- an At_End handler in the same construct.
3743 if Present (Exception_Handlers (HSS)) then
3746 -- Ensure that the First_Real_Statement field is set
3748 elsif No (First_Real_Statement (HSS)) then
3749 Set_First_Real_Statement (HSS, First (Statements (HSS)));
3752 -- Do not move the Activation_Chain declaration in the context of
3753 -- task allocation blocks. Task allocation blocks use _chain in their
3754 -- cleanup handlers and gigi complains if it is declared in the
3755 -- sequence of statements of the scope that declares the handler.
3757 if Is_Task_Allocation then
3759 Chain : constant Entity_Id := Activation_Chain_Entity (N);
3763 Decl := First (Decls);
3764 while Nkind (Decl) /= N_Object_Declaration
3765 or else Defining_Identifier (Decl) /= Chain
3769 -- A task allocation block should always include a _chain
3772 pragma Assert (Present (Decl));
3776 Prepend_To (New_Decls, Decl);
3780 -- Ensure the presence of a declaration list in order to successfully
3781 -- append all original statements to it.
3784 Set_Declarations (N, New_List);
3785 Decls := Declarations (N);
3788 -- Move the declarations into the sequence of statements in order to
3789 -- have them protected by the At_End handler. It may seem weird to
3790 -- put declarations in the sequence of statement but in fact nothing
3791 -- forbids that at the tree level.
3793 Append_List_To (Decls, Statements (HSS));
3794 Set_Statements (HSS, Decls);
3796 -- Reset the Sloc of the handled statement sequence to properly
3797 -- reflect the new initial "statement" in the sequence.
3799 Set_Sloc (HSS, Sloc (First (Decls)));
3801 -- The declarations of finalizer spec and auxiliary variables replace
3802 -- the old declarations that have been moved inward.
3804 Set_Declarations (N, New_Decls);
3805 Analyze_Declarations (New_Decls);
3807 -- Generate finalization calls for all controlled objects appearing
3808 -- in the statements of N. Add context specific cleanup for various
3813 Clean_Stmts => Build_Cleanup_Statements (N),
3815 Top_Decls => New_Decls,
3816 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
3820 if Present (Fin_Id) then
3821 Build_Finalizer_Call (N, Fin_Id);
3824 -- Restore saved polling mode
3826 Polling_Required := Old_Poll;
3828 end Expand_Cleanup_Actions;
3830 ---------------------------
3831 -- Expand_N_Package_Body --
3832 ---------------------------
3834 -- Add call to Activate_Tasks if body is an activator (actual processing
3835 -- is in chapter 9).
3837 -- Generate subprogram descriptor for elaboration routine
3839 -- Encode entity names in package body
3841 procedure Expand_N_Package_Body (N : Node_Id) is
3842 Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
3846 -- This is done only for non-generic packages
3848 if Ekind (Spec_Ent) = E_Package then
3849 Push_Scope (Corresponding_Spec (N));
3851 -- Build dispatch tables of library level tagged types
3853 if Tagged_Type_Expansion
3854 and then Is_Library_Level_Entity (Spec_Ent)
3856 Build_Static_Dispatch_Tables (N);
3859 Build_Task_Activation_Call (N);
3863 Set_Elaboration_Flag (N, Corresponding_Spec (N));
3864 Set_In_Package_Body (Spec_Ent, False);
3866 -- Set to encode entity names in package body before gigi is called
3868 Qualify_Entity_Names (N);
3870 if Ekind (Spec_Ent) /= E_Generic_Package then
3873 Clean_Stmts => No_List,
3875 Top_Decls => No_List,
3876 Defer_Abort => False,
3879 if Present (Fin_Id) then
3881 Body_Ent : Node_Id := Defining_Unit_Name (N);
3884 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
3885 Body_Ent := Defining_Identifier (Body_Ent);
3888 Set_Finalizer (Body_Ent, Fin_Id);
3892 end Expand_N_Package_Body;
3894 ----------------------------------
3895 -- Expand_N_Package_Declaration --
3896 ----------------------------------
3898 -- Add call to Activate_Tasks if there are tasks declared and the package
3899 -- has no body. Note that in Ada83, this may result in premature activation
3900 -- of some tasks, given that we cannot tell whether a body will eventually
3903 procedure Expand_N_Package_Declaration (N : Node_Id) is
3904 Id : constant Entity_Id := Defining_Entity (N);
3905 Spec : constant Node_Id := Specification (N);
3909 No_Body : Boolean := False;
3910 -- True in the case of a package declaration that is a compilation
3911 -- unit and for which no associated body will be compiled in this
3915 -- Case of a package declaration other than a compilation unit
3917 if Nkind (Parent (N)) /= N_Compilation_Unit then
3920 -- Case of a compilation unit that does not require a body
3922 elsif not Body_Required (Parent (N))
3923 and then not Unit_Requires_Body (Id)
3927 -- Special case of generating calling stubs for a remote call interface
3928 -- package: even though the package declaration requires one, the body
3929 -- won't be processed in this compilation (so any stubs for RACWs
3930 -- declared in the package must be generated here, along with the spec).
3932 elsif Parent (N) = Cunit (Main_Unit)
3933 and then Is_Remote_Call_Interface (Id)
3934 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
3939 -- For a package declaration that implies no associated body, generate
3940 -- task activation call and RACW supporting bodies now (since we won't
3941 -- have a specific separate compilation unit for that).
3946 if Has_RACW (Id) then
3948 -- Generate RACW subprogram bodies
3950 Decls := Private_Declarations (Spec);
3953 Decls := Visible_Declarations (Spec);
3958 Set_Visible_Declarations (Spec, Decls);
3961 Append_RACW_Bodies (Decls, Id);
3962 Analyze_List (Decls);
3965 if Present (Activation_Chain_Entity (N)) then
3967 -- Generate task activation call as last step of elaboration
3969 Build_Task_Activation_Call (N);
3975 -- Build dispatch tables of library level tagged types
3977 if Tagged_Type_Expansion
3978 and then (Is_Compilation_Unit (Id)
3979 or else (Is_Generic_Instance (Id)
3980 and then Is_Library_Level_Entity (Id)))
3982 Build_Static_Dispatch_Tables (N);
3985 -- Note: it is not necessary to worry about generating a subprogram
3986 -- descriptor, since the only way to get exception handlers into a
3987 -- package spec is to include instantiations, and that would cause
3988 -- generation of subprogram descriptors to be delayed in any case.
3990 -- Set to encode entity names in package spec before gigi is called
3992 Qualify_Entity_Names (N);
3994 if Ekind (Id) /= E_Generic_Package then
3997 Clean_Stmts => No_List,
3999 Top_Decls => No_List,
4000 Defer_Abort => False,
4003 Set_Finalizer (Id, Fin_Id);
4005 end Expand_N_Package_Declaration;
4007 -----------------------------
4008 -- Find_Node_To_Be_Wrapped --
4009 -----------------------------
4011 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
4013 The_Parent : Node_Id;
4019 pragma Assert (P /= Empty);
4020 The_Parent := Parent (P);
4022 case Nkind (The_Parent) is
4024 -- Simple statement can be wrapped
4029 -- Usually assignments are good candidate for wrapping
4030 -- except when they have been generated as part of a
4031 -- controlled aggregate where the wrapping should take
4032 -- place more globally.
4034 when N_Assignment_Statement =>
4035 if No_Ctrl_Actions (The_Parent) then
4041 -- An entry call statement is a special case if it occurs in
4042 -- the context of a Timed_Entry_Call. In this case we wrap
4043 -- the entire timed entry call.
4045 when N_Entry_Call_Statement |
4046 N_Procedure_Call_Statement =>
4047 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
4048 and then Nkind_In (Parent (Parent (The_Parent)),
4050 N_Conditional_Entry_Call)
4052 return Parent (Parent (The_Parent));
4057 -- Object declarations are also a boundary for the transient scope
4058 -- even if they are not really wrapped
4059 -- (see Wrap_Transient_Declaration)
4061 when N_Object_Declaration |
4062 N_Object_Renaming_Declaration |
4063 N_Subtype_Declaration =>
4066 -- The expression itself is to be wrapped if its parent is a
4067 -- compound statement or any other statement where the expression
4068 -- is known to be scalar
4070 when N_Accept_Alternative |
4071 N_Attribute_Definition_Clause |
4074 N_Delay_Alternative |
4075 N_Delay_Until_Statement |
4076 N_Delay_Relative_Statement |
4077 N_Discriminant_Association |
4079 N_Entry_Body_Formal_Part |
4082 N_Iteration_Scheme |
4083 N_Terminate_Alternative =>
4086 when N_Attribute_Reference =>
4088 if Is_Procedure_Attribute_Name
4089 (Attribute_Name (The_Parent))
4094 -- A raise statement can be wrapped. This will arise when the
4095 -- expression in a raise_with_expression uses the secondary
4096 -- stack, for example.
4098 when N_Raise_Statement =>
4101 -- If the expression is within the iteration scheme of a loop,
4102 -- we must create a declaration for it, followed by an assignment
4103 -- in order to have a usable statement to wrap.
4105 when N_Loop_Parameter_Specification =>
4106 return Parent (The_Parent);
4108 -- The following nodes contains "dummy calls" which don't
4109 -- need to be wrapped.
4111 when N_Parameter_Specification |
4112 N_Discriminant_Specification |
4113 N_Component_Declaration =>
4116 -- The return statement is not to be wrapped when the function
4117 -- itself needs wrapping at the outer-level
4119 when N_Simple_Return_Statement =>
4121 Applies_To : constant Entity_Id :=
4123 (Return_Statement_Entity (The_Parent));
4124 Return_Type : constant Entity_Id := Etype (Applies_To);
4126 if Requires_Transient_Scope (Return_Type) then
4133 -- If we leave a scope without having been able to find a node to
4134 -- wrap, something is going wrong but this can happen in error
4135 -- situation that are not detected yet (such as a dynamic string
4136 -- in a pragma export)
4138 when N_Subprogram_Body |
4139 N_Package_Declaration |
4141 N_Block_Statement =>
4144 -- otherwise continue the search
4150 end Find_Node_To_Be_Wrapped;
4152 -------------------------------------
4153 -- Get_Global_Pool_For_Access_Type --
4154 -------------------------------------
4156 function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id is
4158 -- Access types whose size is smaller than System.Address size can
4159 -- exist only on VMS. We can't use the usual global pool which returns
4160 -- an object of type Address as truncation will make it invalid.
4161 -- To handle this case, VMS has a dedicated global pool that returns
4162 -- addresses that fit into 32 bit accesses.
4164 if Opt.True_VMS_Target and then Esize (T) = 32 then
4165 return RTE (RE_Global_Pool_32_Object);
4167 return RTE (RE_Global_Pool_Object);
4169 end Get_Global_Pool_For_Access_Type;
4171 ----------------------------------
4172 -- Has_New_Controlled_Component --
4173 ----------------------------------
4175 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4179 if not Is_Tagged_Type (E) then
4180 return Has_Controlled_Component (E);
4181 elsif not Is_Derived_Type (E) then
4182 return Has_Controlled_Component (E);
4185 Comp := First_Component (E);
4186 while Present (Comp) loop
4187 if Chars (Comp) = Name_uParent then
4190 elsif Scope (Original_Record_Component (Comp)) = E
4191 and then Needs_Finalization (Etype (Comp))
4196 Next_Component (Comp);
4200 end Has_New_Controlled_Component;
4202 ---------------------------------
4203 -- Has_Simple_Protected_Object --
4204 ---------------------------------
4206 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4208 if Has_Task (T) then
4211 elsif Is_Simple_Protected_Type (T) then
4214 elsif Is_Array_Type (T) then
4215 return Has_Simple_Protected_Object (Component_Type (T));
4217 elsif Is_Record_Type (T) then
4222 Comp := First_Component (T);
4223 while Present (Comp) loop
4224 if Has_Simple_Protected_Object (Etype (Comp)) then
4228 Next_Component (Comp);
4237 end Has_Simple_Protected_Object;
4239 ------------------------------------
4240 -- Insert_Actions_In_Scope_Around --
4241 ------------------------------------
4243 procedure Insert_Actions_In_Scope_Around (N : Node_Id) is
4244 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
4245 After : List_Id renames SE.Actions_To_Be_Wrapped_After;
4246 Before : List_Id renames SE.Actions_To_Be_Wrapped_Before;
4248 procedure Process_Transient_Objects
4249 (First_Object : Node_Id;
4250 Last_Object : Node_Id;
4251 Related_Node : Node_Id);
4252 -- First_Object and Last_Object define a list which contains potential
4253 -- controlled transient objects. Finalization flags are inserted before
4254 -- First_Object and finalization calls are inserted after Last_Object.
4255 -- Related_Node is the node for which transient objects have been
4258 -------------------------------
4259 -- Process_Transient_Objects --
4260 -------------------------------
4262 procedure Process_Transient_Objects
4263 (First_Object : Node_Id;
4264 Last_Object : Node_Id;
4265 Related_Node : Node_Id)
4267 Abort_Id : Entity_Id;
4268 Built : Boolean := False;
4271 Fin_Block : Node_Id;
4272 Last_Fin : Node_Id := Empty;
4276 Obj_Typ : Entity_Id;
4277 Raised_Id : Entity_Id;
4281 -- Examine all objects in the list First_Object .. Last_Object
4283 Stmt := First_Object;
4284 while Present (Stmt) loop
4285 if Nkind (Stmt) = N_Object_Declaration
4286 and then Analyzed (Stmt)
4287 and then Is_Finalizable_Transient (Stmt, N)
4289 -- Do not process the node to be wrapped since it will be
4290 -- handled by the enclosing finalizer.
4292 and then Stmt /= Related_Node
4295 Obj_Id := Defining_Identifier (Stmt);
4296 Obj_Typ := Base_Type (Etype (Obj_Id));
4299 Set_Is_Processed_Transient (Obj_Id);
4301 -- Handle access types
4303 if Is_Access_Type (Desig) then
4304 Desig := Available_View (Designated_Type (Desig));
4307 -- Create the necessary entities and declarations the first
4311 Abort_Id := Make_Temporary (Loc, 'A');
4312 E_Id := Make_Temporary (Loc, 'E');
4313 Raised_Id := Make_Temporary (Loc, 'R');
4315 Insert_List_Before_And_Analyze (First_Object,
4316 Build_Object_Declarations
4317 (Loc, Abort_Id, E_Id, Raised_Id));
4324 -- [Deep_]Finalize (Obj_Ref);
4331 -- (Enn, Get_Current_Excep.all.all);
4335 Obj_Ref := New_Reference_To (Obj_Id, Loc);
4337 if Is_Access_Type (Obj_Typ) then
4338 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4342 Make_Block_Statement (Loc,
4343 Handled_Statement_Sequence =>
4344 Make_Handled_Sequence_Of_Statements (Loc,
4345 Statements => New_List (
4347 (Obj_Ref => Obj_Ref,
4350 Exception_Handlers => New_List (
4351 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4352 Insert_After_And_Analyze (Last_Object, Fin_Block);
4354 -- The raise statement must be inserted after all the
4355 -- finalization blocks.
4357 if No (Last_Fin) then
4358 Last_Fin := Fin_Block;
4361 -- When the associated node is an array object, the expander may
4362 -- sometimes generate a loop and create transient objects inside
4365 elsif Nkind (Related_Node) = N_Object_Declaration
4366 and then Is_Array_Type (Base_Type
4367 (Etype (Defining_Identifier (Related_Node))))
4368 and then Nkind (Stmt) = N_Loop_Statement
4371 Block_HSS : Node_Id := First (Statements (Stmt));
4374 -- The loop statements may have been wrapped in a block by
4375 -- Process_Statements_For_Controlled_Objects, inspect the
4376 -- handled sequence of statements.
4378 if Nkind (Block_HSS) = N_Block_Statement
4379 and then No (Next (Block_HSS))
4381 Block_HSS := Handled_Statement_Sequence (Block_HSS);
4383 Process_Transient_Objects
4384 (First_Object => First (Statements (Block_HSS)),
4385 Last_Object => Last (Statements (Block_HSS)),
4386 Related_Node => Related_Node);
4388 -- Inspect the statements of the loop
4391 Process_Transient_Objects
4392 (First_Object => First (Statements (Stmt)),
4393 Last_Object => Last (Statements (Stmt)),
4394 Related_Node => Related_Node);
4398 -- Terminate the scan after the last object has been processed
4400 elsif Stmt = Last_Object then
4409 -- Raise_From_Controlled_Operation (E, Abort);
4413 and then Present (Last_Fin)
4415 Insert_After_And_Analyze (Last_Fin,
4416 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4418 end Process_Transient_Objects;
4420 -- Start of processing for Insert_Actions_In_Scope_Around
4423 if No (Before) and then No (After) then
4428 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
4429 First_Obj : Node_Id;
4434 -- If the node to be wrapped is the trigger of an asynchronous
4435 -- select, it is not part of a statement list. The actions must be
4436 -- inserted before the select itself, which is part of some list of
4437 -- statements. Note that the triggering alternative includes the
4438 -- triggering statement and an optional statement list. If the node
4439 -- to be wrapped is part of that list, the normal insertion applies.
4441 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4442 and then not Is_List_Member (Node_To_Wrap)
4444 Target := Parent (Parent (Node_To_Wrap));
4449 First_Obj := Target;
4452 -- Add all actions associated with a transient scope into the main
4453 -- tree. There are several scenarios here:
4455 -- +--- Before ----+ +----- After ---+
4456 -- 1) First_Obj ....... Target ........ Last_Obj
4458 -- 2) First_Obj ....... Target
4460 -- 3) Target ........ Last_Obj
4462 if Present (Before) then
4464 -- Flag declarations are inserted before the first object
4466 First_Obj := First (Before);
4468 Insert_List_Before (Target, Before);
4471 if Present (After) then
4473 -- Finalization calls are inserted after the last object
4475 Last_Obj := Last (After);
4477 Insert_List_After (Target, After);
4480 -- Check for transient controlled objects associated with Target and
4481 -- generate the appropriate finalization actions for them.
4483 Process_Transient_Objects
4484 (First_Object => First_Obj,
4485 Last_Object => Last_Obj,
4486 Related_Node => Target);
4488 -- Reset the action lists
4490 if Present (Before) then
4494 if Present (After) then
4498 end Insert_Actions_In_Scope_Around;
4500 ------------------------------
4501 -- Is_Simple_Protected_Type --
4502 ------------------------------
4504 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
4507 Is_Protected_Type (T)
4508 and then not Has_Entries (T)
4509 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
4510 end Is_Simple_Protected_Type;
4512 -----------------------
4513 -- Make_Adjust_Call --
4514 -----------------------
4516 function Make_Adjust_Call
4519 For_Parent : Boolean := False) return Node_Id
4521 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4522 Adj_Id : Entity_Id := Empty;
4523 Ref : Node_Id := Obj_Ref;
4527 -- Recover the proper type which contains Deep_Adjust
4529 if Is_Class_Wide_Type (Typ) then
4530 Utyp := Root_Type (Typ);
4535 Utyp := Underlying_Type (Base_Type (Utyp));
4536 Set_Assignment_OK (Ref);
4538 -- Deal with non-tagged derivation of private views
4540 if Is_Untagged_Derivation (Typ) then
4541 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
4542 Ref := Unchecked_Convert_To (Utyp, Ref);
4543 Set_Assignment_OK (Ref);
4546 -- When dealing with the completion of a private type, use the base
4549 if Utyp /= Base_Type (Utyp) then
4550 pragma Assert (Is_Private_Type (Typ));
4552 Utyp := Base_Type (Utyp);
4553 Ref := Unchecked_Convert_To (Utyp, Ref);
4556 -- Select the appropriate version of adjust
4559 if Has_Controlled_Component (Utyp) then
4560 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4563 -- For types that are both controlled and have controlled components,
4564 -- generate a call to Deep_Adjust.
4566 elsif Is_Controlled (Utyp)
4567 and then Has_Controlled_Component (Utyp)
4569 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4571 -- For types that are not controlled themselves, but contain controlled
4572 -- components or can be extended by types with controlled components,
4573 -- create a call to Deep_Adjust.
4575 elsif Is_Class_Wide_Type (Typ)
4576 or else Has_Controlled_Component (Utyp)
4578 if Is_Tagged_Type (Utyp) then
4579 Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4581 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
4584 -- For types that are derived from Controlled and do not have controlled
4585 -- components, build a call to Adjust.
4588 Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
4591 if Present (Adj_Id) then
4593 -- If the object is unanalyzed, set its expected type for use in
4594 -- Convert_View in case an additional conversion is needed.
4597 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
4599 Set_Etype (Ref, Typ);
4602 -- The object reference may need another conversion depending on the
4603 -- type of the formal and that of the actual.
4605 if not Is_Class_Wide_Type (Typ) then
4606 Ref := Convert_View (Adj_Id, Ref);
4609 return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent);
4613 end Make_Adjust_Call;
4615 ----------------------
4616 -- Make_Attach_Call --
4617 ----------------------
4619 function Make_Attach_Call
4621 Ptr_Typ : Entity_Id) return Node_Id
4623 pragma Assert (VM_Target /= No_VM);
4625 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4628 Make_Procedure_Call_Statement (Loc,
4630 New_Reference_To (RTE (RE_Attach), Loc),
4631 Parameter_Associations => New_List (
4632 New_Reference_To (Finalization_Master (Ptr_Typ), Loc),
4633 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4634 end Make_Attach_Call;
4636 ----------------------
4637 -- Make_Detach_Call --
4638 ----------------------
4640 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
4641 Loc : constant Source_Ptr := Sloc (Obj_Ref);
4645 Make_Procedure_Call_Statement (Loc,
4647 New_Reference_To (RTE (RE_Detach), Loc),
4648 Parameter_Associations => New_List (
4649 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4650 end Make_Detach_Call;
4658 Proc_Id : Entity_Id;
4660 For_Parent : Boolean := False) return Node_Id
4662 Params : constant List_Id := New_List (Param);
4665 -- When creating a call to Deep_Finalize for a _parent field of a
4666 -- derived type, disable the invocation of the nested Finalize by giving
4667 -- the corresponding flag a False value.
4670 Append_To (Params, New_Reference_To (Standard_False, Loc));
4674 Make_Procedure_Call_Statement (Loc,
4675 Name => New_Reference_To (Proc_Id, Loc),
4676 Parameter_Associations => Params);
4679 --------------------------
4680 -- Make_Deep_Array_Body --
4681 --------------------------
4683 function Make_Deep_Array_Body
4684 (Prim : Final_Primitives;
4685 Typ : Entity_Id) return List_Id
4687 function Build_Adjust_Or_Finalize_Statements
4688 (Typ : Entity_Id) return List_Id;
4689 -- Create the statements necessary to adjust or finalize an array of
4690 -- controlled elements. Generate:
4693 -- Temp : constant Exception_Occurrence_Access :=
4694 -- Get_Current_Excep.all;
4695 -- Abort : constant Boolean :=
4697 -- and then Exception_Identity (Temp_Id.all) =
4698 -- Standard'Abort_Signal'Identity;
4700 -- Abort : constant Boolean := False; -- no abort
4702 -- E : Exception_Occurrence;
4703 -- Raised : Boolean := False;
4706 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
4707 -- ^-- in the finalization case
4709 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
4711 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
4715 -- if not Raised then
4717 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4725 -- Raise_From_Controlled_Operation (E, Abort);
4729 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
4730 -- Create the statements necessary to initialize an array of controlled
4731 -- elements. Include a mechanism to carry out partial finalization if an
4732 -- exception occurs. Generate:
4735 -- Counter : Integer := 0;
4738 -- for J1 in V'Range (1) loop
4740 -- for JN in V'Range (N) loop
4742 -- [Deep_]Initialize (V (J1, ..., JN));
4744 -- Counter := Counter + 1;
4749 -- Temp : constant Exception_Occurrence_Access :=
4750 -- Get_Current_Excep.all;
4751 -- Abort : constant Boolean :=
4753 -- and then Exception_Identity (Temp_Id.all) =
4754 -- Standard'Abort_Signal'Identity;
4756 -- Abort : constant Boolean := False; -- no abort
4757 -- E : Exception_Occurence;
4758 -- Raised : Boolean := False;
4765 -- V'Length (N) - Counter;
4767 -- for F1 in reverse V'Range (1) loop
4769 -- for FN in reverse V'Range (N) loop
4770 -- if Counter > 0 then
4771 -- Counter := Counter - 1;
4774 -- [Deep_]Finalize (V (F1, ..., FN));
4778 -- if not Raised then
4780 -- Save_Occurrence (E,
4781 -- Get_Current_Excep.all.all);
4791 -- Raise_From_Controlled_Operation (E, Abort);
4800 function New_References_To
4802 Loc : Source_Ptr) return List_Id;
4803 -- Given a list of defining identifiers, return a list of references to
4804 -- the original identifiers, in the same order as they appear.
4806 -----------------------------------------
4807 -- Build_Adjust_Or_Finalize_Statements --
4808 -----------------------------------------
4810 function Build_Adjust_Or_Finalize_Statements
4811 (Typ : Entity_Id) return List_Id
4813 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4814 Index_List : constant List_Id := New_List;
4815 Loc : constant Source_Ptr := Sloc (Typ);
4816 Num_Dims : constant Int := Number_Dimensions (Typ);
4817 Abort_Id : Entity_Id := Empty;
4820 Core_Loop : Node_Id;
4822 E_Id : Entity_Id := Empty;
4824 Loop_Id : Entity_Id;
4825 Raised_Id : Entity_Id := Empty;
4828 Exceptions_OK : constant Boolean :=
4829 not Restriction_Active (No_Exception_Propagation);
4831 procedure Build_Indices;
4832 -- Generate the indices used in the dimension loops
4838 procedure Build_Indices is
4840 -- Generate the following identifiers:
4841 -- Jnn - for initialization
4843 for Dim in 1 .. Num_Dims loop
4844 Append_To (Index_List,
4845 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4849 -- Start of processing for Build_Adjust_Or_Finalize_Statements
4854 if Exceptions_OK then
4855 Abort_Id := Make_Temporary (Loc, 'A');
4856 E_Id := Make_Temporary (Loc, 'E');
4857 Raised_Id := Make_Temporary (Loc, 'R');
4861 Make_Indexed_Component (Loc,
4862 Prefix => Make_Identifier (Loc, Name_V),
4863 Expressions => New_References_To (Index_List, Loc));
4864 Set_Etype (Comp_Ref, Comp_Typ);
4867 -- [Deep_]Adjust (V (J1, ..., JN))
4869 if Prim = Adjust_Case then
4870 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4873 -- [Deep_]Finalize (V (J1, ..., JN))
4875 else pragma Assert (Prim = Finalize_Case);
4876 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4879 -- Generate the block which houses the adjust or finalize call:
4881 -- <adjust or finalize call>; -- No_Exception_Propagation
4883 -- begin -- Exception handlers allowed
4884 -- <adjust or finalize call>
4888 -- if not Raised then
4890 -- Save_Occurrence (E, Get_Current_Excep.all.all);
4894 if Exceptions_OK then
4896 Make_Block_Statement (Loc,
4897 Handled_Statement_Sequence =>
4898 Make_Handled_Sequence_Of_Statements (Loc,
4899 Statements => New_List (Call),
4900 Exception_Handlers => New_List (
4901 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
4906 -- Generate the dimension loops starting from the innermost one
4908 -- for Jnn in [reverse] V'Range (Dim) loop
4912 J := Last (Index_List);
4914 while Present (J) and then Dim > 0 loop
4920 Make_Loop_Statement (Loc,
4922 Make_Iteration_Scheme (Loc,
4923 Loop_Parameter_Specification =>
4924 Make_Loop_Parameter_Specification (Loc,
4925 Defining_Identifier => Loop_Id,
4926 Discrete_Subtype_Definition =>
4927 Make_Attribute_Reference (Loc,
4928 Prefix => Make_Identifier (Loc, Name_V),
4929 Attribute_Name => Name_Range,
4930 Expressions => New_List (
4931 Make_Integer_Literal (Loc, Dim))),
4933 Reverse_Present => Prim = Finalize_Case)),
4935 Statements => New_List (Core_Loop),
4936 End_Label => Empty);
4941 -- Generate the block which contains the core loop, the declarations
4942 -- of the abort flag, the exception occurrence, the raised flag and
4943 -- the conditional raise:
4946 -- Abort : constant Boolean :=
4947 -- Exception_Occurrence (Get_Current_Excep.all.all) =
4948 -- Standard'Abort_Signal'Identity;
4950 -- Abort : constant Boolean := False; -- no abort
4952 -- E : Exception_Occurrence;
4953 -- Raised : Boolean := False;
4958 -- if Raised then -- Expection handlers allowed
4959 -- Raise_From_Controlled_Operation (E, Abort);
4963 Stmts := New_List (Core_Loop);
4965 if Exceptions_OK then
4967 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
4972 Make_Block_Statement (Loc,
4974 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
4975 Handled_Statement_Sequence =>
4976 Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
4977 end Build_Adjust_Or_Finalize_Statements;
4979 ---------------------------------
4980 -- Build_Initialize_Statements --
4981 ---------------------------------
4983 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
4984 Comp_Typ : constant Entity_Id := Component_Type (Typ);
4985 Final_List : constant List_Id := New_List;
4986 Index_List : constant List_Id := New_List;
4987 Loc : constant Source_Ptr := Sloc (Typ);
4988 Num_Dims : constant Int := Number_Dimensions (Typ);
4989 Abort_Id : Entity_Id;
4990 Counter_Id : Entity_Id;
4992 E_Id : Entity_Id := Empty;
4995 Final_Block : Node_Id;
4996 Final_Loop : Node_Id;
4997 Init_Loop : Node_Id;
5000 Raised_Id : Entity_Id := Empty;
5003 Exceptions_OK : constant Boolean :=
5004 not Restriction_Active (No_Exception_Propagation);
5006 function Build_Counter_Assignment return Node_Id;
5007 -- Generate the following assignment:
5008 -- Counter := V'Length (1) *
5010 -- V'Length (N) - Counter;
5012 function Build_Finalization_Call return Node_Id;
5013 -- Generate a deep finalization call for an array element
5015 procedure Build_Indices;
5016 -- Generate the initialization and finalization indices used in the
5019 function Build_Initialization_Call return Node_Id;
5020 -- Generate a deep initialization call for an array element
5022 ------------------------------
5023 -- Build_Counter_Assignment --
5024 ------------------------------
5026 function Build_Counter_Assignment return Node_Id is
5031 -- Start from the first dimension and generate:
5036 Make_Attribute_Reference (Loc,
5037 Prefix => Make_Identifier (Loc, Name_V),
5038 Attribute_Name => Name_Length,
5039 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
5041 -- Process the rest of the dimensions, generate:
5042 -- Expr * V'Length (N)
5045 while Dim <= Num_Dims loop
5047 Make_Op_Multiply (Loc,
5050 Make_Attribute_Reference (Loc,
5051 Prefix => Make_Identifier (Loc, Name_V),
5052 Attribute_Name => Name_Length,
5053 Expressions => New_List (
5054 Make_Integer_Literal (Loc, Dim))));
5060 -- Counter := Expr - Counter;
5063 Make_Assignment_Statement (Loc,
5064 Name => New_Reference_To (Counter_Id, Loc),
5066 Make_Op_Subtract (Loc,
5068 Right_Opnd => New_Reference_To (Counter_Id, Loc)));
5069 end Build_Counter_Assignment;
5071 -----------------------------
5072 -- Build_Finalization_Call --
5073 -----------------------------
5075 function Build_Finalization_Call return Node_Id is
5076 Comp_Ref : constant Node_Id :=
5077 Make_Indexed_Component (Loc,
5078 Prefix => Make_Identifier (Loc, Name_V),
5079 Expressions => New_References_To (Final_List, Loc));
5082 Set_Etype (Comp_Ref, Comp_Typ);
5085 -- [Deep_]Finalize (V);
5087 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5088 end Build_Finalization_Call;
5094 procedure Build_Indices is
5096 -- Generate the following identifiers:
5097 -- Jnn - for initialization
5098 -- Fnn - for finalization
5100 for Dim in 1 .. Num_Dims loop
5101 Append_To (Index_List,
5102 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5104 Append_To (Final_List,
5105 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5109 -------------------------------
5110 -- Build_Initialization_Call --
5111 -------------------------------
5113 function Build_Initialization_Call return Node_Id is
5114 Comp_Ref : constant Node_Id :=
5115 Make_Indexed_Component (Loc,
5116 Prefix => Make_Identifier (Loc, Name_V),
5117 Expressions => New_References_To (Index_List, Loc));
5120 Set_Etype (Comp_Ref, Comp_Typ);
5123 -- [Deep_]Initialize (V (J1, ..., JN));
5125 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5126 end Build_Initialization_Call;
5128 -- Start of processing for Build_Initialize_Statements
5133 Counter_Id := Make_Temporary (Loc, 'C');
5135 if Exceptions_OK then
5136 Abort_Id := Make_Temporary (Loc, 'A');
5137 E_Id := Make_Temporary (Loc, 'E');
5138 Raised_Id := Make_Temporary (Loc, 'R');
5141 -- Generate the block which houses the finalization call, the index
5142 -- guard and the handler which triggers Program_Error later on.
5144 -- if Counter > 0 then
5145 -- Counter := Counter - 1;
5147 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5149 -- begin -- Exceptions allowed
5150 -- [Deep_]Finalize (V (F1, ..., FN));
5153 -- if not Raised then
5155 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5160 if Exceptions_OK then
5162 Make_Block_Statement (Loc,
5163 Handled_Statement_Sequence =>
5164 Make_Handled_Sequence_Of_Statements (Loc,
5165 Statements => New_List (Build_Finalization_Call),
5166 Exception_Handlers => New_List (
5167 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5169 Fin_Stmt := Build_Finalization_Call;
5172 -- This is the core of the loop, the dimension iterators are added
5173 -- one by one in reverse.
5176 Make_If_Statement (Loc,
5179 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5180 Right_Opnd => Make_Integer_Literal (Loc, 0)),
5182 Then_Statements => New_List (
5183 Make_Assignment_Statement (Loc,
5184 Name => New_Reference_To (Counter_Id, Loc),
5186 Make_Op_Subtract (Loc,
5187 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5188 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5190 Else_Statements => New_List (Fin_Stmt));
5192 -- Generate all finalization loops starting from the innermost
5195 -- for Fnn in reverse V'Range (Dim) loop
5199 F := Last (Final_List);
5201 while Present (F) and then Dim > 0 loop
5207 Make_Loop_Statement (Loc,
5209 Make_Iteration_Scheme (Loc,
5210 Loop_Parameter_Specification =>
5211 Make_Loop_Parameter_Specification (Loc,
5212 Defining_Identifier => Loop_Id,
5213 Discrete_Subtype_Definition =>
5214 Make_Attribute_Reference (Loc,
5215 Prefix => Make_Identifier (Loc, Name_V),
5216 Attribute_Name => Name_Range,
5217 Expressions => New_List (
5218 Make_Integer_Literal (Loc, Dim))),
5220 Reverse_Present => True)),
5222 Statements => New_List (Final_Loop),
5223 End_Label => Empty);
5228 -- Generate the block which contains the finalization loops, the
5229 -- declarations of the abort flag, the exception occurrence, the
5230 -- raised flag and the conditional raise.
5233 -- Abort : constant Boolean :=
5234 -- Exception_Occurrence (Get_Current_Excep.all.all) =
5235 -- Standard'Abort_Signal'Identity;
5237 -- Abort : constant Boolean := False; -- no abort
5239 -- E : Exception_Occurrence;
5240 -- Raised : Boolean := False;
5246 -- V'Length (N) - Counter;
5250 -- if Raised then -- Exception handlers allowed
5251 -- Raise_From_Controlled_Operation (E, Abort);
5254 -- raise; -- Exception handlers allowed
5257 Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5259 if Exceptions_OK then
5261 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
5262 Append_To (Stmts, Make_Raise_Statement (Loc));
5266 Make_Block_Statement (Loc,
5268 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
5269 Handled_Statement_Sequence =>
5270 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5272 -- Generate the block which contains the initialization call and
5273 -- the partial finalization code.
5276 -- [Deep_]Initialize (V (J1, ..., JN));
5278 -- Counter := Counter + 1;
5282 -- <finalization code>
5286 Make_Block_Statement (Loc,
5287 Handled_Statement_Sequence =>
5288 Make_Handled_Sequence_Of_Statements (Loc,
5289 Statements => New_List (Build_Initialization_Call),
5290 Exception_Handlers => New_List (
5291 Make_Exception_Handler (Loc,
5292 Exception_Choices => New_List (Make_Others_Choice (Loc)),
5293 Statements => New_List (Final_Block)))));
5295 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5296 Make_Assignment_Statement (Loc,
5297 Name => New_Reference_To (Counter_Id, Loc),
5300 Left_Opnd => New_Reference_To (Counter_Id, Loc),
5301 Right_Opnd => Make_Integer_Literal (Loc, 1))));
5303 -- Generate all initialization loops starting from the innermost
5306 -- for Jnn in V'Range (Dim) loop
5310 J := Last (Index_List);
5312 while Present (J) and then Dim > 0 loop
5318 Make_Loop_Statement (Loc,
5320 Make_Iteration_Scheme (Loc,
5321 Loop_Parameter_Specification =>
5322 Make_Loop_Parameter_Specification (Loc,
5323 Defining_Identifier => Loop_Id,
5324 Discrete_Subtype_Definition =>
5325 Make_Attribute_Reference (Loc,
5326 Prefix => Make_Identifier (Loc, Name_V),
5327 Attribute_Name => Name_Range,
5328 Expressions => New_List (
5329 Make_Integer_Literal (Loc, Dim))))),
5331 Statements => New_List (Init_Loop),
5332 End_Label => Empty);
5337 -- Generate the block which contains the counter variable and the
5338 -- initialization loops.
5341 -- Counter : Integer := 0;
5348 Make_Block_Statement (Loc,
5349 Declarations => New_List (
5350 Make_Object_Declaration (Loc,
5351 Defining_Identifier => Counter_Id,
5352 Object_Definition =>
5353 New_Reference_To (Standard_Integer, Loc),
5354 Expression => Make_Integer_Literal (Loc, 0))),
5356 Handled_Statement_Sequence =>
5357 Make_Handled_Sequence_Of_Statements (Loc,
5358 Statements => New_List (Init_Loop))));
5359 end Build_Initialize_Statements;
5361 -----------------------
5362 -- New_References_To --
5363 -----------------------
5365 function New_References_To
5367 Loc : Source_Ptr) return List_Id
5369 Refs : constant List_Id := New_List;
5374 while Present (Id) loop
5375 Append_To (Refs, New_Reference_To (Id, Loc));
5380 end New_References_To;
5382 -- Start of processing for Make_Deep_Array_Body
5386 when Address_Case =>
5387 return Make_Finalize_Address_Stmts (Typ);
5391 return Build_Adjust_Or_Finalize_Statements (Typ);
5393 when Initialize_Case =>
5394 return Build_Initialize_Statements (Typ);
5396 end Make_Deep_Array_Body;
5398 --------------------
5399 -- Make_Deep_Proc --
5400 --------------------
5402 function Make_Deep_Proc
5403 (Prim : Final_Primitives;
5405 Stmts : List_Id) return Entity_Id
5407 Loc : constant Source_Ptr := Sloc (Typ);
5409 Proc_Id : Entity_Id;
5412 -- Create the object formal, generate:
5413 -- V : System.Address
5415 if Prim = Address_Case then
5416 Formals := New_List (
5417 Make_Parameter_Specification (Loc,
5418 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5419 Parameter_Type => New_Reference_To (RTE (RE_Address), Loc)));
5426 Formals := New_List (
5427 Make_Parameter_Specification (Loc,
5428 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5430 Out_Present => True,
5431 Parameter_Type => New_Reference_To (Typ, Loc)));
5433 -- F : Boolean := True
5435 if Prim = Adjust_Case
5436 or else Prim = Finalize_Case
5439 Make_Parameter_Specification (Loc,
5440 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5442 New_Reference_To (Standard_Boolean, Loc),
5444 New_Reference_To (Standard_True, Loc)));
5449 Make_Defining_Identifier (Loc,
5450 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5453 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5456 -- exception -- Finalize and Adjust cases only
5457 -- raise Program_Error;
5458 -- end Deep_Initialize / Adjust / Finalize;
5462 -- procedure Finalize_Address (V : System.Address) is
5465 -- end Finalize_Address;
5468 Make_Subprogram_Body (Loc,
5470 Make_Procedure_Specification (Loc,
5471 Defining_Unit_Name => Proc_Id,
5472 Parameter_Specifications => Formals),
5474 Declarations => Empty_List,
5476 Handled_Statement_Sequence =>
5477 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
5482 ---------------------------
5483 -- Make_Deep_Record_Body --
5484 ---------------------------
5486 function Make_Deep_Record_Body
5487 (Prim : Final_Primitives;
5489 Is_Local : Boolean := False) return List_Id
5491 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
5492 -- Build the statements necessary to adjust a record type. The type may
5493 -- have discriminants and contain variant parts. Generate:
5496 -- Root_Controlled (V).Finalized := False;
5499 -- [Deep_]Adjust (V.Comp_1);
5501 -- when Id : others =>
5502 -- if not Raised then
5504 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5509 -- [Deep_]Adjust (V.Comp_N);
5511 -- when Id : others =>
5512 -- if not Raised then
5514 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5519 -- Deep_Adjust (V._parent, False); -- If applicable
5521 -- when Id : others =>
5522 -- if not Raised then
5524 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5530 -- Adjust (V); -- If applicable
5533 -- if not Raised then
5535 -- Save_Occurence (E, Get_Current_Excep.all.all);
5541 -- Raise_From_Controlled_Object (E, Abort);
5545 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
5546 -- Build the statements necessary to finalize a record type. The type
5547 -- may have discriminants and contain variant parts. Generate:
5550 -- Temp : constant Exception_Occurrence_Access :=
5551 -- Get_Current_Excep.all;
5552 -- Abort : constant Boolean :=
5554 -- and then Exception_Identity (Temp_Id.all) =
5555 -- Standard'Abort_Signal'Identity;
5557 -- Abort : constant Boolean := False; -- no abort
5558 -- E : Exception_Occurence;
5559 -- Raised : Boolean := False;
5562 -- if Root_Controlled (V).Finalized then
5568 -- Finalize (V); -- If applicable
5571 -- if not Raised then
5573 -- Save_Occurence (E, Get_Current_Excep.all.all);
5578 -- case Variant_1 is
5580 -- case State_Counter_N => -- If Is_Local is enabled
5590 -- <<LN>> -- If Is_Local is enabled
5592 -- [Deep_]Finalize (V.Comp_N);
5595 -- if not Raised then
5597 -- Save_Occurence (E, Get_Current_Excep.all.all);
5603 -- [Deep_]Finalize (V.Comp_1);
5606 -- if not Raised then
5608 -- Save_Occurence (E, Get_Current_Excep.all.all);
5614 -- case State_Counter_1 => -- If Is_Local is enabled
5620 -- Deep_Finalize (V._parent, False); -- If applicable
5622 -- when Id : others =>
5623 -- if not Raised then
5625 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5629 -- Root_Controlled (V).Finalized := True;
5632 -- Raise_From_Controlled_Object (E, Abort);
5636 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
5637 -- Given a derived tagged type Typ, traverse all components, find field
5638 -- _parent and return its type.
5640 procedure Preprocess_Components
5642 Num_Comps : out Int;
5643 Has_POC : out Boolean);
5644 -- Examine all components in component list Comps, count all controlled
5645 -- components and determine whether at least one of them is per-object
5646 -- constrained. Component _parent is always skipped.
5648 -----------------------------
5649 -- Build_Adjust_Statements --
5650 -----------------------------
5652 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
5653 Loc : constant Source_Ptr := Sloc (Typ);
5654 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
5655 Abort_Id : Entity_Id := Empty;
5656 Bod_Stmts : List_Id;
5657 E_Id : Entity_Id := Empty;
5658 Raised_Id : Entity_Id := Empty;
5662 Exceptions_OK : constant Boolean :=
5663 not Restriction_Active (No_Exception_Propagation);
5665 function Process_Component_List_For_Adjust
5666 (Comps : Node_Id) return List_Id;
5667 -- Build all necessary adjust statements for a single component list
5669 ---------------------------------------
5670 -- Process_Component_List_For_Adjust --
5671 ---------------------------------------
5673 function Process_Component_List_For_Adjust
5674 (Comps : Node_Id) return List_Id
5676 Stmts : constant List_Id := New_List;
5678 Decl_Id : Entity_Id;
5679 Decl_Typ : Entity_Id;
5683 procedure Process_Component_For_Adjust (Decl : Node_Id);
5684 -- Process the declaration of a single controlled component
5686 ----------------------------------
5687 -- Process_Component_For_Adjust --
5688 ----------------------------------
5690 procedure Process_Component_For_Adjust (Decl : Node_Id) is
5691 Id : constant Entity_Id := Defining_Identifier (Decl);
5692 Typ : constant Entity_Id := Etype (Id);
5697 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
5699 -- begin -- Exception handlers allowed
5700 -- [Deep_]Adjust (V.Id);
5703 -- if not Raised then
5705 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5712 Make_Selected_Component (Loc,
5713 Prefix => Make_Identifier (Loc, Name_V),
5714 Selector_Name => Make_Identifier (Loc, Chars (Id))),
5717 if Exceptions_OK then
5719 Make_Block_Statement (Loc,
5720 Handled_Statement_Sequence =>
5721 Make_Handled_Sequence_Of_Statements (Loc,
5722 Statements => New_List (Adj_Stmt),
5723 Exception_Handlers => New_List (
5724 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
5727 Append_To (Stmts, Adj_Stmt);
5728 end Process_Component_For_Adjust;
5730 -- Start of processing for Process_Component_List_For_Adjust
5733 -- Perform an initial check, determine the number of controlled
5734 -- components in the current list and whether at least one of them
5735 -- is per-object constrained.
5737 Preprocess_Components (Comps, Num_Comps, Has_POC);
5739 -- The processing in this routine is done in the following order:
5740 -- 1) Regular components
5741 -- 2) Per-object constrained components
5744 if Num_Comps > 0 then
5746 -- Process all regular components in order of declarations
5748 Decl := First_Non_Pragma (Component_Items (Comps));
5749 while Present (Decl) loop
5750 Decl_Id := Defining_Identifier (Decl);
5751 Decl_Typ := Etype (Decl_Id);
5753 -- Skip _parent as well as per-object constrained components
5755 if Chars (Decl_Id) /= Name_uParent
5756 and then Needs_Finalization (Decl_Typ)
5758 if Has_Access_Constraint (Decl_Id)
5759 and then No (Expression (Decl))
5763 Process_Component_For_Adjust (Decl);
5767 Next_Non_Pragma (Decl);
5770 -- Process all per-object constrained components in order of
5774 Decl := First_Non_Pragma (Component_Items (Comps));
5775 while Present (Decl) loop
5776 Decl_Id := Defining_Identifier (Decl);
5777 Decl_Typ := Etype (Decl_Id);
5781 if Chars (Decl_Id) /= Name_uParent
5782 and then Needs_Finalization (Decl_Typ)
5783 and then Has_Access_Constraint (Decl_Id)
5784 and then No (Expression (Decl))
5786 Process_Component_For_Adjust (Decl);
5789 Next_Non_Pragma (Decl);
5794 -- Process all variants, if any
5797 if Present (Variant_Part (Comps)) then
5799 Var_Alts : constant List_Id := New_List;
5803 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
5804 while Present (Var) loop
5807 -- when <discrete choices> =>
5808 -- <adjust statements>
5810 Append_To (Var_Alts,
5811 Make_Case_Statement_Alternative (Loc,
5813 New_Copy_List (Discrete_Choices (Var)),
5815 Process_Component_List_For_Adjust (
5816 Component_List (Var))));
5818 Next_Non_Pragma (Var);
5822 -- case V.<discriminant> is
5823 -- when <discrete choices 1> =>
5824 -- <adjust statements 1>
5826 -- when <discrete choices N> =>
5827 -- <adjust statements N>
5831 Make_Case_Statement (Loc,
5833 Make_Selected_Component (Loc,
5834 Prefix => Make_Identifier (Loc, Name_V),
5836 Make_Identifier (Loc,
5837 Chars => Chars (Name (Variant_Part (Comps))))),
5838 Alternatives => Var_Alts);
5842 -- Add the variant case statement to the list of statements
5844 if Present (Var_Case) then
5845 Append_To (Stmts, Var_Case);
5848 -- If the component list did not have any controlled components
5849 -- nor variants, return null.
5851 if Is_Empty_List (Stmts) then
5852 Append_To (Stmts, Make_Null_Statement (Loc));
5856 end Process_Component_List_For_Adjust;
5858 -- Start of processing for Build_Adjust_Statements
5861 if Exceptions_OK then
5862 Abort_Id := Make_Temporary (Loc, 'A');
5863 E_Id := Make_Temporary (Loc, 'E');
5864 Raised_Id := Make_Temporary (Loc, 'R');
5867 if Nkind (Typ_Def) = N_Derived_Type_Definition then
5868 Rec_Def := Record_Extension_Part (Typ_Def);
5873 -- Create an adjust sequence for all record components
5875 if Present (Component_List (Rec_Def)) then
5877 Process_Component_List_For_Adjust (Component_List (Rec_Def));
5880 -- A derived record type must adjust all inherited components. This
5881 -- action poses the following problem:
5883 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
5888 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
5890 -- Deep_Adjust (Obj._parent);
5895 -- Adjusting the derived type will invoke Adjust of the parent and
5896 -- then that of the derived type. This is undesirable because both
5897 -- routines may modify shared components. Only the Adjust of the
5898 -- derived type should be invoked.
5900 -- To prevent this double adjustment of shared components,
5901 -- Deep_Adjust uses a flag to control the invocation of Adjust:
5903 -- procedure Deep_Adjust
5904 -- (Obj : in out Some_Type;
5905 -- Flag : Boolean := True)
5913 -- When Deep_Adjust is invokes for field _parent, a value of False is
5914 -- provided for the flag:
5916 -- Deep_Adjust (Obj._parent, False);
5918 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
5920 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
5925 if Needs_Finalization (Par_Typ) then
5929 Make_Selected_Component (Loc,
5930 Prefix => Make_Identifier (Loc, Name_V),
5932 Make_Identifier (Loc, Name_uParent)),
5934 For_Parent => True);
5937 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
5939 -- begin -- Exceptions OK
5940 -- Deep_Adjust (V._parent, False);
5942 -- when Id : others =>
5943 -- if not Raised then
5945 -- Save_Occurrence (E,
5946 -- Get_Current_Excep.all.all);
5950 if Present (Call) then
5953 if Exceptions_OK then
5955 Make_Block_Statement (Loc,
5956 Handled_Statement_Sequence =>
5957 Make_Handled_Sequence_Of_Statements (Loc,
5958 Statements => New_List (Adj_Stmt),
5959 Exception_Handlers => New_List (
5960 Build_Exception_Handler
5961 (Loc, E_Id, Raised_Id))));
5964 Prepend_To (Bod_Stmts, Adj_Stmt);
5970 -- Adjust the object. This action must be performed last after all
5971 -- components have been adjusted.
5973 if Is_Controlled (Typ) then
5979 Proc := Find_Prim_Op (Typ, Name_Adjust);
5983 -- Adjust (V); -- No_Exception_Propagation
5985 -- begin -- Exception handlers allowed
5989 -- if not Raised then
5991 -- Save_Occurrence (E,
5992 -- Get_Current_Excep.all.all);
5997 if Present (Proc) then
5999 Make_Procedure_Call_Statement (Loc,
6000 Name => New_Reference_To (Proc, Loc),
6001 Parameter_Associations => New_List (
6002 Make_Identifier (Loc, Name_V)));
6004 if Exceptions_OK then
6006 Make_Block_Statement (Loc,
6007 Handled_Statement_Sequence =>
6008 Make_Handled_Sequence_Of_Statements (Loc,
6009 Statements => New_List (Adj_Stmt),
6010 Exception_Handlers => New_List (
6011 Build_Exception_Handler
6012 (Loc, E_Id, Raised_Id))));
6015 Append_To (Bod_Stmts,
6016 Make_If_Statement (Loc,
6017 Condition => Make_Identifier (Loc, Name_F),
6018 Then_Statements => New_List (Adj_Stmt)));
6023 -- At this point either all adjustment statements have been generated
6024 -- or the type is not controlled.
6026 if Is_Empty_List (Bod_Stmts) then
6027 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6033 -- Abort : constant Boolean :=
6034 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6035 -- Standard'Abort_Signal'Identity;
6037 -- Abort : constant Boolean := False; -- no abort
6039 -- E : Exception_Occurence;
6040 -- Raised : Boolean := False;
6043 -- Root_Controlled (V).Finalized := False;
6045 -- <adjust statements>
6048 -- Raise_From_Controlled_Operation (E, Abort);
6053 if Exceptions_OK then
6054 Append_To (Bod_Stmts,
6055 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6060 Make_Block_Statement (Loc,
6062 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6063 Handled_Statement_Sequence =>
6064 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6066 end Build_Adjust_Statements;
6068 -------------------------------
6069 -- Build_Finalize_Statements --
6070 -------------------------------
6072 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6073 Loc : constant Source_Ptr := Sloc (Typ);
6074 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
6075 Abort_Id : Entity_Id := Empty;
6076 Bod_Stmts : List_Id;
6078 E_Id : Entity_Id := Empty;
6079 Raised_Id : Entity_Id := Empty;
6083 Exceptions_OK : constant Boolean :=
6084 not Restriction_Active (No_Exception_Propagation);
6086 function Process_Component_List_For_Finalize
6087 (Comps : Node_Id) return List_Id;
6088 -- Build all necessary finalization statements for a single component
6089 -- list. The statements may include a jump circuitry if flag Is_Local
6092 -----------------------------------------
6093 -- Process_Component_List_For_Finalize --
6094 -----------------------------------------
6096 function Process_Component_List_For_Finalize
6097 (Comps : Node_Id) return List_Id
6100 Counter_Id : Entity_Id;
6102 Decl_Id : Entity_Id;
6103 Decl_Typ : Entity_Id;
6106 Jump_Block : Node_Id;
6108 Label_Id : Entity_Id;
6112 procedure Process_Component_For_Finalize
6117 -- Process the declaration of a single controlled component. If
6118 -- flag Is_Local is enabled, create the corresponding label and
6119 -- jump circuitry. Alts is the list of case alternatives, Decls
6120 -- is the top level declaration list where labels are declared
6121 -- and Stmts is the list of finalization actions.
6123 ------------------------------------
6124 -- Process_Component_For_Finalize --
6125 ------------------------------------
6127 procedure Process_Component_For_Finalize
6133 Id : constant Entity_Id := Defining_Identifier (Decl);
6134 Typ : constant Entity_Id := Etype (Id);
6141 Label_Id : Entity_Id;
6148 Make_Identifier (Loc,
6149 Chars => New_External_Name ('L', Num_Comps));
6150 Set_Entity (Label_Id,
6151 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6152 Label := Make_Label (Loc, Label_Id);
6155 Make_Implicit_Label_Declaration (Loc,
6156 Defining_Identifier => Entity (Label_Id),
6157 Label_Construct => Label));
6164 Make_Case_Statement_Alternative (Loc,
6165 Discrete_Choices => New_List (
6166 Make_Integer_Literal (Loc, Num_Comps)),
6168 Statements => New_List (
6169 Make_Goto_Statement (Loc,
6171 New_Reference_To (Entity (Label_Id), Loc)))));
6176 Append_To (Stmts, Label);
6178 -- Decrease the number of components to be processed.
6179 -- This action yields a new Label_Id in future calls.
6181 Num_Comps := Num_Comps - 1;
6186 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6188 -- begin -- Exception handlers allowed
6189 -- [Deep_]Finalize (V.Id);
6192 -- if not Raised then
6194 -- Save_Occurrence (E,
6195 -- Get_Current_Excep.all.all);
6202 Make_Selected_Component (Loc,
6203 Prefix => Make_Identifier (Loc, Name_V),
6204 Selector_Name => Make_Identifier (Loc, Chars (Id))),
6207 if not Restriction_Active (No_Exception_Propagation) then
6209 Make_Block_Statement (Loc,
6210 Handled_Statement_Sequence =>
6211 Make_Handled_Sequence_Of_Statements (Loc,
6212 Statements => New_List (Fin_Stmt),
6213 Exception_Handlers => New_List (
6214 Build_Exception_Handler (Loc, E_Id, Raised_Id))));
6217 Append_To (Stmts, Fin_Stmt);
6218 end Process_Component_For_Finalize;
6220 -- Start of processing for Process_Component_List_For_Finalize
6223 -- Perform an initial check, look for controlled and per-object
6224 -- constrained components.
6226 Preprocess_Components (Comps, Num_Comps, Has_POC);
6228 -- Create a state counter to service the current component list.
6229 -- This step is performed before the variants are inspected in
6230 -- order to generate the same state counter names as those from
6231 -- Build_Initialize_Statements.
6236 Counter := Counter + 1;
6239 Make_Defining_Identifier (Loc,
6240 Chars => New_External_Name ('C', Counter));
6243 -- Process the component in the following order:
6245 -- 2) Per-object constrained components
6246 -- 3) Regular components
6248 -- Start with the variant parts
6251 if Present (Variant_Part (Comps)) then
6253 Var_Alts : constant List_Id := New_List;
6257 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6258 while Present (Var) loop
6261 -- when <discrete choices> =>
6262 -- <finalize statements>
6264 Append_To (Var_Alts,
6265 Make_Case_Statement_Alternative (Loc,
6267 New_Copy_List (Discrete_Choices (Var)),
6269 Process_Component_List_For_Finalize (
6270 Component_List (Var))));
6272 Next_Non_Pragma (Var);
6276 -- case V.<discriminant> is
6277 -- when <discrete choices 1> =>
6278 -- <finalize statements 1>
6280 -- when <discrete choices N> =>
6281 -- <finalize statements N>
6285 Make_Case_Statement (Loc,
6287 Make_Selected_Component (Loc,
6288 Prefix => Make_Identifier (Loc, Name_V),
6290 Make_Identifier (Loc,
6291 Chars => Chars (Name (Variant_Part (Comps))))),
6292 Alternatives => Var_Alts);
6296 -- The current component list does not have a single controlled
6297 -- component, however it may contain variants. Return the case
6298 -- statement for the variants or nothing.
6300 if Num_Comps = 0 then
6301 if Present (Var_Case) then
6302 return New_List (Var_Case);
6304 return New_List (Make_Null_Statement (Loc));
6308 -- Prepare all lists
6314 -- Process all per-object constrained components in reverse order
6317 Decl := Last_Non_Pragma (Component_Items (Comps));
6318 while Present (Decl) loop
6319 Decl_Id := Defining_Identifier (Decl);
6320 Decl_Typ := Etype (Decl_Id);
6324 if Chars (Decl_Id) /= Name_uParent
6325 and then Needs_Finalization (Decl_Typ)
6326 and then Has_Access_Constraint (Decl_Id)
6327 and then No (Expression (Decl))
6329 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6332 Prev_Non_Pragma (Decl);
6336 -- Process the rest of the components in reverse order
6338 Decl := Last_Non_Pragma (Component_Items (Comps));
6339 while Present (Decl) loop
6340 Decl_Id := Defining_Identifier (Decl);
6341 Decl_Typ := Etype (Decl_Id);
6345 if Chars (Decl_Id) /= Name_uParent
6346 and then Needs_Finalization (Decl_Typ)
6348 -- Skip per-object constrained components since they were
6349 -- handled in the above step.
6351 if Has_Access_Constraint (Decl_Id)
6352 and then No (Expression (Decl))
6356 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6360 Prev_Non_Pragma (Decl);
6365 -- LN : label; -- If Is_Local is enabled
6370 -- case CounterX is .
6380 -- <<LN>> -- If Is_Local is enabled
6382 -- [Deep_]Finalize (V.CompY);
6384 -- when Id : others =>
6385 -- if not Raised then
6387 -- Save_Occurrence (E,
6388 -- Get_Current_Excep.all.all);
6392 -- <<L0>> -- If Is_Local is enabled
6397 -- Add the declaration of default jump location L0, its
6398 -- corresponding alternative and its place in the statements.
6400 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6401 Set_Entity (Label_Id,
6402 Make_Defining_Identifier (Loc, Chars (Label_Id)));
6403 Label := Make_Label (Loc, Label_Id);
6405 Append_To (Decls, -- declaration
6406 Make_Implicit_Label_Declaration (Loc,
6407 Defining_Identifier => Entity (Label_Id),
6408 Label_Construct => Label));
6410 Append_To (Alts, -- alternative
6411 Make_Case_Statement_Alternative (Loc,
6412 Discrete_Choices => New_List (
6413 Make_Others_Choice (Loc)),
6415 Statements => New_List (
6416 Make_Goto_Statement (Loc,
6417 Name => New_Reference_To (Entity (Label_Id), Loc)))));
6419 Append_To (Stmts, Label); -- statement
6421 -- Create the jump block
6424 Make_Case_Statement (Loc,
6425 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
6426 Alternatives => Alts));
6430 Make_Block_Statement (Loc,
6431 Declarations => Decls,
6432 Handled_Statement_Sequence =>
6433 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6435 if Present (Var_Case) then
6436 return New_List (Var_Case, Jump_Block);
6438 return New_List (Jump_Block);
6440 end Process_Component_List_For_Finalize;
6442 -- Start of processing for Build_Finalize_Statements
6445 if Exceptions_OK then
6446 Abort_Id := Make_Temporary (Loc, 'A');
6447 E_Id := Make_Temporary (Loc, 'E');
6448 Raised_Id := Make_Temporary (Loc, 'R');
6451 if Nkind (Typ_Def) = N_Derived_Type_Definition then
6452 Rec_Def := Record_Extension_Part (Typ_Def);
6457 -- Create a finalization sequence for all record components
6459 if Present (Component_List (Rec_Def)) then
6461 Process_Component_List_For_Finalize (Component_List (Rec_Def));
6464 -- A derived record type must finalize all inherited components. This
6465 -- action poses the following problem:
6467 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6472 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6474 -- Deep_Finalize (Obj._parent);
6479 -- Finalizing the derived type will invoke Finalize of the parent and
6480 -- then that of the derived type. This is undesirable because both
6481 -- routines may modify shared components. Only the Finalize of the
6482 -- derived type should be invoked.
6484 -- To prevent this double adjustment of shared components,
6485 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6487 -- procedure Deep_Finalize
6488 -- (Obj : in out Some_Type;
6489 -- Flag : Boolean := True)
6497 -- When Deep_Finalize is invokes for field _parent, a value of False
6498 -- is provided for the flag:
6500 -- Deep_Finalize (Obj._parent, False);
6502 if Is_Tagged_Type (Typ)
6503 and then Is_Derived_Type (Typ)
6506 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
6511 if Needs_Finalization (Par_Typ) then
6515 Make_Selected_Component (Loc,
6516 Prefix => Make_Identifier (Loc, Name_V),
6518 Make_Identifier (Loc, Name_uParent)),
6520 For_Parent => True);
6523 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
6525 -- begin -- Exceptions OK
6526 -- Deep_Finalize (V._parent, False);
6528 -- when Id : others =>
6529 -- if not Raised then
6531 -- Save_Occurrence (E,
6532 -- Get_Current_Excep.all.all);
6536 if Present (Call) then
6539 if Exceptions_OK then
6541 Make_Block_Statement (Loc,
6542 Handled_Statement_Sequence =>
6543 Make_Handled_Sequence_Of_Statements (Loc,
6544 Statements => New_List (Fin_Stmt),
6545 Exception_Handlers => New_List (
6546 Build_Exception_Handler
6547 (Loc, E_Id, Raised_Id))));
6550 Append_To (Bod_Stmts, Fin_Stmt);
6556 -- Finalize the object. This action must be performed first before
6557 -- all components have been finalized.
6559 if Is_Controlled (Typ)
6560 and then not Is_Local
6567 Proc := Find_Prim_Op (Typ, Name_Finalize);
6571 -- Finalize (V); -- No_Exception_Propagation
6577 -- if not Raised then
6579 -- Save_Occurrence (E,
6580 -- Get_Current_Excep.all.all);
6585 if Present (Proc) then
6587 Make_Procedure_Call_Statement (Loc,
6588 Name => New_Reference_To (Proc, Loc),
6589 Parameter_Associations => New_List (
6590 Make_Identifier (Loc, Name_V)));
6592 if Exceptions_OK then
6594 Make_Block_Statement (Loc,
6595 Handled_Statement_Sequence =>
6596 Make_Handled_Sequence_Of_Statements (Loc,
6597 Statements => New_List (Fin_Stmt),
6598 Exception_Handlers => New_List (
6599 Build_Exception_Handler
6600 (Loc, E_Id, Raised_Id))));
6603 Prepend_To (Bod_Stmts,
6604 Make_If_Statement (Loc,
6605 Condition => Make_Identifier (Loc, Name_F),
6606 Then_Statements => New_List (Fin_Stmt)));
6611 -- At this point either all finalization statements have been
6612 -- generated or the type is not controlled.
6614 if No (Bod_Stmts) then
6615 return New_List (Make_Null_Statement (Loc));
6619 -- Abort : constant Boolean :=
6620 -- Exception_Occurrence (Get_Current_Excep.all.all) =
6621 -- Standard'Abort_Signal'Identity;
6623 -- Abort : constant Boolean := False; -- no abort
6625 -- E : Exception_Occurence;
6626 -- Raised : Boolean := False;
6629 -- if V.Finalized then
6633 -- <finalize statements>
6634 -- V.Finalized := True;
6637 -- Raise_From_Controlled_Operation (E, Abort);
6642 if Exceptions_OK then
6643 Append_To (Bod_Stmts,
6644 Build_Raise_Statement (Loc, Abort_Id, E_Id, Raised_Id));
6649 Make_Block_Statement (Loc,
6651 Build_Object_Declarations (Loc, Abort_Id, E_Id, Raised_Id),
6652 Handled_Statement_Sequence =>
6653 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6655 end Build_Finalize_Statements;
6657 -----------------------
6658 -- Parent_Field_Type --
6659 -----------------------
6661 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
6665 Field := First_Entity (Typ);
6666 while Present (Field) loop
6667 if Chars (Field) = Name_uParent then
6668 return Etype (Field);
6671 Next_Entity (Field);
6674 -- A derived tagged type should always have a parent field
6676 raise Program_Error;
6677 end Parent_Field_Type;
6679 ---------------------------
6680 -- Preprocess_Components --
6681 ---------------------------
6683 procedure Preprocess_Components
6685 Num_Comps : out Int;
6686 Has_POC : out Boolean)
6696 Decl := First_Non_Pragma (Component_Items (Comps));
6697 while Present (Decl) loop
6698 Id := Defining_Identifier (Decl);
6701 -- Skip field _parent
6703 if Chars (Id) /= Name_uParent
6704 and then Needs_Finalization (Typ)
6706 Num_Comps := Num_Comps + 1;
6708 if Has_Access_Constraint (Id)
6709 and then No (Expression (Decl))
6715 Next_Non_Pragma (Decl);
6717 end Preprocess_Components;
6719 -- Start of processing for Make_Deep_Record_Body
6723 when Address_Case =>
6724 return Make_Finalize_Address_Stmts (Typ);
6727 return Build_Adjust_Statements (Typ);
6729 when Finalize_Case =>
6730 return Build_Finalize_Statements (Typ);
6732 when Initialize_Case =>
6734 Loc : constant Source_Ptr := Sloc (Typ);
6737 if Is_Controlled (Typ) then
6739 Make_Procedure_Call_Statement (Loc,
6742 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
6743 Parameter_Associations => New_List (
6744 Make_Identifier (Loc, Name_V))));
6750 end Make_Deep_Record_Body;
6752 ----------------------
6753 -- Make_Final_Call --
6754 ----------------------
6756 function Make_Final_Call
6759 For_Parent : Boolean := False) return Node_Id
6761 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6763 Fin_Id : Entity_Id := Empty;
6768 -- Recover the proper type which contains [Deep_]Finalize
6770 if Is_Class_Wide_Type (Typ) then
6771 Utyp := Root_Type (Typ);
6775 elsif Is_Concurrent_Type (Typ) then
6776 Utyp := Corresponding_Record_Type (Typ);
6778 Ref := Convert_Concurrent (Obj_Ref, Typ);
6780 elsif Is_Private_Type (Typ)
6781 and then Present (Full_View (Typ))
6782 and then Is_Concurrent_Type (Full_View (Typ))
6784 Utyp := Corresponding_Record_Type (Full_View (Typ));
6786 Ref := Convert_Concurrent (Obj_Ref, Full_View (Typ));
6794 Utyp := Underlying_Type (Base_Type (Utyp));
6795 Set_Assignment_OK (Ref);
6797 -- Deal with non-tagged derivation of private views. If the parent type
6798 -- is a protected type, Deep_Finalize is found on the corresponding
6799 -- record of the ancestor.
6801 if Is_Untagged_Derivation (Typ) then
6802 if Is_Protected_Type (Typ) then
6803 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
6805 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6807 if Is_Protected_Type (Utyp) then
6808 Utyp := Corresponding_Record_Type (Utyp);
6812 Ref := Unchecked_Convert_To (Utyp, Ref);
6813 Set_Assignment_OK (Ref);
6816 -- Deal with derived private types which do not inherit primitives from
6817 -- their parents. In this case, [Deep_]Finalize can be found in the full
6818 -- view of the parent type.
6820 if Is_Tagged_Type (Utyp)
6821 and then Is_Derived_Type (Utyp)
6822 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
6823 and then Is_Private_Type (Etype (Utyp))
6824 and then Present (Full_View (Etype (Utyp)))
6826 Utyp := Full_View (Etype (Utyp));
6827 Ref := Unchecked_Convert_To (Utyp, Ref);
6828 Set_Assignment_OK (Ref);
6831 -- When dealing with the completion of a private type, use the base type
6834 if Utyp /= Base_Type (Utyp) then
6835 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
6837 Utyp := Base_Type (Utyp);
6838 Ref := Unchecked_Convert_To (Utyp, Ref);
6839 Set_Assignment_OK (Ref);
6842 -- Select the appropriate version of finalize
6845 if Has_Controlled_Component (Utyp) then
6846 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6849 -- Derivations from [Limited_]Controlled
6851 elsif Is_Controlled (Utyp) then
6852 if Has_Controlled_Component (Utyp) then
6853 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6855 Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
6858 -- Class-wide types, interfaces and types with controlled components
6860 elsif Is_Class_Wide_Type (Typ)
6861 or else Is_Interface (Typ)
6862 or else Has_Controlled_Component (Utyp)
6864 if Is_Tagged_Type (Utyp) then
6865 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6867 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
6872 elsif Is_Tagged_Type (Utyp) then
6873 Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6876 raise Program_Error;
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
6928 Loc : constant Source_Ptr := Sloc (Typ);
6929 Proc_Id : Entity_Id;
6932 -- Nothing to do if the type is not controlled or it already has a
6933 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
6934 -- come from source. These are usually generated for completeness and
6935 -- do not need the Finalize_Address primitive.
6937 if not Needs_Finalization (Typ)
6938 or else Is_Abstract_Type (Typ)
6939 or else Present (TSS (Typ, TSS_Finalize_Address))
6941 (Is_Class_Wide_Type (Typ)
6942 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
6943 and then not Comes_From_Source (Root_Type (Typ)))
6949 Make_Defining_Identifier (Loc,
6950 Make_TSS_Name (Typ, TSS_Finalize_Address));
6953 -- procedure <Typ>FD (V : System.Address) is
6956 -- type Pnn is access all Typ;
6957 -- for Pnn'Storage_Size use 0;
6959 -- [Deep_]Finalize (Pnn (V).all);
6964 Make_Subprogram_Body (Loc,
6966 Make_Procedure_Specification (Loc,
6967 Defining_Unit_Name => Proc_Id,
6969 Parameter_Specifications => New_List (
6970 Make_Parameter_Specification (Loc,
6971 Defining_Identifier =>
6972 Make_Defining_Identifier (Loc, Name_V),
6974 New_Reference_To (RTE (RE_Address), Loc)))),
6976 Declarations => No_List,
6978 Handled_Statement_Sequence =>
6979 Make_Handled_Sequence_Of_Statements (Loc,
6981 Make_Finalize_Address_Stmts (Typ))));
6983 Set_TSS (Typ, Proc_Id);
6984 end Make_Finalize_Address_Body;
6986 ---------------------------------
6987 -- Make_Finalize_Address_Stmts --
6988 ---------------------------------
6990 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
6991 Loc : constant Source_Ptr := Sloc (Typ);
6992 Ptr_Typ : constant Entity_Id := Make_Temporary (Loc, 'P');
6994 Desg_Typ : Entity_Id;
6997 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
6998 -- Subsidiary routine, generate the following attribute reference:
7000 -- Some_Typ'Alignment
7002 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id;
7003 -- Subsidiary routine, generate the following expression:
7005 -- 2 * Some_Typ'Alignment
7011 function Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
7014 Make_Attribute_Reference (Loc,
7015 Prefix => New_Reference_To (Some_Typ, Loc),
7016 Attribute_Name => Name_Alignment);
7019 -------------------------
7020 -- Double_Alignment_Of --
7021 -------------------------
7023 function Double_Alignment_Of (Some_Typ : Entity_Id) return Node_Id is
7026 Make_Op_Multiply (Loc,
7027 Left_Opnd => Make_Integer_Literal (Loc, 2),
7028 Right_Opnd => Alignment_Of (Some_Typ));
7029 end Double_Alignment_Of;
7031 -- Start of processing for Make_Finalize_Address_Stmts
7034 if Is_Array_Type (Typ) then
7035 if Is_Constrained (First_Subtype (Typ)) then
7036 Desg_Typ := First_Subtype (Typ);
7038 Desg_Typ := Base_Type (Typ);
7041 -- Class-wide types of constrained root types
7043 elsif Is_Class_Wide_Type (Typ)
7044 and then Has_Discriminants (Root_Type (Typ))
7046 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7049 Parent_Typ : Entity_Id := Root_Type (Typ);
7052 -- Climb the parent type chain looking for a non-constrained type
7054 while Parent_Typ /= Etype (Parent_Typ)
7055 and then Has_Discriminants (Parent_Typ)
7057 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7059 Parent_Typ := Etype (Parent_Typ);
7062 -- Handle views created for tagged types with unknown
7065 if Is_Underlying_Record_View (Parent_Typ) then
7066 Parent_Typ := Underlying_Record_View (Parent_Typ);
7069 Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
7079 -- type Ptr_Typ is access all Typ;
7080 -- for Ptr_Typ'Storage_Size use 0;
7083 Make_Full_Type_Declaration (Loc,
7084 Defining_Identifier => Ptr_Typ,
7086 Make_Access_To_Object_Definition (Loc,
7087 All_Present => True,
7088 Subtype_Indication => New_Reference_To (Desg_Typ, Loc))),
7090 Make_Attribute_Definition_Clause (Loc,
7091 Name => New_Reference_To (Ptr_Typ, Loc),
7092 Chars => Name_Storage_Size,
7093 Expression => Make_Integer_Literal (Loc, 0)));
7095 Obj_Expr := Make_Identifier (Loc, Name_V);
7097 -- Unconstrained arrays require special processing in order to retrieve
7098 -- the elements. To achieve this, we have to skip the dope vector which
7099 -- lays in front of the elements and then use a thin pointer to perform
7100 -- the address-to-access conversion.
7102 if Is_Array_Type (Typ)
7103 and then not Is_Constrained (First_Subtype (Typ))
7106 Dope_Expr : Node_Id;
7107 Dope_Id : Entity_Id;
7108 For_First : Boolean := True;
7110 Index_Typ : Entity_Id;
7113 -- Ensure that Ptr_Typ a thin pointer, generate:
7115 -- for Ptr_Typ'Size use System.Address'Size;
7118 Make_Attribute_Definition_Clause (Loc,
7119 Name => New_Reference_To (Ptr_Typ, Loc),
7122 Make_Integer_Literal (Loc, System_Address_Size)));
7124 -- For unconstrained arrays, create the expression which computes
7125 -- the size of the dope vector.
7127 Index := First_Index (Typ);
7128 while Present (Index) loop
7129 Index_Typ := Etype (Index);
7131 -- Each bound has two values and a potential hole added to
7132 -- compensate for alignment differences.
7138 -- 2 * Index_Typ'Alignment
7140 Dope_Expr := Double_Alignment_Of (Index_Typ);
7144 -- Dope_Expr + 2 * Index_Typ'Alignment
7148 Left_Opnd => Dope_Expr,
7149 Right_Opnd => Double_Alignment_Of (Index_Typ));
7155 -- Round the cumulative alignment to the next higher multiple of
7156 -- the array alignment. Generate:
7158 -- ((Dope_Expr + Typ'Alignment - 1) / Typ'Alignment)
7162 Make_Op_Multiply (Loc,
7164 Make_Op_Divide (Loc,
7167 Left_Opnd => Dope_Expr,
7169 Make_Op_Subtract (Loc,
7170 Left_Opnd => Alignment_Of (Typ),
7171 Right_Opnd => Make_Integer_Literal (Loc, 1))),
7172 Right_Opnd => Alignment_Of (Typ)),
7173 Right_Opnd => Alignment_Of (Typ));
7176 -- Dnn : Storage_Offset := Dope_Expr;
7178 Dope_Id := Make_Temporary (Loc, 'D');
7181 Make_Object_Declaration (Loc,
7182 Defining_Identifier => Dope_Id,
7183 Constant_Present => True,
7184 Object_Definition =>
7185 New_Reference_To (RTE (RE_Storage_Offset), Loc),
7186 Expression => Dope_Expr));
7188 -- Shift the address from the start of the dope vector to the
7189 -- start of the elements:
7193 -- Note that this is done through a wrapper routine since RTSfind
7194 -- cannot retrieve operations with string names of the form "+".
7197 Make_Function_Call (Loc,
7199 New_Reference_To (RTE (RE_Add_Offset_To_Address), Loc),
7200 Parameter_Associations => New_List (
7202 New_Reference_To (Dope_Id, Loc)));
7206 -- Create the block and the finalization call
7209 Make_Block_Statement (Loc,
7210 Declarations => Decls,
7212 Handled_Statement_Sequence =>
7213 Make_Handled_Sequence_Of_Statements (Loc,
7214 Statements => New_List (
7217 Make_Explicit_Dereference (Loc,
7218 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7219 Typ => Desg_Typ)))));
7220 end Make_Finalize_Address_Stmts;
7222 -------------------------------------
7223 -- Make_Handler_For_Ctrl_Operation --
7224 -------------------------------------
7228 -- when E : others =>
7229 -- Raise_From_Controlled_Operation (E, False);
7234 -- raise Program_Error [finalize raised exception];
7236 -- depending on whether Raise_From_Controlled_Operation is available
7238 function Make_Handler_For_Ctrl_Operation
7239 (Loc : Source_Ptr) return Node_Id
7242 -- Choice parameter (for the first case above)
7244 Raise_Node : Node_Id;
7245 -- Procedure call or raise statement
7248 -- Standard runtime, .NET/JVM targets: add choice parameter E and pass
7249 -- it to Raise_From_Controlled_Operation so that the original exception
7250 -- name and message can be recorded in the exception message for
7253 if RTE_Available (RE_Raise_From_Controlled_Operation) then
7254 E_Occ := Make_Defining_Identifier (Loc, Name_E);
7256 Make_Procedure_Call_Statement (Loc,
7259 (RTE (RE_Raise_From_Controlled_Operation), Loc),
7260 Parameter_Associations => New_List (
7261 New_Reference_To (E_Occ, Loc),
7262 New_Reference_To (Standard_False, Loc)));
7264 -- Restricted runtime: exception messages are not supported
7269 Make_Raise_Program_Error (Loc,
7270 Reason => PE_Finalize_Raised_Exception);
7274 Make_Implicit_Exception_Handler (Loc,
7275 Exception_Choices => New_List (Make_Others_Choice (Loc)),
7276 Choice_Parameter => E_Occ,
7277 Statements => New_List (Raise_Node));
7278 end Make_Handler_For_Ctrl_Operation;
7280 --------------------
7281 -- Make_Init_Call --
7282 --------------------
7284 function Make_Init_Call
7286 Typ : Entity_Id) return Node_Id
7288 Loc : constant Source_Ptr := Sloc (Obj_Ref);
7295 -- Deal with the type and object reference. Depending on the context, an
7296 -- object reference may need several conversions.
7298 if Is_Concurrent_Type (Typ) then
7300 Utyp := Corresponding_Record_Type (Typ);
7301 Ref := Convert_Concurrent (Obj_Ref, Typ);
7303 elsif Is_Private_Type (Typ)
7304 and then Present (Full_View (Typ))
7305 and then Is_Concurrent_Type (Underlying_Type (Typ))
7308 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
7309 Ref := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7317 Set_Assignment_OK (Ref);
7319 Utyp := Underlying_Type (Base_Type (Utyp));
7321 -- Deal with non-tagged derivation of private views
7323 if Is_Untagged_Derivation (Typ)
7324 and then not Is_Conc
7326 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7327 Ref := Unchecked_Convert_To (Utyp, Ref);
7329 -- The following is to prevent problems with UC see 1.156 RH ???
7331 Set_Assignment_OK (Ref);
7334 -- If the underlying_type is a subtype, then we are dealing with the
7335 -- completion of a private type. We need to access the base type and
7336 -- generate a conversion to it.
7338 if Utyp /= Base_Type (Utyp) then
7339 pragma Assert (Is_Private_Type (Typ));
7340 Utyp := Base_Type (Utyp);
7341 Ref := Unchecked_Convert_To (Utyp, Ref);
7344 -- Select the appropriate version of initialize
7346 if Has_Controlled_Component (Utyp) then
7347 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7349 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7350 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7353 -- The object reference may need another conversion depending on the
7354 -- type of the formal and that of the actual.
7356 Ref := Convert_View (Proc, Ref);
7359 -- [Deep_]Initialize (Ref);
7362 Make_Procedure_Call_Statement (Loc,
7364 New_Reference_To (Proc, Loc),
7365 Parameter_Associations => New_List (Ref));
7368 ------------------------------
7369 -- Make_Local_Deep_Finalize --
7370 ------------------------------
7372 function Make_Local_Deep_Finalize
7374 Nam : Entity_Id) return Node_Id
7376 Loc : constant Source_Ptr := Sloc (Typ);
7380 Formals := New_List (
7384 Make_Parameter_Specification (Loc,
7385 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7387 Out_Present => True,
7388 Parameter_Type => New_Reference_To (Typ, Loc)),
7390 -- F : Boolean := True
7392 Make_Parameter_Specification (Loc,
7393 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7394 Parameter_Type => New_Reference_To (Standard_Boolean, Loc),
7395 Expression => New_Reference_To (Standard_True, Loc)));
7397 -- Add the necessary number of counters to represent the initialization
7398 -- state of an object.
7401 Make_Subprogram_Body (Loc,
7403 Make_Procedure_Specification (Loc,
7404 Defining_Unit_Name => Nam,
7405 Parameter_Specifications => Formals),
7407 Declarations => No_List,
7409 Handled_Statement_Sequence =>
7410 Make_Handled_Sequence_Of_Statements (Loc,
7411 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7412 end Make_Local_Deep_Finalize;
7414 --------------------------
7415 -- Make_Transient_Block --
7416 --------------------------
7418 function Make_Transient_Block
7421 Par : Node_Id) return Node_Id
7423 Decls : constant List_Id := New_List;
7424 Instrs : constant List_Id := New_List (Action);
7429 -- Case where only secondary stack use is involved
7431 if VM_Target = No_VM
7432 and then Uses_Sec_Stack (Current_Scope)
7433 and then Nkind (Action) /= N_Simple_Return_Statement
7434 and then Nkind (Par) /= N_Exception_Handler
7440 S := Scope (Current_Scope);
7442 -- At the outer level, no need to release the sec stack
7444 if S = Standard_Standard then
7445 Set_Uses_Sec_Stack (Current_Scope, False);
7448 -- In a function, only release the sec stack if the
7449 -- function does not return on the sec stack otherwise
7450 -- the result may be lost. The caller is responsible for
7453 elsif Ekind (S) = E_Function then
7454 Set_Uses_Sec_Stack (Current_Scope, False);
7456 if not Requires_Transient_Scope (Etype (S)) then
7457 Set_Uses_Sec_Stack (S, True);
7458 Check_Restriction (No_Secondary_Stack, Action);
7463 -- In a loop or entry we should install a block encompassing
7464 -- all the construct. For now just release right away.
7466 elsif Ekind_In (S, E_Entry, E_Loop) then
7469 -- In a procedure or a block, we release on exit of the
7470 -- procedure or block. ??? memory leak can be created by
7473 elsif Ekind_In (S, E_Block, E_Procedure) then
7474 Set_Uses_Sec_Stack (S, True);
7475 Check_Restriction (No_Secondary_Stack, Action);
7476 Set_Uses_Sec_Stack (Current_Scope, False);
7486 -- Create the transient block. Set the parent now since the block itself
7487 -- is not part of the tree.
7490 Make_Block_Statement (Loc,
7491 Identifier => New_Reference_To (Current_Scope, Loc),
7492 Declarations => Decls,
7493 Handled_Statement_Sequence =>
7494 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7495 Has_Created_Identifier => True);
7496 Set_Parent (Block, Par);
7498 -- Insert actions stuck in the transient scopes as well as all freezing
7499 -- nodes needed by those actions.
7501 Insert_Actions_In_Scope_Around (Action);
7503 Insert := Prev (Action);
7504 if Present (Insert) then
7505 Freeze_All (First_Entity (Current_Scope), Insert);
7508 -- When the transient scope was established, we pushed the entry for
7509 -- the transient scope onto the scope stack, so that the scope was
7510 -- active for the installation of finalizable entities etc. Now we
7511 -- must remove this entry, since we have constructed a proper block.
7516 end Make_Transient_Block;
7518 ------------------------
7519 -- Node_To_Be_Wrapped --
7520 ------------------------
7522 function Node_To_Be_Wrapped return Node_Id is
7524 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
7525 end Node_To_Be_Wrapped;
7527 ----------------------------
7528 -- Set_Node_To_Be_Wrapped --
7529 ----------------------------
7531 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
7533 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
7534 end Set_Node_To_Be_Wrapped;
7536 ----------------------------------
7537 -- Store_After_Actions_In_Scope --
7538 ----------------------------------
7540 procedure Store_After_Actions_In_Scope (L : List_Id) is
7541 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7544 if Present (SE.Actions_To_Be_Wrapped_After) then
7545 Insert_List_Before_And_Analyze (
7546 First (SE.Actions_To_Be_Wrapped_After), L);
7549 SE.Actions_To_Be_Wrapped_After := L;
7551 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7552 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7554 Set_Parent (L, SE.Node_To_Be_Wrapped);
7559 end Store_After_Actions_In_Scope;
7561 -----------------------------------
7562 -- Store_Before_Actions_In_Scope --
7563 -----------------------------------
7565 procedure Store_Before_Actions_In_Scope (L : List_Id) is
7566 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7569 if Present (SE.Actions_To_Be_Wrapped_Before) then
7570 Insert_List_After_And_Analyze (
7571 Last (SE.Actions_To_Be_Wrapped_Before), L);
7574 SE.Actions_To_Be_Wrapped_Before := L;
7576 if Is_List_Member (SE.Node_To_Be_Wrapped) then
7577 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7579 Set_Parent (L, SE.Node_To_Be_Wrapped);
7584 end Store_Before_Actions_In_Scope;
7586 --------------------------------
7587 -- Wrap_Transient_Declaration --
7588 --------------------------------
7590 -- If a transient scope has been established during the processing of the
7591 -- Expression of an Object_Declaration, it is not possible to wrap the
7592 -- declaration into a transient block as usual case, otherwise the object
7593 -- would be itself declared in the wrong scope. Therefore, all entities (if
7594 -- any) defined in the transient block are moved to the proper enclosing
7595 -- scope, furthermore, if they are controlled variables they are finalized
7596 -- right after the declaration. The finalization list of the transient
7597 -- scope is defined as a renaming of the enclosing one so during their
7598 -- initialization they will be attached to the proper finalization list.
7599 -- For instance, the following declaration :
7601 -- X : Typ := F (G (A), G (B));
7603 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7604 -- is expanded into :
7606 -- X : Typ := [ complex Expression-Action ];
7607 -- [Deep_]Finalize (_v1);
7608 -- [Deep_]Finalize (_v2);
7610 procedure Wrap_Transient_Declaration (N : Node_Id) is
7617 Encl_S := Scope (S);
7619 -- Insert Actions kept in the Scope stack
7621 Insert_Actions_In_Scope_Around (N);
7623 -- If the declaration is consuming some secondary stack, mark the
7624 -- enclosing scope appropriately.
7626 Uses_SS := Uses_Sec_Stack (S);
7629 -- Put the local entities back in the enclosing scope, and set the
7630 -- Is_Public flag appropriately.
7632 Transfer_Entities (S, Encl_S);
7634 -- Mark the enclosing dynamic scope so that the sec stack will be
7635 -- released upon its exit unless this is a function that returns on
7636 -- the sec stack in which case this will be done by the caller.
7638 if VM_Target = No_VM and then Uses_SS then
7639 S := Enclosing_Dynamic_Scope (S);
7641 if Ekind (S) = E_Function
7642 and then Requires_Transient_Scope (Etype (S))
7646 Set_Uses_Sec_Stack (S);
7647 Check_Restriction (No_Secondary_Stack, N);
7650 end Wrap_Transient_Declaration;
7652 -------------------------------
7653 -- Wrap_Transient_Expression --
7654 -------------------------------
7656 procedure Wrap_Transient_Expression (N : Node_Id) is
7657 Expr : constant Node_Id := Relocate_Node (N);
7658 Loc : constant Source_Ptr := Sloc (N);
7659 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
7660 Typ : constant Entity_Id := Etype (N);
7667 -- M : constant Mark_Id := SS_Mark;
7668 -- procedure Finalizer is ... (See Build_Finalizer)
7677 Insert_Actions (N, New_List (
7678 Make_Object_Declaration (Loc,
7679 Defining_Identifier => Temp,
7680 Object_Definition => New_Reference_To (Typ, Loc)),
7682 Make_Transient_Block (Loc,
7684 Make_Assignment_Statement (Loc,
7685 Name => New_Reference_To (Temp, Loc),
7686 Expression => Expr),
7687 Par => Parent (N))));
7689 Rewrite (N, New_Reference_To (Temp, Loc));
7690 Analyze_And_Resolve (N, Typ);
7691 end Wrap_Transient_Expression;
7693 ------------------------------
7694 -- Wrap_Transient_Statement --
7695 ------------------------------
7697 procedure Wrap_Transient_Statement (N : Node_Id) is
7698 Loc : constant Source_Ptr := Sloc (N);
7699 New_Stmt : constant Node_Id := Relocate_Node (N);
7704 -- M : constant Mark_Id := SS_Mark;
7705 -- procedure Finalizer is ... (See Build_Finalizer)
7715 Make_Transient_Block (Loc,
7717 Par => Parent (N)));
7719 -- With the scope stack back to normal, we can call analyze on the
7720 -- resulting block. At this point, the transient scope is being
7721 -- treated like a perfectly normal scope, so there is nothing
7722 -- special about it.
7724 -- Note: Wrap_Transient_Statement is called with the node already
7725 -- analyzed (i.e. Analyzed (N) is True). This is important, since
7726 -- otherwise we would get a recursive processing of the node when
7727 -- we do this Analyze call.
7730 end Wrap_Transient_Statement;