1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2015, 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_Prag
; use Exp_Prag
;
42 with Exp_Tss
; use Exp_Tss
;
43 with Exp_Util
; use Exp_Util
;
44 with Freeze
; use Freeze
;
46 with Nlists
; use Nlists
;
47 with Nmake
; use Nmake
;
49 with Output
; use Output
;
50 with Restrict
; use Restrict
;
51 with Rident
; use Rident
;
52 with Rtsfind
; use Rtsfind
;
53 with Sinfo
; use Sinfo
;
55 with Sem_Aux
; use Sem_Aux
;
56 with Sem_Ch3
; use Sem_Ch3
;
57 with Sem_Ch7
; use Sem_Ch7
;
58 with Sem_Ch8
; use Sem_Ch8
;
59 with Sem_Res
; use Sem_Res
;
60 with Sem_Util
; use Sem_Util
;
61 with Snames
; use Snames
;
62 with Stand
; use Stand
;
63 with Targparm
; use Targparm
;
64 with Tbuild
; use Tbuild
;
65 with Ttypes
; use Ttypes
;
66 with Uintp
; use Uintp
;
68 package body Exp_Ch7
is
70 --------------------------------
71 -- Transient Scope Management --
72 --------------------------------
74 -- A transient scope is created when temporary objects are created by the
75 -- compiler. These temporary objects are allocated on the secondary stack
76 -- and the transient scope is responsible for finalizing the object when
77 -- appropriate and reclaiming the memory at the right time. The temporary
78 -- objects are generally the objects allocated to store the result of a
79 -- function returning an unconstrained or a tagged value. Expressions
80 -- needing to be wrapped in a transient scope (functions calls returning
81 -- unconstrained or tagged values) may appear in 3 different contexts which
82 -- lead to 3 different kinds of transient scope expansion:
84 -- 1. In a simple statement (procedure call, assignment, ...). In this
85 -- case the instruction is wrapped into a transient block. See
86 -- Wrap_Transient_Statement for details.
88 -- 2. In an expression of a control structure (test in a IF statement,
89 -- expression in a CASE statement, ...). See Wrap_Transient_Expression
92 -- 3. In a expression of an object_declaration. No wrapping is possible
93 -- here, so the finalization actions, if any, are done right after the
94 -- declaration and the secondary stack deallocation is done in the
95 -- proper enclosing scope. See Wrap_Transient_Declaration for details.
97 -- Note about functions returning tagged types: it has been decided to
98 -- always allocate their result in the secondary stack, even though is not
99 -- absolutely mandatory when the tagged type is constrained because the
100 -- caller knows the size of the returned object and thus could allocate the
101 -- result in the primary stack. An exception to this is when the function
102 -- builds its result in place, as is done for functions with inherently
103 -- limited result types for Ada 2005. In that case, certain callers may
104 -- pass the address of a constrained object as the target object for the
107 -- By allocating tagged results in the secondary stack a number of
108 -- implementation difficulties are avoided:
110 -- - If it is a dispatching function call, the computation of the size of
111 -- the result is possible but complex from the outside.
113 -- - If the returned type is controlled, the assignment of the returned
114 -- value to the anonymous object involves an Adjust, and we have no
115 -- easy way to access the anonymous object created by the back end.
117 -- - If the returned type is class-wide, this is an unconstrained type
120 -- Furthermore, the small loss in efficiency which is the result of this
121 -- decision is not such a big deal because functions returning tagged types
122 -- are not as common in practice compared to functions returning access to
125 --------------------------------------------------
126 -- Transient Blocks and Finalization Management --
127 --------------------------------------------------
129 function Find_Node_To_Be_Wrapped
(N
: Node_Id
) return Node_Id
;
130 -- N is a node which may generate a transient scope. Loop over the parent
131 -- pointers of N until it find the appropriate node to wrap. If it returns
132 -- Empty, it means that no transient scope is needed in this context.
134 procedure Insert_Actions_In_Scope_Around
137 Manage_SS
: Boolean);
138 -- Insert the before-actions kept in the scope stack before N, and the
139 -- after-actions after N, which must be a member of a list. If flag Clean
140 -- is set, insert any cleanup actions. If flag Manage_SS is set, insert
141 -- calls to mark and release the secondary stack.
143 function Make_Transient_Block
146 Par
: Node_Id
) return Node_Id
;
147 -- Action is a single statement or object declaration. Par is the proper
148 -- parent of the generated block. Create a transient block whose name is
149 -- the current scope and the only handled statement is Action. If Action
150 -- involves controlled objects or secondary stack usage, the corresponding
151 -- cleanup actions are performed at the end of the block.
153 procedure Set_Node_To_Be_Wrapped
(N
: Node_Id
);
154 -- Set the field Node_To_Be_Wrapped of the current scope
156 -- ??? The entire comment needs to be rewritten
157 -- ??? which entire comment?
159 procedure Store_Actions_In_Scope
(AK
: Scope_Action_Kind
; L
: List_Id
);
160 -- Shared processing for Store_xxx_Actions_In_Scope
162 -----------------------------
163 -- Finalization Management --
164 -----------------------------
166 -- This part describe how Initialization/Adjustment/Finalization procedures
167 -- are generated and called. Two cases must be considered, types that are
168 -- Controlled (Is_Controlled flag set) and composite types that contain
169 -- controlled components (Has_Controlled_Component flag set). In the first
170 -- case the procedures to call are the user-defined primitive operations
171 -- Initialize/Adjust/Finalize. In the second case, GNAT generates
172 -- Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
173 -- of calling the former procedures on the controlled components.
175 -- For records with Has_Controlled_Component set, a hidden "controller"
176 -- component is inserted. This controller component contains its own
177 -- finalization list on which all controlled components are attached
178 -- creating an indirection on the upper-level Finalization list. This
179 -- technique facilitates the management of objects whose number of
180 -- controlled components changes during execution. This controller
181 -- component is itself controlled and is attached to the upper-level
182 -- finalization chain. Its adjust primitive is in charge of calling adjust
183 -- on the components and adjusting the finalization pointer to match their
184 -- new location (see a-finali.adb).
186 -- It is not possible to use a similar technique for arrays that have
187 -- Has_Controlled_Component set. In this case, deep procedures are
188 -- generated that call initialize/adjust/finalize + attachment or
189 -- detachment on the finalization list for all component.
191 -- Initialize calls: they are generated for declarations or dynamic
192 -- allocations of Controlled objects with no initial value. They are always
193 -- followed by an attachment to the current Finalization Chain. For the
194 -- dynamic allocation case this the chain attached to the scope of the
195 -- access type definition otherwise, this is the chain of the current
198 -- Adjust Calls: They are generated on 2 occasions: (1) for declarations
199 -- or dynamic allocations of Controlled objects with an initial value.
200 -- (2) after an assignment. In the first case they are followed by an
201 -- attachment to the final chain, in the second case they are not.
203 -- Finalization Calls: They are generated on (1) scope exit, (2)
204 -- assignments, (3) unchecked deallocations. In case (3) they have to
205 -- be detached from the final chain, in case (2) they must not and in
206 -- case (1) this is not important since we are exiting the scope anyway.
210 -- Type extensions will have a new record controller at each derivation
211 -- level containing controlled components. The record controller for
212 -- the parent/ancestor is attached to the finalization list of the
213 -- extension's record controller (i.e. the parent is like a component
214 -- of the extension).
216 -- For types that are both Is_Controlled and Has_Controlled_Components,
217 -- the record controller and the object itself are handled separately.
218 -- It could seem simpler to attach the object at the end of its record
219 -- controller but this would not tackle view conversions properly.
221 -- A classwide type can always potentially have controlled components
222 -- but the record controller of the corresponding actual type may not
223 -- be known at compile time so the dispatch table contains a special
224 -- field that allows computation of the offset of the record controller
225 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
227 -- Here is a simple example of the expansion of a controlled block :
231 -- Y : Controlled := Init;
237 -- Z : R := (C => X);
247 -- _L : System.FI.Finalizable_Ptr;
249 -- procedure _Clean is
252 -- System.FI.Finalize_List (_L);
260 -- Attach_To_Final_List (_L, Finalizable (X), 1);
261 -- at end: Abort_Undefer;
262 -- Y : Controlled := Init;
264 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
272 -- Deep_Initialize (W, _L, 1);
273 -- at end: Abort_Under;
274 -- Z : R := (C => X);
275 -- Deep_Adjust (Z, _L, 1);
279 -- Deep_Finalize (W, False);
280 -- <save W's final pointers>
282 -- <restore W's final pointers>
283 -- Deep_Adjust (W, _L, 0);
288 type Final_Primitives
is
289 (Initialize_Case
, Adjust_Case
, Finalize_Case
, Address_Case
);
290 -- This enumeration type is defined in order to ease sharing code for
291 -- building finalization procedures for composite types.
293 Name_Of
: constant array (Final_Primitives
) of Name_Id
:=
294 (Initialize_Case
=> Name_Initialize
,
295 Adjust_Case
=> Name_Adjust
,
296 Finalize_Case
=> Name_Finalize
,
297 Address_Case
=> Name_Finalize_Address
);
298 Deep_Name_Of
: constant array (Final_Primitives
) of TSS_Name_Type
:=
299 (Initialize_Case
=> TSS_Deep_Initialize
,
300 Adjust_Case
=> TSS_Deep_Adjust
,
301 Finalize_Case
=> TSS_Deep_Finalize
,
302 Address_Case
=> TSS_Finalize_Address
);
304 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
);
305 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
306 -- Has_Controlled_Component set and store them using the TSS mechanism.
308 function Build_Cleanup_Statements
310 Additional_Cleanup
: List_Id
) return List_Id
;
311 -- Create the clean up calls for an asynchronous call block, task master,
312 -- protected subprogram body, task allocation block or task body, or
313 -- additional cleanup actions parked on a transient block. If the context
314 -- does not contain the above constructs, the routine returns an empty
317 procedure Build_Finalizer
319 Clean_Stmts
: List_Id
;
322 Defer_Abort
: Boolean;
323 Fin_Id
: out Entity_Id
);
324 -- N may denote an accept statement, block, entry body, package body,
325 -- package spec, protected body, subprogram body, or a task body. Create
326 -- a procedure which contains finalization calls for all controlled objects
327 -- declared in the declarative or statement region of N. The calls are
328 -- built in reverse order relative to the original declarations. In the
329 -- case of a task body, the routine delays the creation of the finalizer
330 -- until all statements have been moved to the task body procedure.
331 -- Clean_Stmts may contain additional context-dependent code used to abort
332 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
333 -- Mark_Id is the secondary stack used in the current context or Empty if
334 -- missing. Top_Decls is the list on which the declaration of the finalizer
335 -- is attached in the non-package case. Defer_Abort indicates that the
336 -- statements passed in perform actions that require abort to be deferred,
337 -- such as for task termination. Fin_Id is the finalizer declaration
340 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
);
341 -- N is a construct which contains a handled sequence of statements, Fin_Id
342 -- is the entity of a finalizer. Create an At_End handler which covers the
343 -- statements of N and calls Fin_Id. If the handled statement sequence has
344 -- an exception handler, the statements will be wrapped in a block to avoid
345 -- unwanted interaction with the new At_End handler.
347 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
);
348 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
349 -- Has_Component_Component set and store them using the TSS mechanism.
351 procedure Check_Visibly_Controlled
352 (Prim
: Final_Primitives
;
354 E
: in out Entity_Id
;
355 Cref
: in out Node_Id
);
356 -- The controlled operation declared for a derived type may not be
357 -- overriding, if the controlled operations of the parent type are hidden,
358 -- for example when the parent is a private type whose full view is
359 -- controlled. For other primitive operations we modify the name of the
360 -- operation to indicate that it is not overriding, but this is not
361 -- possible for Initialize, etc. because they have to be retrievable by
362 -- name. Before generating the proper call to one of these operations we
363 -- check whether Typ is known to be controlled at the point of definition.
364 -- If it is not then we must retrieve the hidden operation of the parent
365 -- and use it instead. This is one case that might be solved more cleanly
366 -- once Overriding pragmas or declarations are in place.
368 function Convert_View
371 Ind
: Pos
:= 1) return Node_Id
;
372 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
373 -- argument being passed to it. Ind indicates which formal of procedure
374 -- Proc we are trying to match. This function will, if necessary, generate
375 -- a conversion between the partial and full view of Arg to match the type
376 -- of the formal of Proc, or force a conversion to the class-wide type in
377 -- the case where the operation is abstract.
379 function Enclosing_Function
(E
: Entity_Id
) return Entity_Id
;
380 -- Given an arbitrary entity, traverse the scope chain looking for the
381 -- first enclosing function. Return Empty if no function was found.
387 Skip_Self
: Boolean := False) return Node_Id
;
388 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
389 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
390 -- an adjust or finalization call. Wnen flag Skip_Self is set, the related
391 -- action has an effect on the components only (if any).
393 function Make_Deep_Proc
394 (Prim
: Final_Primitives
;
396 Stmts
: List_Id
) return Node_Id
;
397 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
398 -- Deep_Finalize procedures according to the first parameter, these
399 -- procedures operate on the type Typ. The Stmts parameter gives the body
402 function Make_Deep_Array_Body
403 (Prim
: Final_Primitives
;
404 Typ
: Entity_Id
) return List_Id
;
405 -- This function generates the list of statements for implementing
406 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
407 -- the first parameter, these procedures operate on the array type Typ.
409 function Make_Deep_Record_Body
410 (Prim
: Final_Primitives
;
412 Is_Local
: Boolean := False) return List_Id
;
413 -- This function generates the list of statements for implementing
414 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
415 -- the first parameter, these procedures operate on the record type Typ.
416 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
417 -- whether the inner logic should be dictated by state counters.
419 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
;
420 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
421 -- Make_Deep_Record_Body. Generate the following statements:
424 -- type Acc_Typ is access all Typ;
425 -- for Acc_Typ'Storage_Size use 0;
427 -- [Deep_]Finalize (Acc_Typ (V).all);
430 ----------------------------
431 -- Build_Array_Deep_Procs --
432 ----------------------------
434 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
) is
438 (Prim
=> Initialize_Case
,
440 Stmts
=> Make_Deep_Array_Body
(Initialize_Case
, Typ
)));
442 if not Is_Limited_View
(Typ
) then
445 (Prim
=> Adjust_Case
,
447 Stmts
=> Make_Deep_Array_Body
(Adjust_Case
, Typ
)));
450 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
451 -- suppressed since these routine will not be used.
453 if not Restriction_Active
(No_Finalization
) then
456 (Prim
=> Finalize_Case
,
458 Stmts
=> Make_Deep_Array_Body
(Finalize_Case
, Typ
)));
460 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
461 -- .NET do not support address arithmetic and unchecked conversions.
463 if VM_Target
= No_VM
then
466 (Prim
=> Address_Case
,
468 Stmts
=> Make_Deep_Array_Body
(Address_Case
, Typ
)));
471 end Build_Array_Deep_Procs
;
473 ------------------------------
474 -- Build_Cleanup_Statements --
475 ------------------------------
477 function Build_Cleanup_Statements
479 Additional_Cleanup
: List_Id
) return List_Id
481 Is_Asynchronous_Call
: constant Boolean :=
482 Nkind
(N
) = N_Block_Statement
483 and then Is_Asynchronous_Call_Block
(N
);
484 Is_Master
: constant Boolean :=
485 Nkind
(N
) /= N_Entry_Body
486 and then Is_Task_Master
(N
);
487 Is_Protected_Body
: constant Boolean :=
488 Nkind
(N
) = N_Subprogram_Body
489 and then Is_Protected_Subprogram_Body
(N
);
490 Is_Task_Allocation
: constant Boolean :=
491 Nkind
(N
) = N_Block_Statement
492 and then Is_Task_Allocation_Block
(N
);
493 Is_Task_Body
: constant Boolean :=
494 Nkind
(Original_Node
(N
)) = N_Task_Body
;
496 Loc
: constant Source_Ptr
:= Sloc
(N
);
497 Stmts
: constant List_Id
:= New_List
;
501 if Restricted_Profile
then
503 Build_Runtime_Call
(Loc
, RE_Complete_Restricted_Task
));
505 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Task
));
509 if Restriction_Active
(No_Task_Hierarchy
) = False then
510 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Master
));
513 -- Add statements to unlock the protected object parameter and to
514 -- undefer abort. If the context is a protected procedure and the object
515 -- has entries, call the entry service routine.
517 -- NOTE: The generated code references _object, a parameter to the
520 elsif Is_Protected_Body
then
522 Spec
: constant Node_Id
:= Parent
(Corresponding_Spec
(N
));
523 Conc_Typ
: Entity_Id
;
525 Param_Typ
: Entity_Id
;
528 -- Find the _object parameter representing the protected object
530 Param
:= First
(Parameter_Specifications
(Spec
));
532 Param_Typ
:= Etype
(Parameter_Type
(Param
));
534 if Ekind
(Param_Typ
) = E_Record_Type
then
535 Conc_Typ
:= Corresponding_Concurrent_Type
(Param_Typ
);
538 exit when No
(Param
) or else Present
(Conc_Typ
);
542 pragma Assert
(Present
(Param
));
544 -- Historical note: In earlier versions of GNAT, there was code
545 -- at this point to generate stuff to service entry queues. It is
546 -- now abstracted in Build_Protected_Subprogram_Call_Cleanup.
548 Build_Protected_Subprogram_Call_Cleanup
549 (Specification
(N
), Conc_Typ
, Loc
, Stmts
);
552 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
553 -- tasks. Other unactivated tasks are completed by Complete_Task or
556 -- NOTE: The generated code references _chain, a local object
558 elsif Is_Task_Allocation
then
561 -- Expunge_Unactivated_Tasks (_chain);
563 -- where _chain is the list of tasks created by the allocator but not
564 -- yet activated. This list will be empty unless the block completes
568 Make_Procedure_Call_Statement
(Loc
,
571 (RTE
(RE_Expunge_Unactivated_Tasks
), Loc
),
572 Parameter_Associations
=> New_List
(
573 New_Occurrence_Of
(Activation_Chain_Entity
(N
), Loc
))));
575 -- Attempt to cancel an asynchronous entry call whenever the block which
576 -- contains the abortable part is exited.
578 -- NOTE: The generated code references Cnn, a local object
580 elsif Is_Asynchronous_Call
then
582 Cancel_Param
: constant Entity_Id
:=
583 Entry_Cancel_Parameter
(Entity
(Identifier
(N
)));
586 -- If it is of type Communication_Block, this must be a protected
587 -- entry call. Generate:
589 -- if Enqueued (Cancel_Param) then
590 -- Cancel_Protected_Entry_Call (Cancel_Param);
593 if Is_RTE
(Etype
(Cancel_Param
), RE_Communication_Block
) then
595 Make_If_Statement
(Loc
,
597 Make_Function_Call
(Loc
,
599 New_Occurrence_Of
(RTE
(RE_Enqueued
), Loc
),
600 Parameter_Associations
=> New_List
(
601 New_Occurrence_Of
(Cancel_Param
, Loc
))),
603 Then_Statements
=> New_List
(
604 Make_Procedure_Call_Statement
(Loc
,
607 (RTE
(RE_Cancel_Protected_Entry_Call
), Loc
),
608 Parameter_Associations
=> New_List
(
609 New_Occurrence_Of
(Cancel_Param
, Loc
))))));
611 -- Asynchronous delay, generate:
612 -- Cancel_Async_Delay (Cancel_Param);
614 elsif Is_RTE
(Etype
(Cancel_Param
), RE_Delay_Block
) then
616 Make_Procedure_Call_Statement
(Loc
,
618 New_Occurrence_Of
(RTE
(RE_Cancel_Async_Delay
), Loc
),
619 Parameter_Associations
=> New_List
(
620 Make_Attribute_Reference
(Loc
,
622 New_Occurrence_Of
(Cancel_Param
, Loc
),
623 Attribute_Name
=> Name_Unchecked_Access
))));
625 -- Task entry call, generate:
626 -- Cancel_Task_Entry_Call (Cancel_Param);
630 Make_Procedure_Call_Statement
(Loc
,
632 New_Occurrence_Of
(RTE
(RE_Cancel_Task_Entry_Call
), Loc
),
633 Parameter_Associations
=> New_List
(
634 New_Occurrence_Of
(Cancel_Param
, Loc
))));
639 Append_List_To
(Stmts
, Additional_Cleanup
);
641 end Build_Cleanup_Statements
;
643 -----------------------------
644 -- Build_Controlling_Procs --
645 -----------------------------
647 procedure Build_Controlling_Procs
(Typ
: Entity_Id
) is
649 if Is_Array_Type
(Typ
) then
650 Build_Array_Deep_Procs
(Typ
);
651 else pragma Assert
(Is_Record_Type
(Typ
));
652 Build_Record_Deep_Procs
(Typ
);
654 end Build_Controlling_Procs
;
656 -----------------------------
657 -- Build_Exception_Handler --
658 -----------------------------
660 function Build_Exception_Handler
661 (Data
: Finalization_Exception_Data
;
662 For_Library
: Boolean := False) return Node_Id
665 Proc_To_Call
: Entity_Id
;
670 pragma Assert
(Present
(Data
.Raised_Id
));
672 if Exception_Extra_Info
673 or else (For_Library
and not Restricted_Profile
)
675 if Exception_Extra_Info
then
679 -- Get_Current_Excep.all
682 Make_Function_Call
(Data
.Loc
,
684 Make_Explicit_Dereference
(Data
.Loc
,
687 (RTE
(RE_Get_Current_Excep
), Data
.Loc
)));
694 Except
:= Make_Null
(Data
.Loc
);
697 if For_Library
and then not Restricted_Profile
then
698 Proc_To_Call
:= RTE
(RE_Save_Library_Occurrence
);
699 Actuals
:= New_List
(Except
);
702 Proc_To_Call
:= RTE
(RE_Save_Occurrence
);
704 -- The dereference occurs only when Exception_Extra_Info is true,
705 -- and therefore Except is not null.
709 New_Occurrence_Of
(Data
.E_Id
, Data
.Loc
),
710 Make_Explicit_Dereference
(Data
.Loc
, Except
));
716 -- if not Raised_Id then
717 -- Raised_Id := True;
719 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
721 -- Save_Library_Occurrence (Get_Current_Excep.all);
726 Make_If_Statement
(Data
.Loc
,
728 Make_Op_Not
(Data
.Loc
,
729 Right_Opnd
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
)),
731 Then_Statements
=> New_List
(
732 Make_Assignment_Statement
(Data
.Loc
,
733 Name
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
),
734 Expression
=> New_Occurrence_Of
(Standard_True
, Data
.Loc
)),
736 Make_Procedure_Call_Statement
(Data
.Loc
,
738 New_Occurrence_Of
(Proc_To_Call
, Data
.Loc
),
739 Parameter_Associations
=> Actuals
))));
744 -- Raised_Id := True;
747 Make_Assignment_Statement
(Data
.Loc
,
748 Name
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
),
749 Expression
=> New_Occurrence_Of
(Standard_True
, Data
.Loc
)));
757 Make_Exception_Handler
(Data
.Loc
,
758 Exception_Choices
=> New_List
(Make_Others_Choice
(Data
.Loc
)),
759 Statements
=> Stmts
);
760 end Build_Exception_Handler
;
762 -------------------------------
763 -- Build_Finalization_Master --
764 -------------------------------
766 procedure Build_Finalization_Master
768 For_Anonymous
: Boolean := False;
769 For_Private
: Boolean := False;
770 Context_Scope
: Entity_Id
:= Empty
;
771 Insertion_Node
: Node_Id
:= Empty
)
773 procedure Add_Pending_Access_Type
775 Ptr_Typ
: Entity_Id
);
776 -- Add access type Ptr_Typ to the pending access type list for type Typ
778 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean;
779 -- Determine whether entity E is inside a wrapper package created for
780 -- an instance of Ada.Unchecked_Deallocation.
782 -----------------------------
783 -- Add_Pending_Access_Type --
784 -----------------------------
786 procedure Add_Pending_Access_Type
793 if Present
(Pending_Access_Types
(Typ
)) then
794 List
:= Pending_Access_Types
(Typ
);
796 List
:= New_Elmt_List
;
797 Set_Pending_Access_Types
(Typ
, List
);
800 Prepend_Elmt
(Ptr_Typ
, List
);
801 end Add_Pending_Access_Type
;
803 ------------------------------
804 -- In_Deallocation_Instance --
805 ------------------------------
807 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean is
808 Pkg
: constant Entity_Id
:= Scope
(E
);
809 Par
: Node_Id
:= Empty
;
812 if Ekind
(Pkg
) = E_Package
813 and then Present
(Related_Instance
(Pkg
))
814 and then Ekind
(Related_Instance
(Pkg
)) = E_Procedure
816 Par
:= Generic_Parent
(Parent
(Related_Instance
(Pkg
)));
820 and then Chars
(Par
) = Name_Unchecked_Deallocation
821 and then Chars
(Scope
(Par
)) = Name_Ada
822 and then Scope
(Scope
(Par
)) = Standard_Standard
;
826 end In_Deallocation_Instance
;
830 Desig_Typ
: constant Entity_Id
:= Designated_Type
(Typ
);
832 Ptr_Typ
: constant Entity_Id
:= Root_Type_Of_Full_View
(Base_Type
(Typ
));
833 -- A finalization master created for a named access type is associated
834 -- with the full view (if applicable) as a consequence of freezing. The
835 -- full view criteria does not apply to anonymous access types because
836 -- those cannot have a private and a full view.
838 -- Start of processing for Build_Finalization_Master
841 -- Certain run-time configurations and targets do not provide support
842 -- for controlled types.
844 if Restriction_Active
(No_Finalization
) then
847 -- Do not process C, C++, CIL and Java types since it is assumend that
848 -- the non-Ada side will handle their clean up.
850 elsif Convention
(Desig_Typ
) = Convention_C
851 or else Convention
(Desig_Typ
) = Convention_CIL
852 or else Convention
(Desig_Typ
) = Convention_CPP
853 or else Convention
(Desig_Typ
) = Convention_Java
857 -- Various machinery such as freezing may have already created a
858 -- finalization master.
860 elsif Present
(Finalization_Master
(Ptr_Typ
)) then
863 -- Do not process types that return on the secondary stack
865 elsif Present
(Associated_Storage_Pool
(Ptr_Typ
))
866 and then Is_RTE
(Associated_Storage_Pool
(Ptr_Typ
), RE_SS_Pool
)
870 -- Do not process types which may never allocate an object
872 elsif No_Pool_Assigned
(Ptr_Typ
) then
875 -- Do not process access types coming from Ada.Unchecked_Deallocation
876 -- instances. Even though the designated type may be controlled, the
877 -- access type will never participate in allocation.
879 elsif In_Deallocation_Instance
(Ptr_Typ
) then
882 -- Ignore the general use of anonymous access types unless the context
883 -- requires a finalization master.
885 elsif Ekind
(Ptr_Typ
) = E_Anonymous_Access_Type
886 and then not For_Anonymous
890 -- Do not process non-library access types when restriction No_Nested_
891 -- Finalization is in effect since masters are controlled objects.
893 elsif Restriction_Active
(No_Nested_Finalization
)
894 and then not Is_Library_Level_Entity
(Ptr_Typ
)
898 -- For .NET/JVM targets, allow the processing of access-to-controlled
899 -- types where the designated type is explicitly derived from [Limited_]
902 elsif VM_Target
/= No_VM
and then not Is_Controlled
(Desig_Typ
) then
905 -- Do not create finalization masters in GNATprove mode because this
906 -- unwanted extra expansion. A compilation in this mode keeps the tree
907 -- as close as possible to the original sources.
909 elsif GNATprove_Mode
then
914 Actions
: constant List_Id
:= New_List
;
915 Loc
: constant Source_Ptr
:= Sloc
(Ptr_Typ
);
916 Fin_Mas_Id
: Entity_Id
;
920 -- Source access types use fixed master names since the master is
921 -- inserted in the same source unit only once. The only exception to
922 -- this are instances using the same access type as generic actual.
924 if Comes_From_Source
(Ptr_Typ
) and then not Inside_A_Generic
then
926 Make_Defining_Identifier
(Loc
,
927 Chars
=> New_External_Name
(Chars
(Ptr_Typ
), "FM"));
929 -- Internally generated access types use temporaries as their names
930 -- due to possible collision with identical names coming from other
934 Fin_Mas_Id
:= Make_Temporary
(Loc
, 'F');
937 Set_Finalization_Master
(Ptr_Typ
, Fin_Mas_Id
);
940 -- <Ptr_Typ>FM : aliased Finalization_Master;
943 Make_Object_Declaration
(Loc
,
944 Defining_Identifier
=> Fin_Mas_Id
,
945 Aliased_Present
=> True,
947 New_Occurrence_Of
(RTE
(RE_Finalization_Master
), Loc
)));
949 -- Set the associated pool and primitive Finalize_Address of the new
950 -- finalization master. This step is skipped on .NET/JVM because the
951 -- target does not support storage pools or address arithmetic.
953 if VM_Target
= No_VM
then
955 -- The access type has a user-defined storage pool, use it
957 if Present
(Associated_Storage_Pool
(Ptr_Typ
)) then
958 Pool_Id
:= Associated_Storage_Pool
(Ptr_Typ
);
960 -- Otherwise the default choice is the global storage pool
963 Pool_Id
:= RTE
(RE_Global_Pool_Object
);
964 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
968 -- Set_Base_Pool (<Ptr_Typ>FM, Pool_Id'Unchecked_Access);
971 Make_Procedure_Call_Statement
(Loc
,
973 New_Occurrence_Of
(RTE
(RE_Set_Base_Pool
), Loc
),
974 Parameter_Associations
=> New_List
(
975 New_Occurrence_Of
(Fin_Mas_Id
, Loc
),
976 Make_Attribute_Reference
(Loc
,
977 Prefix
=> New_Occurrence_Of
(Pool_Id
, Loc
),
978 Attribute_Name
=> Name_Unrestricted_Access
))));
980 -- Finalize_Address is not generated in CodePeer mode because the
981 -- body contains address arithmetic. Skip this step.
983 if CodePeer_Mode
then
986 -- Associate the Finalize_Address primitive of the designated type
987 -- with the finalization master of the access type. The designated
988 -- type must be forzen as Finalize_Address is generated when the
989 -- freeze node is expanded.
991 elsif Is_Frozen
(Desig_Typ
)
992 and then Present
(Finalize_Address
(Desig_Typ
))
994 -- The finalization master of an anonymous access type may need
995 -- to be inserted in a specific place in the tree. For instance:
999 -- <finalization master of "access Comp_Typ">
1001 -- type Rec_Typ is record
1002 -- Comp : access Comp_Typ;
1005 -- <freeze node for Comp_Typ>
1006 -- <freeze node for Rec_Typ>
1008 -- Due to this oddity, the anonymous access type is stored for
1009 -- later processing (see below).
1011 and then Ekind
(Ptr_Typ
) /= E_Anonymous_Access_Type
1014 -- Set_Finalize_Address
1015 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
1018 Make_Set_Finalize_Address_Call
1020 Ptr_Typ
=> Ptr_Typ
));
1022 -- Otherwise the designated type is either anonymous access or a
1023 -- Taft-amendment type and has not been frozen. Store the access
1024 -- type for later processing (see Freeze_Type).
1027 Add_Pending_Access_Type
(Desig_Typ
, Ptr_Typ
);
1031 -- A finalization master created for an anonymous access type or an
1032 -- access designating a type with private components must be inserted
1033 -- before a context-dependent node.
1035 if For_Anonymous
or For_Private
then
1037 -- At this point both the scope of the context and the insertion
1038 -- mode must be known.
1040 pragma Assert
(Present
(Context_Scope
));
1041 pragma Assert
(Present
(Insertion_Node
));
1043 Push_Scope
(Context_Scope
);
1045 -- Treat use clauses as declarations and insert directly in front
1048 if Nkind_In
(Insertion_Node
, N_Use_Package_Clause
,
1051 Insert_List_Before_And_Analyze
(Insertion_Node
, Actions
);
1053 Insert_Actions
(Insertion_Node
, Actions
);
1058 -- Otherwise the finalization master and its initialization become a
1059 -- part of the freeze node.
1062 Append_Freeze_Actions
(Ptr_Typ
, Actions
);
1065 end Build_Finalization_Master
;
1067 ---------------------
1068 -- Build_Finalizer --
1069 ---------------------
1071 procedure Build_Finalizer
1073 Clean_Stmts
: List_Id
;
1074 Mark_Id
: Entity_Id
;
1075 Top_Decls
: List_Id
;
1076 Defer_Abort
: Boolean;
1077 Fin_Id
: out Entity_Id
)
1079 Acts_As_Clean
: constant Boolean :=
1082 (Present
(Clean_Stmts
)
1083 and then Is_Non_Empty_List
(Clean_Stmts
));
1084 Exceptions_OK
: constant Boolean :=
1085 not Restriction_Active
(No_Exception_Propagation
);
1086 For_Package_Body
: constant Boolean := Nkind
(N
) = N_Package_Body
;
1087 For_Package_Spec
: constant Boolean := Nkind
(N
) = N_Package_Declaration
;
1088 For_Package
: constant Boolean :=
1089 For_Package_Body
or else For_Package_Spec
;
1090 Loc
: constant Source_Ptr
:= Sloc
(N
);
1092 -- NOTE: Local variable declarations are conservative and do not create
1093 -- structures right from the start. Entities and lists are created once
1094 -- it has been established that N has at least one controlled object.
1096 Components_Built
: Boolean := False;
1097 -- A flag used to avoid double initialization of entities and lists. If
1098 -- the flag is set then the following variables have been initialized:
1104 Counter_Id
: Entity_Id
:= Empty
;
1105 Counter_Val
: Int
:= 0;
1106 -- Name and value of the state counter
1108 Decls
: List_Id
:= No_List
;
1109 -- Declarative region of N (if available). If N is a package declaration
1110 -- Decls denotes the visible declarations.
1112 Finalizer_Data
: Finalization_Exception_Data
;
1113 -- Data for the exception
1115 Finalizer_Decls
: List_Id
:= No_List
;
1116 -- Local variable declarations. This list holds the label declarations
1117 -- of all jump block alternatives as well as the declaration of the
1118 -- local exception occurence and the raised flag:
1119 -- E : Exception_Occurrence;
1120 -- Raised : Boolean := False;
1121 -- L<counter value> : label;
1123 Finalizer_Insert_Nod
: Node_Id
:= Empty
;
1124 -- Insertion point for the finalizer body. Depending on the context
1125 -- (Nkind of N) and the individual grouping of controlled objects, this
1126 -- node may denote a package declaration or body, package instantiation,
1127 -- block statement or a counter update statement.
1129 Finalizer_Stmts
: List_Id
:= No_List
;
1130 -- The statement list of the finalizer body. It contains the following:
1132 -- Abort_Defer; -- Added if abort is allowed
1133 -- <call to Prev_At_End> -- Added if exists
1134 -- <cleanup statements> -- Added if Acts_As_Clean
1135 -- <jump block> -- Added if Has_Ctrl_Objs
1136 -- <finalization statements> -- Added if Has_Ctrl_Objs
1137 -- <stack release> -- Added if Mark_Id exists
1138 -- Abort_Undefer; -- Added if abort is allowed
1140 Has_Ctrl_Objs
: Boolean := False;
1141 -- A general flag which denotes whether N has at least one controlled
1144 Has_Tagged_Types
: Boolean := False;
1145 -- A general flag which indicates whether N has at least one library-
1146 -- level tagged type declaration.
1148 HSS
: Node_Id
:= Empty
;
1149 -- The sequence of statements of N (if available)
1151 Jump_Alts
: List_Id
:= No_List
;
1152 -- Jump block alternatives. Depending on the value of the state counter,
1153 -- the control flow jumps to a sequence of finalization statements. This
1154 -- list contains the following:
1156 -- when <counter value> =>
1157 -- goto L<counter value>;
1159 Jump_Block_Insert_Nod
: Node_Id
:= Empty
;
1160 -- Specific point in the finalizer statements where the jump block is
1163 Last_Top_Level_Ctrl_Construct
: Node_Id
:= Empty
;
1164 -- The last controlled construct encountered when processing the top
1165 -- level lists of N. This can be a nested package, an instantiation or
1166 -- an object declaration.
1168 Prev_At_End
: Entity_Id
:= Empty
;
1169 -- The previous at end procedure of the handled statements block of N
1171 Priv_Decls
: List_Id
:= No_List
;
1172 -- The private declarations of N if N is a package declaration
1174 Spec_Id
: Entity_Id
:= Empty
;
1175 Spec_Decls
: List_Id
:= Top_Decls
;
1176 Stmts
: List_Id
:= No_List
;
1178 Tagged_Type_Stmts
: List_Id
:= No_List
;
1179 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1180 -- tagged types found in N.
1182 -----------------------
1183 -- Local subprograms --
1184 -----------------------
1186 procedure Build_Components
;
1187 -- Create all entites and initialize all lists used in the creation of
1190 procedure Create_Finalizer
;
1191 -- Create the spec and body of the finalizer and insert them in the
1192 -- proper place in the tree depending on the context.
1194 procedure Process_Declarations
1196 Preprocess
: Boolean := False;
1197 Top_Level
: Boolean := False);
1198 -- Inspect a list of declarations or statements which may contain
1199 -- objects that need finalization. When flag Preprocess is set, the
1200 -- routine will simply count the total number of controlled objects in
1201 -- Decls. Flag Top_Level denotes whether the processing is done for
1202 -- objects in nested package declarations or instances.
1204 procedure Process_Object_Declaration
1206 Has_No_Init
: Boolean := False;
1207 Is_Protected
: Boolean := False);
1208 -- Generate all the machinery associated with the finalization of a
1209 -- single object. Flag Has_No_Init is used to denote certain contexts
1210 -- where Decl does not have initialization call(s). Flag Is_Protected
1211 -- is set when Decl denotes a simple protected object.
1213 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
);
1214 -- Generate all the code necessary to unregister the external tag of a
1217 ----------------------
1218 -- Build_Components --
1219 ----------------------
1221 procedure Build_Components
is
1222 Counter_Decl
: Node_Id
;
1223 Counter_Typ
: Entity_Id
;
1224 Counter_Typ_Decl
: Node_Id
;
1227 pragma Assert
(Present
(Decls
));
1229 -- This routine might be invoked several times when dealing with
1230 -- constructs that have two lists (either two declarative regions
1231 -- or declarations and statements). Avoid double initialization.
1233 if Components_Built
then
1237 Components_Built
:= True;
1239 if Has_Ctrl_Objs
then
1241 -- Create entities for the counter, its type, the local exception
1242 -- and the raised flag.
1244 Counter_Id
:= Make_Temporary
(Loc
, 'C');
1245 Counter_Typ
:= Make_Temporary
(Loc
, 'T');
1247 Finalizer_Decls
:= New_List
;
1249 Build_Object_Declarations
1250 (Finalizer_Data
, Finalizer_Decls
, Loc
, For_Package
);
1252 -- Since the total number of controlled objects is always known,
1253 -- build a subtype of Natural with precise bounds. This allows
1254 -- the backend to optimize the case statement. Generate:
1256 -- subtype Tnn is Natural range 0 .. Counter_Val;
1259 Make_Subtype_Declaration
(Loc
,
1260 Defining_Identifier
=> Counter_Typ
,
1261 Subtype_Indication
=>
1262 Make_Subtype_Indication
(Loc
,
1263 Subtype_Mark
=> New_Occurrence_Of
(Standard_Natural
, Loc
),
1265 Make_Range_Constraint
(Loc
,
1269 Make_Integer_Literal
(Loc
, Uint_0
),
1271 Make_Integer_Literal
(Loc
, Counter_Val
)))));
1273 -- Generate the declaration of the counter itself:
1275 -- Counter : Integer := 0;
1278 Make_Object_Declaration
(Loc
,
1279 Defining_Identifier
=> Counter_Id
,
1280 Object_Definition
=> New_Occurrence_Of
(Counter_Typ
, Loc
),
1281 Expression
=> Make_Integer_Literal
(Loc
, 0));
1283 -- Set the type of the counter explicitly to prevent errors when
1284 -- examining object declarations later on.
1286 Set_Etype
(Counter_Id
, Counter_Typ
);
1288 -- The counter and its type are inserted before the source
1289 -- declarations of N.
1291 Prepend_To
(Decls
, Counter_Decl
);
1292 Prepend_To
(Decls
, Counter_Typ_Decl
);
1294 -- The counter and its associated type must be manually analized
1295 -- since N has already been analyzed. Use the scope of the spec
1296 -- when inserting in a package.
1299 Push_Scope
(Spec_Id
);
1300 Analyze
(Counter_Typ_Decl
);
1301 Analyze
(Counter_Decl
);
1305 Analyze
(Counter_Typ_Decl
);
1306 Analyze
(Counter_Decl
);
1309 Jump_Alts
:= New_List
;
1312 -- If the context requires additional clean up, the finalization
1313 -- machinery is added after the clean up code.
1315 if Acts_As_Clean
then
1316 Finalizer_Stmts
:= Clean_Stmts
;
1317 Jump_Block_Insert_Nod
:= Last
(Finalizer_Stmts
);
1319 Finalizer_Stmts
:= New_List
;
1322 if Has_Tagged_Types
then
1323 Tagged_Type_Stmts
:= New_List
;
1325 end Build_Components
;
1327 ----------------------
1328 -- Create_Finalizer --
1329 ----------------------
1331 procedure Create_Finalizer
is
1332 Body_Id
: Entity_Id
;
1335 Jump_Block
: Node_Id
;
1337 Label_Id
: Entity_Id
;
1339 function New_Finalizer_Name
return Name_Id
;
1340 -- Create a fully qualified name of a package spec or body finalizer.
1341 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1343 ------------------------
1344 -- New_Finalizer_Name --
1345 ------------------------
1347 function New_Finalizer_Name
return Name_Id
is
1348 procedure New_Finalizer_Name
(Id
: Entity_Id
);
1349 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1350 -- has a non-standard scope, process the scope first.
1352 ------------------------
1353 -- New_Finalizer_Name --
1354 ------------------------
1356 procedure New_Finalizer_Name
(Id
: Entity_Id
) is
1358 if Scope
(Id
) = Standard_Standard
then
1359 Get_Name_String
(Chars
(Id
));
1362 New_Finalizer_Name
(Scope
(Id
));
1363 Add_Str_To_Name_Buffer
("__");
1364 Add_Str_To_Name_Buffer
(Get_Name_String
(Chars
(Id
)));
1366 end New_Finalizer_Name
;
1368 -- Start of processing for New_Finalizer_Name
1371 -- Create the fully qualified name of the enclosing scope
1373 New_Finalizer_Name
(Spec_Id
);
1376 -- __finalize_[spec|body]
1378 Add_Str_To_Name_Buffer
("__finalize_");
1380 if For_Package_Spec
then
1381 Add_Str_To_Name_Buffer
("spec");
1383 Add_Str_To_Name_Buffer
("body");
1387 end New_Finalizer_Name
;
1389 -- Start of processing for Create_Finalizer
1392 -- Step 1: Creation of the finalizer name
1394 -- Packages must use a distinct name for their finalizers since the
1395 -- binder will have to generate calls to them by name. The name is
1396 -- of the following form:
1398 -- xx__yy__finalize_[spec|body]
1401 Fin_Id
:= Make_Defining_Identifier
(Loc
, New_Finalizer_Name
);
1402 Set_Has_Qualified_Name
(Fin_Id
);
1403 Set_Has_Fully_Qualified_Name
(Fin_Id
);
1405 -- The default name is _finalizer
1409 Make_Defining_Identifier
(Loc
,
1410 Chars
=> New_External_Name
(Name_uFinalizer
));
1412 -- The visibility semantics of AT_END handlers force a strange
1413 -- separation of spec and body for stack-related finalizers:
1415 -- declare : Enclosing_Scope
1416 -- procedure _finalizer;
1418 -- <controlled objects>
1419 -- procedure _finalizer is
1425 -- Both spec and body are within the same construct and scope, but
1426 -- the body is part of the handled sequence of statements. This
1427 -- placement confuses the elaboration mechanism on targets where
1428 -- AT_END handlers are expanded into "when all others" handlers:
1431 -- when all others =>
1432 -- _finalizer; -- appears to require elab checks
1437 -- Since the compiler guarantees that the body of a _finalizer is
1438 -- always inserted in the same construct where the AT_END handler
1439 -- resides, there is no need for elaboration checks.
1441 Set_Kill_Elaboration_Checks
(Fin_Id
);
1444 -- Step 2: Creation of the finalizer specification
1447 -- procedure Fin_Id;
1450 Make_Subprogram_Declaration
(Loc
,
1452 Make_Procedure_Specification
(Loc
,
1453 Defining_Unit_Name
=> Fin_Id
));
1455 -- Step 3: Creation of the finalizer body
1457 if Has_Ctrl_Objs
then
1459 -- Add L0, the default destination to the jump block
1461 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
1462 Set_Entity
(Label_Id
,
1463 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
1464 Label
:= Make_Label
(Loc
, Label_Id
);
1469 Prepend_To
(Finalizer_Decls
,
1470 Make_Implicit_Label_Declaration
(Loc
,
1471 Defining_Identifier
=> Entity
(Label_Id
),
1472 Label_Construct
=> Label
));
1478 Append_To
(Jump_Alts
,
1479 Make_Case_Statement_Alternative
(Loc
,
1480 Discrete_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
1481 Statements
=> New_List
(
1482 Make_Goto_Statement
(Loc
,
1483 Name
=> New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
1488 Append_To
(Finalizer_Stmts
, Label
);
1490 -- Create the jump block which controls the finalization flow
1491 -- depending on the value of the state counter.
1494 Make_Case_Statement
(Loc
,
1495 Expression
=> Make_Identifier
(Loc
, Chars
(Counter_Id
)),
1496 Alternatives
=> Jump_Alts
);
1498 if Acts_As_Clean
and then Present
(Jump_Block_Insert_Nod
) then
1499 Insert_After
(Jump_Block_Insert_Nod
, Jump_Block
);
1501 Prepend_To
(Finalizer_Stmts
, Jump_Block
);
1505 -- Add the library-level tagged type unregistration machinery before
1506 -- the jump block circuitry. This ensures that external tags will be
1507 -- removed even if a finalization exception occurs at some point.
1509 if Has_Tagged_Types
then
1510 Prepend_List_To
(Finalizer_Stmts
, Tagged_Type_Stmts
);
1513 -- Add a call to the previous At_End handler if it exists. The call
1514 -- must always precede the jump block.
1516 if Present
(Prev_At_End
) then
1517 Prepend_To
(Finalizer_Stmts
,
1518 Make_Procedure_Call_Statement
(Loc
, Prev_At_End
));
1520 -- Clear the At_End handler since we have already generated the
1521 -- proper replacement call for it.
1523 Set_At_End_Proc
(HSS
, Empty
);
1526 -- Release the secondary stack mark
1528 if Present
(Mark_Id
) then
1529 Append_To
(Finalizer_Stmts
, Build_SS_Release_Call
(Loc
, Mark_Id
));
1532 -- Protect the statements with abort defer/undefer. This is only when
1533 -- aborts are allowed and the clean up statements require deferral or
1534 -- there are controlled objects to be finalized.
1536 if Abort_Allowed
and then (Defer_Abort
or Has_Ctrl_Objs
) then
1537 Prepend_To
(Finalizer_Stmts
,
1538 Make_Procedure_Call_Statement
(Loc
,
1539 Name
=> New_Occurrence_Of
(RTE
(RE_Abort_Defer
), Loc
)));
1541 Append_To
(Finalizer_Stmts
,
1542 Make_Procedure_Call_Statement
(Loc
,
1543 Name
=> New_Occurrence_Of
(RTE
(RE_Abort_Undefer
), Loc
)));
1546 -- The local exception does not need to be reraised for library-level
1547 -- finalizers. Note that this action must be carried out after object
1548 -- clean up, secondary stack release and abort undeferral. Generate:
1550 -- if Raised and then not Abort then
1551 -- Raise_From_Controlled_Operation (E);
1554 if Has_Ctrl_Objs
and Exceptions_OK
and not For_Package
then
1555 Append_To
(Finalizer_Stmts
,
1556 Build_Raise_Statement
(Finalizer_Data
));
1560 -- procedure Fin_Id is
1561 -- Abort : constant Boolean := Triggered_By_Abort;
1563 -- Abort : constant Boolean := False; -- no abort
1565 -- E : Exception_Occurrence; -- All added if flag
1566 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1572 -- Abort_Defer; -- Added if abort is allowed
1573 -- <call to Prev_At_End> -- Added if exists
1574 -- <cleanup statements> -- Added if Acts_As_Clean
1575 -- <jump block> -- Added if Has_Ctrl_Objs
1576 -- <finalization statements> -- Added if Has_Ctrl_Objs
1577 -- <stack release> -- Added if Mark_Id exists
1578 -- Abort_Undefer; -- Added if abort is allowed
1579 -- <exception propagation> -- Added if Has_Ctrl_Objs
1582 -- Create the body of the finalizer
1584 Body_Id
:= Make_Defining_Identifier
(Loc
, Chars
(Fin_Id
));
1587 Set_Has_Qualified_Name
(Body_Id
);
1588 Set_Has_Fully_Qualified_Name
(Body_Id
);
1592 Make_Subprogram_Body
(Loc
,
1594 Make_Procedure_Specification
(Loc
,
1595 Defining_Unit_Name
=> Body_Id
),
1596 Declarations
=> Finalizer_Decls
,
1597 Handled_Statement_Sequence
=>
1598 Make_Handled_Sequence_Of_Statements
(Loc
, Finalizer_Stmts
));
1600 -- Step 4: Spec and body insertion, analysis
1604 -- If the package spec has private declarations, the finalizer
1605 -- body must be added to the end of the list in order to have
1606 -- visibility of all private controlled objects.
1608 if For_Package_Spec
then
1609 if Present
(Priv_Decls
) then
1610 Append_To
(Priv_Decls
, Fin_Spec
);
1611 Append_To
(Priv_Decls
, Fin_Body
);
1613 Append_To
(Decls
, Fin_Spec
);
1614 Append_To
(Decls
, Fin_Body
);
1617 -- For package bodies, both the finalizer spec and body are
1618 -- inserted at the end of the package declarations.
1621 Append_To
(Decls
, Fin_Spec
);
1622 Append_To
(Decls
, Fin_Body
);
1625 -- Push the name of the package
1627 Push_Scope
(Spec_Id
);
1635 -- Create the spec for the finalizer. The At_End handler must be
1636 -- able to call the body which resides in a nested structure.
1640 -- procedure Fin_Id; -- Spec
1642 -- <objects and possibly statements>
1643 -- procedure Fin_Id is ... -- Body
1646 -- Fin_Id; -- At_End handler
1649 pragma Assert
(Present
(Spec_Decls
));
1651 Append_To
(Spec_Decls
, Fin_Spec
);
1654 -- When the finalizer acts solely as a clean up routine, the body
1655 -- is inserted right after the spec.
1657 if Acts_As_Clean
and not Has_Ctrl_Objs
then
1658 Insert_After
(Fin_Spec
, Fin_Body
);
1660 -- In all other cases the body is inserted after either:
1662 -- 1) The counter update statement of the last controlled object
1663 -- 2) The last top level nested controlled package
1664 -- 3) The last top level controlled instantiation
1667 -- Manually freeze the spec. This is somewhat of a hack because
1668 -- a subprogram is frozen when its body is seen and the freeze
1669 -- node appears right before the body. However, in this case,
1670 -- the spec must be frozen earlier since the At_End handler
1671 -- must be able to call it.
1674 -- procedure Fin_Id; -- Spec
1675 -- [Fin_Id] -- Freeze node
1679 -- Fin_Id; -- At_End handler
1682 Ensure_Freeze_Node
(Fin_Id
);
1683 Insert_After
(Fin_Spec
, Freeze_Node
(Fin_Id
));
1684 Set_Is_Frozen
(Fin_Id
);
1686 -- In the case where the last construct to contain a controlled
1687 -- object is either a nested package, an instantiation or a
1688 -- freeze node, the body must be inserted directly after the
1691 if Nkind_In
(Last_Top_Level_Ctrl_Construct
,
1693 N_Package_Declaration
,
1696 Finalizer_Insert_Nod
:= Last_Top_Level_Ctrl_Construct
;
1699 Insert_After
(Finalizer_Insert_Nod
, Fin_Body
);
1704 end Create_Finalizer
;
1706 --------------------------
1707 -- Process_Declarations --
1708 --------------------------
1710 procedure Process_Declarations
1712 Preprocess
: Boolean := False;
1713 Top_Level
: Boolean := False)
1718 Obj_Typ
: Entity_Id
;
1719 Pack_Id
: Entity_Id
;
1723 Old_Counter_Val
: Int
;
1724 -- This variable is used to determine whether a nested package or
1725 -- instance contains at least one controlled object.
1727 procedure Processing_Actions
1728 (Has_No_Init
: Boolean := False;
1729 Is_Protected
: Boolean := False);
1730 -- Depending on the mode of operation of Process_Declarations, either
1731 -- increment the controlled object counter, set the controlled object
1732 -- flag and store the last top level construct or process the current
1733 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1734 -- the current declaration may not have initialization proc(s). Flag
1735 -- Is_Protected should be set when the current declaration denotes a
1736 -- simple protected object.
1738 ------------------------
1739 -- Processing_Actions --
1740 ------------------------
1742 procedure Processing_Actions
1743 (Has_No_Init
: Boolean := False;
1744 Is_Protected
: Boolean := False)
1747 -- Library-level tagged type
1749 if Nkind
(Decl
) = N_Full_Type_Declaration
then
1751 Has_Tagged_Types
:= True;
1753 if Top_Level
and then No
(Last_Top_Level_Ctrl_Construct
) then
1754 Last_Top_Level_Ctrl_Construct
:= Decl
;
1758 Process_Tagged_Type_Declaration
(Decl
);
1761 -- Controlled object declaration
1765 Counter_Val
:= Counter_Val
+ 1;
1766 Has_Ctrl_Objs
:= True;
1768 if Top_Level
and then No
(Last_Top_Level_Ctrl_Construct
) then
1769 Last_Top_Level_Ctrl_Construct
:= Decl
;
1773 Process_Object_Declaration
(Decl
, Has_No_Init
, Is_Protected
);
1776 end Processing_Actions
;
1778 -- Start of processing for Process_Declarations
1781 if No
(Decls
) or else Is_Empty_List
(Decls
) then
1785 -- Process all declarations in reverse order
1787 Decl
:= Last_Non_Pragma
(Decls
);
1788 while Present
(Decl
) loop
1790 -- Library-level tagged types
1792 if Nkind
(Decl
) = N_Full_Type_Declaration
then
1793 Typ
:= Defining_Identifier
(Decl
);
1795 -- Ignored Ghost types do not need any cleanup actions because
1796 -- they will not appear in the final tree.
1798 if Is_Ignored_Ghost_Entity
(Typ
) then
1801 elsif Is_Tagged_Type
(Typ
)
1802 and then Is_Library_Level_Entity
(Typ
)
1803 and then Convention
(Typ
) = Convention_Ada
1804 and then Present
(Access_Disp_Table
(Typ
))
1805 and then RTE_Available
(RE_Register_Tag
)
1806 and then not Is_Abstract_Type
(Typ
)
1807 and then not No_Run_Time_Mode
1812 -- Regular object declarations
1814 elsif Nkind
(Decl
) = N_Object_Declaration
then
1815 Obj_Id
:= Defining_Identifier
(Decl
);
1816 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
1817 Expr
:= Expression
(Decl
);
1819 -- Bypass any form of processing for objects which have their
1820 -- finalization disabled. This applies only to objects at the
1823 if For_Package
and then Finalize_Storage_Only
(Obj_Typ
) then
1826 -- Transient variables are treated separately in order to
1827 -- minimize the size of the generated code. For details, see
1828 -- Process_Transient_Objects.
1830 elsif Is_Processed_Transient
(Obj_Id
) then
1833 -- Ignored Ghost objects do not need any cleanup actions
1834 -- because they will not appear in the final tree.
1836 elsif Is_Ignored_Ghost_Entity
(Obj_Id
) then
1839 -- The object is of the form:
1840 -- Obj : Typ [:= Expr];
1842 -- Do not process the incomplete view of a deferred constant.
1843 -- Do not consider tag-to-class-wide conversions.
1845 elsif not Is_Imported
(Obj_Id
)
1846 and then Needs_Finalization
(Obj_Typ
)
1847 and then not (Ekind
(Obj_Id
) = E_Constant
1848 and then not Has_Completion
(Obj_Id
))
1849 and then not Is_Tag_To_Class_Wide_Conversion
(Obj_Id
)
1853 -- The object is of the form:
1854 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1856 -- Obj : Access_Typ :=
1857 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
1859 elsif Is_Access_Type
(Obj_Typ
)
1860 and then Needs_Finalization
1861 (Available_View
(Designated_Type
(Obj_Typ
)))
1862 and then Present
(Expr
)
1864 (Is_Secondary_Stack_BIP_Func_Call
(Expr
)
1866 (Is_Non_BIP_Func_Call
(Expr
)
1867 and then not Is_Related_To_Func_Return
(Obj_Id
)))
1869 Processing_Actions
(Has_No_Init
=> True);
1871 -- Processing for "hook" objects generated for controlled
1872 -- transients declared inside an Expression_With_Actions.
1874 elsif Is_Access_Type
(Obj_Typ
)
1875 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1876 and then Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
1877 N_Object_Declaration
1879 Processing_Actions
(Has_No_Init
=> True);
1881 -- Process intermediate results of an if expression with one
1882 -- of the alternatives using a controlled function call.
1884 elsif Is_Access_Type
(Obj_Typ
)
1885 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1886 and then Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
1887 N_Defining_Identifier
1888 and then Present
(Expr
)
1889 and then Nkind
(Expr
) = N_Null
1891 Processing_Actions
(Has_No_Init
=> True);
1893 -- Simple protected objects which use type System.Tasking.
1894 -- Protected_Objects.Protection to manage their locks should
1895 -- be treated as controlled since they require manual cleanup.
1896 -- The only exception is illustrated in the following example:
1899 -- type Ctrl is new Controlled ...
1900 -- procedure Finalize (Obj : in out Ctrl);
1904 -- package body Pkg is
1905 -- protected Prot is
1906 -- procedure Do_Something (Obj : in out Ctrl);
1909 -- protected body Prot is
1910 -- procedure Do_Something (Obj : in out Ctrl) is ...
1913 -- procedure Finalize (Obj : in out Ctrl) is
1915 -- Prot.Do_Something (Obj);
1919 -- Since for the most part entities in package bodies depend on
1920 -- those in package specs, Prot's lock should be cleaned up
1921 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1922 -- This act however attempts to invoke Do_Something and fails
1923 -- because the lock has disappeared.
1925 elsif Ekind
(Obj_Id
) = E_Variable
1926 and then not In_Library_Level_Package_Body
(Obj_Id
)
1927 and then (Is_Simple_Protected_Type
(Obj_Typ
)
1928 or else Has_Simple_Protected_Object
(Obj_Typ
))
1930 Processing_Actions
(Is_Protected
=> True);
1933 -- Specific cases of object renamings
1935 elsif Nkind
(Decl
) = N_Object_Renaming_Declaration
then
1936 Obj_Id
:= Defining_Identifier
(Decl
);
1937 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
1939 -- Bypass any form of processing for objects which have their
1940 -- finalization disabled. This applies only to objects at the
1943 if For_Package
and then Finalize_Storage_Only
(Obj_Typ
) then
1946 -- Ignored Ghost object renamings do not need any cleanup
1947 -- actions because they will not appear in the final tree.
1949 elsif Is_Ignored_Ghost_Entity
(Obj_Id
) then
1952 -- Return object of a build-in-place function. This case is
1953 -- recognized and marked by the expansion of an extended return
1954 -- statement (see Expand_N_Extended_Return_Statement).
1956 elsif Needs_Finalization
(Obj_Typ
)
1957 and then Is_Return_Object
(Obj_Id
)
1958 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1960 Processing_Actions
(Has_No_Init
=> True);
1962 -- Detect a case where a source object has been initialized by
1963 -- a controlled function call or another object which was later
1964 -- rewritten as a class-wide conversion of Ada.Tags.Displace.
1966 -- Obj1 : CW_Type := Src_Obj;
1967 -- Obj2 : CW_Type := Function_Call (...);
1969 -- Obj1 : CW_Type renames (... Ada.Tags.Displace (Src_Obj));
1970 -- Tmp : ... := Function_Call (...)'reference;
1971 -- Obj2 : CW_Type renames (... Ada.Tags.Displace (Tmp));
1973 elsif Is_Displacement_Of_Object_Or_Function_Result
(Obj_Id
) then
1974 Processing_Actions
(Has_No_Init
=> True);
1977 -- Inspect the freeze node of an access-to-controlled type and
1978 -- look for a delayed finalization master. This case arises when
1979 -- the freeze actions are inserted at a later time than the
1980 -- expansion of the context. Since Build_Finalizer is never called
1981 -- on a single construct twice, the master will be ultimately
1982 -- left out and never finalized. This is also needed for freeze
1983 -- actions of designated types themselves, since in some cases the
1984 -- finalization master is associated with a designated type's
1985 -- freeze node rather than that of the access type (see handling
1986 -- for freeze actions in Build_Finalization_Master).
1988 elsif Nkind
(Decl
) = N_Freeze_Entity
1989 and then Present
(Actions
(Decl
))
1991 Typ
:= Entity
(Decl
);
1993 -- Freeze nodes for ignored Ghost types do not need cleanup
1994 -- actions because they will never appear in the final tree.
1996 if Is_Ignored_Ghost_Entity
(Typ
) then
1999 elsif (Is_Access_Type
(Typ
)
2000 and then not Is_Access_Subprogram_Type
(Typ
)
2001 and then Needs_Finalization
2002 (Available_View
(Designated_Type
(Typ
))))
2003 or else (Is_Type
(Typ
) and then Needs_Finalization
(Typ
))
2005 Old_Counter_Val
:= Counter_Val
;
2007 -- Freeze nodes are considered to be identical to packages
2008 -- and blocks in terms of nesting. The difference is that
2009 -- a finalization master created inside the freeze node is
2010 -- at the same nesting level as the node itself.
2012 Process_Declarations
(Actions
(Decl
), Preprocess
);
2014 -- The freeze node contains a finalization master
2018 and then No
(Last_Top_Level_Ctrl_Construct
)
2019 and then Counter_Val
> Old_Counter_Val
2021 Last_Top_Level_Ctrl_Construct
:= Decl
;
2025 -- Nested package declarations, avoid generics
2027 elsif Nkind
(Decl
) = N_Package_Declaration
then
2028 Pack_Id
:= Defining_Entity
(Decl
);
2029 Spec
:= Specification
(Decl
);
2031 -- Do not inspect an ignored Ghost package because all code
2032 -- found within will not appear in the final tree.
2034 if Is_Ignored_Ghost_Entity
(Pack_Id
) then
2037 elsif Ekind
(Pack_Id
) /= E_Generic_Package
then
2038 Old_Counter_Val
:= Counter_Val
;
2039 Process_Declarations
2040 (Private_Declarations
(Spec
), Preprocess
);
2041 Process_Declarations
2042 (Visible_Declarations
(Spec
), Preprocess
);
2044 -- Either the visible or the private declarations contain a
2045 -- controlled object. The nested package declaration is the
2046 -- last such construct.
2050 and then No
(Last_Top_Level_Ctrl_Construct
)
2051 and then Counter_Val
> Old_Counter_Val
2053 Last_Top_Level_Ctrl_Construct
:= Decl
;
2057 -- Nested package bodies, avoid generics
2059 elsif Nkind
(Decl
) = N_Package_Body
then
2061 -- Do not inspect an ignored Ghost package body because all
2062 -- code found within will not appear in the final tree.
2064 if Is_Ignored_Ghost_Entity
(Defining_Entity
(Decl
)) then
2067 elsif Ekind
(Corresponding_Spec
(Decl
)) /=
2070 Old_Counter_Val
:= Counter_Val
;
2071 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2073 -- The nested package body is the last construct to contain
2074 -- a controlled object.
2078 and then No
(Last_Top_Level_Ctrl_Construct
)
2079 and then Counter_Val
> Old_Counter_Val
2081 Last_Top_Level_Ctrl_Construct
:= Decl
;
2085 -- Handle a rare case caused by a controlled transient variable
2086 -- created as part of a record init proc. The variable is wrapped
2087 -- in a block, but the block is not associated with a transient
2090 elsif Nkind
(Decl
) = N_Block_Statement
2091 and then Inside_Init_Proc
2093 Old_Counter_Val
:= Counter_Val
;
2095 if Present
(Handled_Statement_Sequence
(Decl
)) then
2096 Process_Declarations
2097 (Statements
(Handled_Statement_Sequence
(Decl
)),
2101 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2103 -- Either the declaration or statement list of the block has a
2104 -- controlled object.
2108 and then No
(Last_Top_Level_Ctrl_Construct
)
2109 and then Counter_Val
> Old_Counter_Val
2111 Last_Top_Level_Ctrl_Construct
:= Decl
;
2114 -- Handle the case where the original context has been wrapped in
2115 -- a block to avoid interference between exception handlers and
2116 -- At_End handlers. Treat the block as transparent and process its
2119 elsif Nkind
(Decl
) = N_Block_Statement
2120 and then Is_Finalization_Wrapper
(Decl
)
2122 if Present
(Handled_Statement_Sequence
(Decl
)) then
2123 Process_Declarations
2124 (Statements
(Handled_Statement_Sequence
(Decl
)),
2128 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2131 Prev_Non_Pragma
(Decl
);
2133 end Process_Declarations
;
2135 --------------------------------
2136 -- Process_Object_Declaration --
2137 --------------------------------
2139 procedure Process_Object_Declaration
2141 Has_No_Init
: Boolean := False;
2142 Is_Protected
: Boolean := False)
2144 Loc
: constant Source_Ptr
:= Sloc
(Decl
);
2145 Obj_Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2147 Init_Typ
: Entity_Id
;
2148 -- The initialization type of the related object declaration. Note
2149 -- that this is not necessarely the same type as Obj_Typ because of
2150 -- possible type derivations.
2152 Obj_Typ
: Entity_Id
;
2153 -- The type of the related object declaration
2155 function Build_BIP_Cleanup_Stmts
(Func_Id
: Entity_Id
) return Node_Id
;
2156 -- Func_Id denotes a build-in-place function. Generate the following
2159 -- if BIPallocfrom > Secondary_Stack'Pos
2160 -- and then BIPfinalizationmaster /= null
2163 -- type Ptr_Typ is access Obj_Typ;
2164 -- for Ptr_Typ'Storage_Pool
2165 -- use Base_Pool (BIPfinalizationmaster);
2167 -- Free (Ptr_Typ (Temp));
2171 -- Obj_Typ is the type of the current object, Temp is the original
2172 -- allocation which Obj_Id renames.
2174 procedure Find_Last_Init
2175 (Last_Init
: out Node_Id
;
2176 Body_Insert
: out Node_Id
);
2177 -- Find the last initialization call related to object declaration
2178 -- Decl. Last_Init denotes the last initialization call which follows
2179 -- Decl. Body_Insert denotes a node where the finalizer body could be
2180 -- potentially inserted after (if blocks are involved).
2182 -----------------------------
2183 -- Build_BIP_Cleanup_Stmts --
2184 -----------------------------
2186 function Build_BIP_Cleanup_Stmts
2187 (Func_Id
: Entity_Id
) return Node_Id
2189 Decls
: constant List_Id
:= New_List
;
2190 Fin_Mas_Id
: constant Entity_Id
:=
2191 Build_In_Place_Formal
2192 (Func_Id
, BIP_Finalization_Master
);
2193 Func_Typ
: constant Entity_Id
:= Etype
(Func_Id
);
2194 Temp_Id
: constant Entity_Id
:=
2195 Entity
(Prefix
(Name
(Parent
(Obj_Id
))));
2199 Free_Stmt
: Node_Id
;
2200 Pool_Id
: Entity_Id
;
2201 Ptr_Typ
: Entity_Id
;
2205 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2207 Pool_Id
:= Make_Temporary
(Loc
, 'P');
2210 Make_Object_Renaming_Declaration
(Loc
,
2211 Defining_Identifier
=> Pool_Id
,
2213 New_Occurrence_Of
(RTE
(RE_Root_Storage_Pool
), Loc
),
2215 Make_Explicit_Dereference
(Loc
,
2217 Make_Function_Call
(Loc
,
2219 New_Occurrence_Of
(RTE
(RE_Base_Pool
), Loc
),
2220 Parameter_Associations
=> New_List
(
2221 Make_Explicit_Dereference
(Loc
,
2223 New_Occurrence_Of
(Fin_Mas_Id
, Loc
)))))));
2225 -- Create an access type which uses the storage pool of the
2226 -- caller's finalization master.
2229 -- type Ptr_Typ is access Func_Typ;
2231 Ptr_Typ
:= Make_Temporary
(Loc
, 'P');
2234 Make_Full_Type_Declaration
(Loc
,
2235 Defining_Identifier
=> Ptr_Typ
,
2237 Make_Access_To_Object_Definition
(Loc
,
2238 Subtype_Indication
=> New_Occurrence_Of
(Func_Typ
, Loc
))));
2240 -- Perform minor decoration in order to set the master and the
2241 -- storage pool attributes.
2243 Set_Ekind
(Ptr_Typ
, E_Access_Type
);
2244 Set_Finalization_Master
(Ptr_Typ
, Fin_Mas_Id
);
2245 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
2247 -- Create an explicit free statement. Note that the free uses the
2248 -- caller's pool expressed as a renaming.
2251 Make_Free_Statement
(Loc
,
2253 Unchecked_Convert_To
(Ptr_Typ
,
2254 New_Occurrence_Of
(Temp_Id
, Loc
)));
2256 Set_Storage_Pool
(Free_Stmt
, Pool_Id
);
2258 -- Create a block to house the dummy type and the instantiation as
2259 -- well as to perform the cleanup the temporary.
2265 -- Free (Ptr_Typ (Temp_Id));
2269 Make_Block_Statement
(Loc
,
2270 Declarations
=> Decls
,
2271 Handled_Statement_Sequence
=>
2272 Make_Handled_Sequence_Of_Statements
(Loc
,
2273 Statements
=> New_List
(Free_Stmt
)));
2276 -- if BIPfinalizationmaster /= null then
2280 Left_Opnd
=> New_Occurrence_Of
(Fin_Mas_Id
, Loc
),
2281 Right_Opnd
=> Make_Null
(Loc
));
2283 -- For constrained or tagged results escalate the condition to
2284 -- include the allocation format. Generate:
2286 -- if BIPallocform > Secondary_Stack'Pos
2287 -- and then BIPfinalizationmaster /= null
2290 if not Is_Constrained
(Func_Typ
)
2291 or else Is_Tagged_Type
(Func_Typ
)
2294 Alloc
: constant Entity_Id
:=
2295 Build_In_Place_Formal
(Func_Id
, BIP_Alloc_Form
);
2301 Left_Opnd
=> New_Occurrence_Of
(Alloc
, Loc
),
2303 Make_Integer_Literal
(Loc
,
2305 (BIP_Allocation_Form
'Pos (Secondary_Stack
)))),
2307 Right_Opnd
=> Cond
);
2317 Make_If_Statement
(Loc
,
2319 Then_Statements
=> New_List
(Free_Blk
));
2320 end Build_BIP_Cleanup_Stmts
;
2322 --------------------
2323 -- Find_Last_Init --
2324 --------------------
2326 procedure Find_Last_Init
2327 (Last_Init
: out Node_Id
;
2328 Body_Insert
: out Node_Id
)
2330 function Find_Last_Init_In_Block
(Blk
: Node_Id
) return Node_Id
;
2331 -- Find the last initialization call within the statements of
2334 function Is_Init_Call
(N
: Node_Id
) return Boolean;
2335 -- Determine whether node N denotes one of the initialization
2336 -- procedures of types Init_Typ or Obj_Typ.
2338 function Next_Suitable_Statement
(Stmt
: Node_Id
) return Node_Id
;
2339 -- Given a statement which is part of a list, return the next
2340 -- statement while skipping over dynamic elab checks.
2342 -----------------------------
2343 -- Find_Last_Init_In_Block --
2344 -----------------------------
2346 function Find_Last_Init_In_Block
(Blk
: Node_Id
) return Node_Id
is
2347 HSS
: constant Node_Id
:= Handled_Statement_Sequence
(Blk
);
2351 -- Examine the individual statements of the block in reverse to
2352 -- locate the last initialization call.
2354 if Present
(HSS
) and then Present
(Statements
(HSS
)) then
2355 Stmt
:= Last
(Statements
(HSS
));
2356 while Present
(Stmt
) loop
2358 -- Peek inside nested blocks in case aborts are allowed
2360 if Nkind
(Stmt
) = N_Block_Statement
then
2361 return Find_Last_Init_In_Block
(Stmt
);
2363 elsif Is_Init_Call
(Stmt
) then
2372 end Find_Last_Init_In_Block
;
2378 function Is_Init_Call
(N
: Node_Id
) return Boolean is
2379 function Is_Init_Proc_Of
2380 (Subp_Id
: Entity_Id
;
2381 Typ
: Entity_Id
) return Boolean;
2382 -- Determine whether subprogram Subp_Id is a valid init proc of
2385 ---------------------
2386 -- Is_Init_Proc_Of --
2387 ---------------------
2389 function Is_Init_Proc_Of
2390 (Subp_Id
: Entity_Id
;
2391 Typ
: Entity_Id
) return Boolean
2393 Deep_Init
: Entity_Id
:= Empty
;
2394 Prim_Init
: Entity_Id
:= Empty
;
2395 Type_Init
: Entity_Id
:= Empty
;
2398 -- Obtain all possible initialization routines of the
2399 -- related type and try to match the subprogram entity
2400 -- against one of them.
2404 Deep_Init
:= TSS
(Typ
, TSS_Deep_Initialize
);
2406 -- Primitive Initialize
2408 if Is_Controlled
(Typ
) then
2409 Prim_Init
:= Find_Prim_Op
(Typ
, Name_Initialize
);
2411 if Present
(Prim_Init
) then
2412 Prim_Init
:= Ultimate_Alias
(Prim_Init
);
2416 -- Type initialization routine
2418 if Has_Non_Null_Base_Init_Proc
(Typ
) then
2419 Type_Init
:= Base_Init_Proc
(Typ
);
2423 (Present
(Deep_Init
) and then Subp_Id
= Deep_Init
)
2425 (Present
(Prim_Init
) and then Subp_Id
= Prim_Init
)
2427 (Present
(Type_Init
) and then Subp_Id
= Type_Init
);
2428 end Is_Init_Proc_Of
;
2432 Call_Id
: Entity_Id
;
2434 -- Start of processing for Is_Init_Call
2437 if Nkind
(N
) = N_Procedure_Call_Statement
2438 and then Nkind
(Name
(N
)) = N_Identifier
2440 Call_Id
:= Entity
(Name
(N
));
2442 -- Consider both the type of the object declaration and its
2443 -- related initialization type.
2446 Is_Init_Proc_Of
(Call_Id
, Init_Typ
)
2448 Is_Init_Proc_Of
(Call_Id
, Obj_Typ
);
2454 -----------------------------
2455 -- Next_Suitable_Statement --
2456 -----------------------------
2458 function Next_Suitable_Statement
(Stmt
: Node_Id
) return Node_Id
is
2459 Result
: Node_Id
:= Next
(Stmt
);
2462 -- Skip over access-before-elaboration checks
2464 if Dynamic_Elaboration_Checks
2465 and then Nkind
(Result
) = N_Raise_Program_Error
2467 Result
:= Next
(Result
);
2471 end Next_Suitable_Statement
;
2479 Deep_Init_Found
: Boolean := False;
2480 -- A flag set when a call to [Deep_]Initialize has been found
2482 -- Start of processing for Find_Last_Init
2486 Body_Insert
:= Empty
;
2488 -- Object renamings and objects associated with controlled
2489 -- function results do not require initialization.
2495 Stmt
:= Next_Suitable_Statement
(Decl
);
2497 -- A limited controlled object initialized by a function call uses
2498 -- the build-in-place machinery to obtain its value.
2500 -- Obj : Lim_Controlled_Type := Func_Call;
2504 -- Obj : Lim_Controlled_Type;
2505 -- type Ptr_Typ is access Lim_Controlled_Type;
2506 -- Temp : constant Ptr_Typ :=
2509 -- BIPaccess => Obj'Unrestricted_Access)'reference;
2511 -- In this scenario the declaration of the temporary acts as the
2512 -- last initialization statement.
2514 if Is_Limited_Type
(Obj_Typ
)
2515 and then Has_Init_Expression
(Decl
)
2516 and then No
(Expression
(Decl
))
2518 while Present
(Stmt
) loop
2519 if Nkind
(Stmt
) = N_Object_Declaration
2520 and then Present
(Expression
(Stmt
))
2521 and then Is_Object_Access_BIP_Func_Call
2522 (Expr
=> Expression
(Stmt
),
2532 -- Nothing to do for an object with supporessed initialization.
2533 -- Note that this check is not performed at the beginning of the
2534 -- routine because a declaration marked with No_Initialization
2535 -- may still be initialized by a build-in-place call (the case
2538 elsif No_Initialization
(Decl
) then
2541 -- In all other cases the initialization calls follow the related
2542 -- object. The general structure of object initialization built by
2543 -- routine Default_Initialize_Object is as follows:
2545 -- [begin -- aborts allowed
2547 -- Type_Init_Proc (Obj);
2548 -- [begin] -- exceptions allowed
2549 -- Deep_Initialize (Obj);
2550 -- [exception -- exceptions allowed
2552 -- Deep_Finalize (Obj, Self => False);
2555 -- [at end -- aborts allowed
2559 -- When aborts are allowed, the initialization calls are housed
2562 elsif Nkind
(Stmt
) = N_Block_Statement
then
2563 Last_Init
:= Find_Last_Init_In_Block
(Stmt
);
2564 Body_Insert
:= Stmt
;
2566 -- Otherwise the initialization calls follow the related object
2569 Stmt_2
:= Next_Suitable_Statement
(Stmt
);
2571 -- Check for an optional call to Deep_Initialize which may
2572 -- appear within a block depending on whether the object has
2573 -- controlled components.
2575 if Present
(Stmt_2
) then
2576 if Nkind
(Stmt_2
) = N_Block_Statement
then
2577 Call
:= Find_Last_Init_In_Block
(Stmt_2
);
2579 if Present
(Call
) then
2580 Deep_Init_Found
:= True;
2582 Body_Insert
:= Stmt_2
;
2585 elsif Is_Init_Call
(Stmt_2
) then
2586 Deep_Init_Found
:= True;
2587 Last_Init
:= Stmt_2
;
2588 Body_Insert
:= Last_Init
;
2592 -- If the object lacks a call to Deep_Initialize, then it must
2593 -- have a call to its related type init proc.
2595 if not Deep_Init_Found
and then Is_Init_Call
(Stmt
) then
2597 Body_Insert
:= Last_Init
;
2605 Count_Ins
: Node_Id
;
2607 Fin_Stmts
: List_Id
;
2610 Label_Id
: Entity_Id
;
2613 -- Start of processing for Process_Object_Declaration
2616 -- Handle the object type and the reference to the object
2618 Obj_Ref
:= New_Occurrence_Of
(Obj_Id
, Loc
);
2619 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
2622 if Is_Access_Type
(Obj_Typ
) then
2623 Obj_Typ
:= Directly_Designated_Type
(Obj_Typ
);
2624 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
2626 elsif Is_Concurrent_Type
(Obj_Typ
)
2627 and then Present
(Corresponding_Record_Type
(Obj_Typ
))
2629 Obj_Typ
:= Corresponding_Record_Type
(Obj_Typ
);
2630 Obj_Ref
:= Unchecked_Convert_To
(Obj_Typ
, Obj_Ref
);
2632 elsif Is_Private_Type
(Obj_Typ
)
2633 and then Present
(Full_View
(Obj_Typ
))
2635 Obj_Typ
:= Full_View
(Obj_Typ
);
2636 Obj_Ref
:= Unchecked_Convert_To
(Obj_Typ
, Obj_Ref
);
2638 elsif Obj_Typ
/= Base_Type
(Obj_Typ
) then
2639 Obj_Typ
:= Base_Type
(Obj_Typ
);
2640 Obj_Ref
:= Unchecked_Convert_To
(Obj_Typ
, Obj_Ref
);
2647 Set_Etype
(Obj_Ref
, Obj_Typ
);
2649 -- Handle the initialization type of the object declaration
2651 Init_Typ
:= Obj_Typ
;
2653 if Is_Private_Type
(Init_Typ
)
2654 and then Present
(Full_View
(Init_Typ
))
2656 Init_Typ
:= Full_View
(Init_Typ
);
2658 elsif Is_Untagged_Derivation
(Init_Typ
) then
2659 Init_Typ
:= Root_Type
(Init_Typ
);
2666 -- Set a new value for the state counter and insert the statement
2667 -- after the object declaration. Generate:
2669 -- Counter := <value>;
2672 Make_Assignment_Statement
(Loc
,
2673 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
2674 Expression
=> Make_Integer_Literal
(Loc
, Counter_Val
));
2676 -- Insert the counter after all initialization has been done. The
2677 -- place of insertion depends on the context. If an object is being
2678 -- initialized via an aggregate, then the counter must be inserted
2679 -- after the last aggregate assignment.
2681 if Ekind_In
(Obj_Id
, E_Constant
, E_Variable
)
2682 and then Present
(Last_Aggregate_Assignment
(Obj_Id
))
2684 Count_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
2687 -- In all other cases the counter is inserted after the last call to
2688 -- either [Deep_]Initialize or the type specific init proc.
2691 Find_Last_Init
(Count_Ins
, Body_Ins
);
2694 Insert_After
(Count_Ins
, Inc_Decl
);
2697 -- If the current declaration is the last in the list, the finalizer
2698 -- body needs to be inserted after the set counter statement for the
2699 -- current object declaration. This is complicated by the fact that
2700 -- the set counter statement may appear in abort deferred block. In
2701 -- that case, the proper insertion place is after the block.
2703 if No
(Finalizer_Insert_Nod
) then
2705 -- Insertion after an abort deffered block
2707 if Present
(Body_Ins
) then
2708 Finalizer_Insert_Nod
:= Body_Ins
;
2710 Finalizer_Insert_Nod
:= Inc_Decl
;
2714 -- Create the associated label with this object, generate:
2716 -- L<counter> : label;
2719 Make_Identifier
(Loc
, New_External_Name
('L', Counter_Val
));
2721 (Label_Id
, Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
2722 Label
:= Make_Label
(Loc
, Label_Id
);
2724 Prepend_To
(Finalizer_Decls
,
2725 Make_Implicit_Label_Declaration
(Loc
,
2726 Defining_Identifier
=> Entity
(Label_Id
),
2727 Label_Construct
=> Label
));
2729 -- Create the associated jump with this object, generate:
2731 -- when <counter> =>
2734 Prepend_To
(Jump_Alts
,
2735 Make_Case_Statement_Alternative
(Loc
,
2736 Discrete_Choices
=> New_List
(
2737 Make_Integer_Literal
(Loc
, Counter_Val
)),
2738 Statements
=> New_List
(
2739 Make_Goto_Statement
(Loc
,
2740 Name
=> New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
2742 -- Insert the jump destination, generate:
2746 Append_To
(Finalizer_Stmts
, Label
);
2748 -- Processing for simple protected objects. Such objects require
2749 -- manual finalization of their lock managers.
2751 if Is_Protected
then
2752 Fin_Stmts
:= No_List
;
2754 if Is_Simple_Protected_Type
(Obj_Typ
) then
2755 Fin_Call
:= Cleanup_Protected_Object
(Decl
, Obj_Ref
);
2757 if Present
(Fin_Call
) then
2758 Fin_Stmts
:= New_List
(Fin_Call
);
2761 elsif Has_Simple_Protected_Object
(Obj_Typ
) then
2762 if Is_Record_Type
(Obj_Typ
) then
2763 Fin_Stmts
:= Cleanup_Record
(Decl
, Obj_Ref
, Obj_Typ
);
2764 elsif Is_Array_Type
(Obj_Typ
) then
2765 Fin_Stmts
:= Cleanup_Array
(Decl
, Obj_Ref
, Obj_Typ
);
2771 -- System.Tasking.Protected_Objects.Finalize_Protection
2779 if Present
(Fin_Stmts
) then
2780 Append_To
(Finalizer_Stmts
,
2781 Make_Block_Statement
(Loc
,
2782 Handled_Statement_Sequence
=>
2783 Make_Handled_Sequence_Of_Statements
(Loc
,
2784 Statements
=> Fin_Stmts
,
2786 Exception_Handlers
=> New_List
(
2787 Make_Exception_Handler
(Loc
,
2788 Exception_Choices
=> New_List
(
2789 Make_Others_Choice
(Loc
)),
2791 Statements
=> New_List
(
2792 Make_Null_Statement
(Loc
)))))));
2795 -- Processing for regular controlled objects
2799 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2801 -- begin -- Exception handlers allowed
2802 -- [Deep_]Finalize (Obj);
2805 -- when Id : others =>
2806 -- if not Raised then
2808 -- Save_Occurrence (E, Id);
2817 -- For CodePeer, the exception handlers normally generated here
2818 -- generate complex flowgraphs which result in capacity problems.
2819 -- Omitting these handlers for CodePeer is justified as follows:
2821 -- If a handler is dead, then omitting it is surely ok
2823 -- If a handler is live, then CodePeer should flag the
2824 -- potentially-exception-raising construct that causes it
2825 -- to be live. That is what we are interested in, not what
2826 -- happens after the exception is raised.
2828 if Exceptions_OK
and not CodePeer_Mode
then
2829 Fin_Stmts
:= New_List
(
2830 Make_Block_Statement
(Loc
,
2831 Handled_Statement_Sequence
=>
2832 Make_Handled_Sequence_Of_Statements
(Loc
,
2833 Statements
=> New_List
(Fin_Call
),
2835 Exception_Handlers
=> New_List
(
2836 Build_Exception_Handler
2837 (Finalizer_Data
, For_Package
)))));
2839 -- When exception handlers are prohibited, the finalization call
2840 -- appears unprotected. Any exception raised during finalization
2841 -- will bypass the circuitry which ensures the cleanup of all
2842 -- remaining objects.
2845 Fin_Stmts
:= New_List
(Fin_Call
);
2848 -- If we are dealing with a return object of a build-in-place
2849 -- function, generate the following cleanup statements:
2851 -- if BIPallocfrom > Secondary_Stack'Pos
2852 -- and then BIPfinalizationmaster /= null
2855 -- type Ptr_Typ is access Obj_Typ;
2856 -- for Ptr_Typ'Storage_Pool use
2857 -- Base_Pool (BIPfinalizationmaster.all).all;
2859 -- Free (Ptr_Typ (Temp));
2863 -- The generated code effectively detaches the temporary from the
2864 -- caller finalization master and deallocates the object. This is
2865 -- disabled on .NET/JVM because pools are not supported.
2867 if VM_Target
= No_VM
and then Is_Return_Object
(Obj_Id
) then
2869 Func_Id
: constant Entity_Id
:= Enclosing_Function
(Obj_Id
);
2871 if Is_Build_In_Place_Function
(Func_Id
)
2872 and then Needs_BIP_Finalization_Master
(Func_Id
)
2874 Append_To
(Fin_Stmts
, Build_BIP_Cleanup_Stmts
(Func_Id
));
2879 if Ekind_In
(Obj_Id
, E_Constant
, E_Variable
)
2880 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
2882 -- Temporaries created for the purpose of "exporting" a
2883 -- controlled transient out of an Expression_With_Actions (EWA)
2884 -- need guards. The following illustrates the usage of such
2887 -- Access_Typ : access [all] Obj_Typ;
2888 -- Temp : Access_Typ := null;
2889 -- <Counter> := ...;
2892 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2893 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2895 -- Temp := Ctrl_Trans'Unchecked_Access;
2898 -- The finalization machinery does not process EWA nodes as
2899 -- this may lead to premature finalization of expressions. Note
2900 -- that Temp is marked as being properly initialized regardless
2901 -- of whether the initialization of Ctrl_Trans succeeded. Since
2902 -- a failed initialization may leave Temp with a value of null,
2903 -- add a guard to handle this case:
2905 -- if Obj /= null then
2906 -- <object finalization statements>
2909 if Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
2910 N_Object_Declaration
2912 Fin_Stmts
:= New_List
(
2913 Make_If_Statement
(Loc
,
2916 Left_Opnd
=> New_Occurrence_Of
(Obj_Id
, Loc
),
2917 Right_Opnd
=> Make_Null
(Loc
)),
2918 Then_Statements
=> Fin_Stmts
));
2920 -- Return objects use a flag to aid in processing their
2921 -- potential finalization when the enclosing function fails
2922 -- to return properly. Generate:
2925 -- <object finalization statements>
2929 Fin_Stmts
:= New_List
(
2930 Make_If_Statement
(Loc
,
2935 (Status_Flag_Or_Transient_Decl
(Obj_Id
), Loc
)),
2937 Then_Statements
=> Fin_Stmts
));
2942 Append_List_To
(Finalizer_Stmts
, Fin_Stmts
);
2944 -- Since the declarations are examined in reverse, the state counter
2945 -- must be decremented in order to keep with the true position of
2948 Counter_Val
:= Counter_Val
- 1;
2949 end Process_Object_Declaration
;
2951 -------------------------------------
2952 -- Process_Tagged_Type_Declaration --
2953 -------------------------------------
2955 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
) is
2956 Typ
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2957 DT_Ptr
: constant Entity_Id
:=
2958 Node
(First_Elmt
(Access_Disp_Table
(Typ
)));
2961 -- Ada.Tags.Unregister_Tag (<Typ>P);
2963 Append_To
(Tagged_Type_Stmts
,
2964 Make_Procedure_Call_Statement
(Loc
,
2966 New_Occurrence_Of
(RTE
(RE_Unregister_Tag
), Loc
),
2967 Parameter_Associations
=> New_List
(
2968 New_Occurrence_Of
(DT_Ptr
, Loc
))));
2969 end Process_Tagged_Type_Declaration
;
2971 -- Start of processing for Build_Finalizer
2976 -- Do not perform this expansion in SPARK mode because it is not
2979 if GNATprove_Mode
then
2983 -- Step 1: Extract all lists which may contain controlled objects or
2984 -- library-level tagged types.
2986 if For_Package_Spec
then
2987 Decls
:= Visible_Declarations
(Specification
(N
));
2988 Priv_Decls
:= Private_Declarations
(Specification
(N
));
2990 -- Retrieve the package spec id
2992 Spec_Id
:= Defining_Unit_Name
(Specification
(N
));
2994 if Nkind
(Spec_Id
) = N_Defining_Program_Unit_Name
then
2995 Spec_Id
:= Defining_Identifier
(Spec_Id
);
2998 -- Accept statement, block, entry body, package body, protected body,
2999 -- subprogram body or task body.
3002 Decls
:= Declarations
(N
);
3003 HSS
:= Handled_Statement_Sequence
(N
);
3005 if Present
(HSS
) then
3006 if Present
(Statements
(HSS
)) then
3007 Stmts
:= Statements
(HSS
);
3010 if Present
(At_End_Proc
(HSS
)) then
3011 Prev_At_End
:= At_End_Proc
(HSS
);
3015 -- Retrieve the package spec id for package bodies
3017 if For_Package_Body
then
3018 Spec_Id
:= Corresponding_Spec
(N
);
3022 -- Do not process nested packages since those are handled by the
3023 -- enclosing scope's finalizer. Do not process non-expanded package
3024 -- instantiations since those will be re-analyzed and re-expanded.
3028 (not Is_Library_Level_Entity
(Spec_Id
)
3030 -- Nested packages are considered to be library level entities,
3031 -- but do not need to be processed separately. True library level
3032 -- packages have a scope value of 1.
3034 or else Scope_Depth_Value
(Spec_Id
) /= Uint_1
3035 or else (Is_Generic_Instance
(Spec_Id
)
3036 and then Package_Instantiation
(Spec_Id
) /= N
))
3041 -- Step 2: Object [pre]processing
3045 -- Preprocess the visible declarations now in order to obtain the
3046 -- correct number of controlled object by the time the private
3047 -- declarations are processed.
3049 Process_Declarations
(Decls
, Preprocess
=> True, Top_Level
=> True);
3051 -- From all the possible contexts, only package specifications may
3052 -- have private declarations.
3054 if For_Package_Spec
then
3055 Process_Declarations
3056 (Priv_Decls
, Preprocess
=> True, Top_Level
=> True);
3059 -- The current context may lack controlled objects, but require some
3060 -- other form of completion (task termination for instance). In such
3061 -- cases, the finalizer must be created and carry the additional
3064 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
3068 -- The preprocessing has determined that the context has controlled
3069 -- objects or library-level tagged types.
3071 if Has_Ctrl_Objs
or Has_Tagged_Types
then
3073 -- Private declarations are processed first in order to preserve
3074 -- possible dependencies between public and private objects.
3076 if For_Package_Spec
then
3077 Process_Declarations
(Priv_Decls
);
3080 Process_Declarations
(Decls
);
3086 -- Preprocess both declarations and statements
3088 Process_Declarations
(Decls
, Preprocess
=> True, Top_Level
=> True);
3089 Process_Declarations
(Stmts
, Preprocess
=> True, Top_Level
=> True);
3091 -- At this point it is known that N has controlled objects. Ensure
3092 -- that N has a declarative list since the finalizer spec will be
3095 if Has_Ctrl_Objs
and then No
(Decls
) then
3096 Set_Declarations
(N
, New_List
);
3097 Decls
:= Declarations
(N
);
3098 Spec_Decls
:= Decls
;
3101 -- The current context may lack controlled objects, but require some
3102 -- other form of completion (task termination for instance). In such
3103 -- cases, the finalizer must be created and carry the additional
3106 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
3110 if Has_Ctrl_Objs
or Has_Tagged_Types
then
3111 Process_Declarations
(Stmts
);
3112 Process_Declarations
(Decls
);
3116 -- Step 3: Finalizer creation
3118 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
3121 end Build_Finalizer
;
3123 --------------------------
3124 -- Build_Finalizer_Call --
3125 --------------------------
3127 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
) is
3128 Is_Prot_Body
: constant Boolean :=
3129 Nkind
(N
) = N_Subprogram_Body
3130 and then Is_Protected_Subprogram_Body
(N
);
3131 -- Determine whether N denotes the protected version of a subprogram
3132 -- which belongs to a protected type.
3134 Loc
: constant Source_Ptr
:= Sloc
(N
);
3138 -- Do not perform this expansion in SPARK mode because we do not create
3139 -- finalizers in the first place.
3141 if GNATprove_Mode
then
3145 -- The At_End handler should have been assimilated by the finalizer
3147 HSS
:= Handled_Statement_Sequence
(N
);
3148 pragma Assert
(No
(At_End_Proc
(HSS
)));
3150 -- If the construct to be cleaned up is a protected subprogram body, the
3151 -- finalizer call needs to be associated with the block which wraps the
3152 -- unprotected version of the subprogram. The following illustrates this
3155 -- procedure Prot_SubpP is
3156 -- procedure finalizer is
3158 -- Service_Entries (Prot_Obj);
3165 -- Prot_SubpN (Prot_Obj);
3171 if Is_Prot_Body
then
3172 HSS
:= Handled_Statement_Sequence
(Last
(Statements
(HSS
)));
3174 -- An At_End handler and regular exception handlers cannot coexist in
3175 -- the same statement sequence. Wrap the original statements in a block.
3177 elsif Present
(Exception_Handlers
(HSS
)) then
3179 End_Lab
: constant Node_Id
:= End_Label
(HSS
);
3184 Make_Block_Statement
(Loc
, Handled_Statement_Sequence
=> HSS
);
3186 Set_Handled_Statement_Sequence
(N
,
3187 Make_Handled_Sequence_Of_Statements
(Loc
, New_List
(Block
)));
3189 HSS
:= Handled_Statement_Sequence
(N
);
3190 Set_End_Label
(HSS
, End_Lab
);
3194 Set_At_End_Proc
(HSS
, New_Occurrence_Of
(Fin_Id
, Loc
));
3196 Analyze
(At_End_Proc
(HSS
));
3197 Expand_At_End_Handler
(HSS
, Empty
);
3198 end Build_Finalizer_Call
;
3200 ---------------------
3201 -- Build_Late_Proc --
3202 ---------------------
3204 procedure Build_Late_Proc
(Typ
: Entity_Id
; Nam
: Name_Id
) is
3206 for Final_Prim
in Name_Of
'Range loop
3207 if Name_Of
(Final_Prim
) = Nam
then
3210 (Prim
=> Final_Prim
,
3212 Stmts
=> Make_Deep_Record_Body
(Final_Prim
, Typ
)));
3215 end Build_Late_Proc
;
3217 -------------------------------
3218 -- Build_Object_Declarations --
3219 -------------------------------
3221 procedure Build_Object_Declarations
3222 (Data
: out Finalization_Exception_Data
;
3225 For_Package
: Boolean := False)
3230 -- This variable captures an unused dummy internal entity, see the
3231 -- comment associated with its use.
3234 pragma Assert
(Decls
/= No_List
);
3236 -- Always set the proper location as it may be needed even when
3237 -- exception propagation is forbidden.
3241 if Restriction_Active
(No_Exception_Propagation
) then
3242 Data
.Abort_Id
:= Empty
;
3244 Data
.Raised_Id
:= Empty
;
3248 Data
.Raised_Id
:= Make_Temporary
(Loc
, 'R');
3250 -- In certain scenarios, finalization can be triggered by an abort. If
3251 -- the finalization itself fails and raises an exception, the resulting
3252 -- Program_Error must be supressed and replaced by an abort signal. In
3253 -- order to detect this scenario, save the state of entry into the
3254 -- finalization code.
3256 -- No need to do this for VM case, since VM version of Ada.Exceptions
3257 -- does not include routine Raise_From_Controlled_Operation which is the
3258 -- the sole user of flag Abort.
3260 -- This is not needed for library-level finalizers as they are called by
3261 -- the environment task and cannot be aborted.
3263 if VM_Target
= No_VM
and then not For_Package
then
3264 if Abort_Allowed
then
3265 Data
.Abort_Id
:= Make_Temporary
(Loc
, 'A');
3268 -- Abort_Id : constant Boolean := <A_Expr>;
3271 Make_Object_Declaration
(Loc
,
3272 Defining_Identifier
=> Data
.Abort_Id
,
3273 Constant_Present
=> True,
3274 Object_Definition
=>
3275 New_Occurrence_Of
(Standard_Boolean
, Loc
),
3277 New_Occurrence_Of
(RTE
(RE_Triggered_By_Abort
), Loc
)));
3279 -- Abort is not required
3282 -- Generate a dummy entity to ensure that the internal symbols are
3283 -- in sync when a unit is compiled with and without aborts.
3285 Dummy
:= Make_Temporary
(Loc
, 'A');
3286 Data
.Abort_Id
:= Empty
;
3289 -- .NET/JVM or library-level finalizers
3292 Data
.Abort_Id
:= Empty
;
3295 if Exception_Extra_Info
then
3296 Data
.E_Id
:= Make_Temporary
(Loc
, 'E');
3299 -- E_Id : Exception_Occurrence;
3302 Make_Object_Declaration
(Loc
,
3303 Defining_Identifier
=> Data
.E_Id
,
3304 Object_Definition
=>
3305 New_Occurrence_Of
(RTE
(RE_Exception_Occurrence
), Loc
));
3306 Set_No_Initialization
(Decl
);
3308 Append_To
(Decls
, Decl
);
3315 -- Raised_Id : Boolean := False;
3318 Make_Object_Declaration
(Loc
,
3319 Defining_Identifier
=> Data
.Raised_Id
,
3320 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
3321 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
)));
3322 end Build_Object_Declarations
;
3324 ---------------------------
3325 -- Build_Raise_Statement --
3326 ---------------------------
3328 function Build_Raise_Statement
3329 (Data
: Finalization_Exception_Data
) return Node_Id
3335 -- Standard run-time and .NET/JVM targets use the specialized routine
3336 -- Raise_From_Controlled_Operation.
3338 if Exception_Extra_Info
3339 and then RTE_Available
(RE_Raise_From_Controlled_Operation
)
3342 Make_Procedure_Call_Statement
(Data
.Loc
,
3345 (RTE
(RE_Raise_From_Controlled_Operation
), Data
.Loc
),
3346 Parameter_Associations
=>
3347 New_List
(New_Occurrence_Of
(Data
.E_Id
, Data
.Loc
)));
3349 -- Restricted run-time: exception messages are not supported and hence
3350 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3355 Make_Raise_Program_Error
(Data
.Loc
,
3356 Reason
=> PE_Finalize_Raised_Exception
);
3361 -- Raised_Id and then not Abort_Id
3365 Expr
:= New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
);
3367 if Present
(Data
.Abort_Id
) then
3368 Expr
:= Make_And_Then
(Data
.Loc
,
3371 Make_Op_Not
(Data
.Loc
,
3372 Right_Opnd
=> New_Occurrence_Of
(Data
.Abort_Id
, Data
.Loc
)));
3377 -- if Raised_Id and then not Abort_Id then
3378 -- Raise_From_Controlled_Operation (E_Id);
3380 -- raise Program_Error; -- restricted runtime
3384 Make_If_Statement
(Data
.Loc
,
3386 Then_Statements
=> New_List
(Stmt
));
3387 end Build_Raise_Statement
;
3389 -----------------------------
3390 -- Build_Record_Deep_Procs --
3391 -----------------------------
3393 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
) is
3397 (Prim
=> Initialize_Case
,
3399 Stmts
=> Make_Deep_Record_Body
(Initialize_Case
, Typ
)));
3401 if not Is_Limited_View
(Typ
) then
3404 (Prim
=> Adjust_Case
,
3406 Stmts
=> Make_Deep_Record_Body
(Adjust_Case
, Typ
)));
3409 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3410 -- suppressed since these routine will not be used.
3412 if not Restriction_Active
(No_Finalization
) then
3415 (Prim
=> Finalize_Case
,
3417 Stmts
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
)));
3419 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3420 -- .NET do not support address arithmetic and unchecked conversions.
3422 if VM_Target
= No_VM
then
3425 (Prim
=> Address_Case
,
3427 Stmts
=> Make_Deep_Record_Body
(Address_Case
, Typ
)));
3430 end Build_Record_Deep_Procs
;
3436 function Cleanup_Array
3439 Typ
: Entity_Id
) return List_Id
3441 Loc
: constant Source_Ptr
:= Sloc
(N
);
3442 Index_List
: constant List_Id
:= New_List
;
3444 function Free_Component
return List_Id
;
3445 -- Generate the code to finalize the task or protected subcomponents
3446 -- of a single component of the array.
3448 function Free_One_Dimension
(Dim
: Int
) return List_Id
;
3449 -- Generate a loop over one dimension of the array
3451 --------------------
3452 -- Free_Component --
3453 --------------------
3455 function Free_Component
return List_Id
is
3456 Stmts
: List_Id
:= New_List
;
3458 C_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
3461 -- Component type is known to contain tasks or protected objects
3464 Make_Indexed_Component
(Loc
,
3465 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3466 Expressions
=> Index_List
);
3468 Set_Etype
(Tsk
, C_Typ
);
3470 if Is_Task_Type
(C_Typ
) then
3471 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3473 elsif Is_Simple_Protected_Type
(C_Typ
) then
3474 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3476 elsif Is_Record_Type
(C_Typ
) then
3477 Stmts
:= Cleanup_Record
(N
, Tsk
, C_Typ
);
3479 elsif Is_Array_Type
(C_Typ
) then
3480 Stmts
:= Cleanup_Array
(N
, Tsk
, C_Typ
);
3486 ------------------------
3487 -- Free_One_Dimension --
3488 ------------------------
3490 function Free_One_Dimension
(Dim
: Int
) return List_Id
is
3494 if Dim
> Number_Dimensions
(Typ
) then
3495 return Free_Component
;
3497 -- Here we generate the required loop
3500 Index
:= Make_Temporary
(Loc
, 'J');
3501 Append
(New_Occurrence_Of
(Index
, Loc
), Index_List
);
3504 Make_Implicit_Loop_Statement
(N
,
3505 Identifier
=> Empty
,
3507 Make_Iteration_Scheme
(Loc
,
3508 Loop_Parameter_Specification
=>
3509 Make_Loop_Parameter_Specification
(Loc
,
3510 Defining_Identifier
=> Index
,
3511 Discrete_Subtype_Definition
=>
3512 Make_Attribute_Reference
(Loc
,
3513 Prefix
=> Duplicate_Subexpr
(Obj
),
3514 Attribute_Name
=> Name_Range
,
3515 Expressions
=> New_List
(
3516 Make_Integer_Literal
(Loc
, Dim
))))),
3517 Statements
=> Free_One_Dimension
(Dim
+ 1)));
3519 end Free_One_Dimension
;
3521 -- Start of processing for Cleanup_Array
3524 return Free_One_Dimension
(1);
3527 --------------------
3528 -- Cleanup_Record --
3529 --------------------
3531 function Cleanup_Record
3534 Typ
: Entity_Id
) return List_Id
3536 Loc
: constant Source_Ptr
:= Sloc
(N
);
3539 Stmts
: constant List_Id
:= New_List
;
3540 U_Typ
: constant Entity_Id
:= Underlying_Type
(Typ
);
3543 if Has_Discriminants
(U_Typ
)
3544 and then Nkind
(Parent
(U_Typ
)) = N_Full_Type_Declaration
3545 and then Nkind
(Type_Definition
(Parent
(U_Typ
))) = N_Record_Definition
3548 (Variant_Part
(Component_List
(Type_Definition
(Parent
(U_Typ
)))))
3550 -- For now, do not attempt to free a component that may appear in a
3551 -- variant, and instead issue a warning. Doing this "properly" would
3552 -- require building a case statement and would be quite a mess. Note
3553 -- that the RM only requires that free "work" for the case of a task
3554 -- access value, so already we go way beyond this in that we deal
3555 -- with the array case and non-discriminated record cases.
3558 ("task/protected object in variant record will not be freed??", N
);
3559 return New_List
(Make_Null_Statement
(Loc
));
3562 Comp
:= First_Component
(Typ
);
3563 while Present
(Comp
) loop
3564 if Has_Task
(Etype
(Comp
))
3565 or else Has_Simple_Protected_Object
(Etype
(Comp
))
3568 Make_Selected_Component
(Loc
,
3569 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3570 Selector_Name
=> New_Occurrence_Of
(Comp
, Loc
));
3571 Set_Etype
(Tsk
, Etype
(Comp
));
3573 if Is_Task_Type
(Etype
(Comp
)) then
3574 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3576 elsif Is_Simple_Protected_Type
(Etype
(Comp
)) then
3577 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3579 elsif Is_Record_Type
(Etype
(Comp
)) then
3581 -- Recurse, by generating the prefix of the argument to
3582 -- the eventual cleanup call.
3584 Append_List_To
(Stmts
, Cleanup_Record
(N
, Tsk
, Etype
(Comp
)));
3586 elsif Is_Array_Type
(Etype
(Comp
)) then
3587 Append_List_To
(Stmts
, Cleanup_Array
(N
, Tsk
, Etype
(Comp
)));
3591 Next_Component
(Comp
);
3597 ------------------------------
3598 -- Cleanup_Protected_Object --
3599 ------------------------------
3601 function Cleanup_Protected_Object
3603 Ref
: Node_Id
) return Node_Id
3605 Loc
: constant Source_Ptr
:= Sloc
(N
);
3608 -- For restricted run-time libraries (Ravenscar), tasks are
3609 -- non-terminating, and protected objects can only appear at library
3610 -- level, so we do not want finalization of protected objects.
3612 if Restricted_Profile
then
3617 Make_Procedure_Call_Statement
(Loc
,
3619 New_Occurrence_Of
(RTE
(RE_Finalize_Protection
), Loc
),
3620 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3622 end Cleanup_Protected_Object
;
3628 function Cleanup_Task
3630 Ref
: Node_Id
) return Node_Id
3632 Loc
: constant Source_Ptr
:= Sloc
(N
);
3635 -- For restricted run-time libraries (Ravenscar), tasks are
3636 -- non-terminating and they can only appear at library level, so we do
3637 -- not want finalization of task objects.
3639 if Restricted_Profile
then
3644 Make_Procedure_Call_Statement
(Loc
,
3646 New_Occurrence_Of
(RTE
(RE_Free_Task
), Loc
),
3647 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3651 ------------------------------
3652 -- Check_Visibly_Controlled --
3653 ------------------------------
3655 procedure Check_Visibly_Controlled
3656 (Prim
: Final_Primitives
;
3658 E
: in out Entity_Id
;
3659 Cref
: in out Node_Id
)
3661 Parent_Type
: Entity_Id
;
3665 if Is_Derived_Type
(Typ
)
3666 and then Comes_From_Source
(E
)
3667 and then not Present
(Overridden_Operation
(E
))
3669 -- We know that the explicit operation on the type does not override
3670 -- the inherited operation of the parent, and that the derivation
3671 -- is from a private type that is not visibly controlled.
3673 Parent_Type
:= Etype
(Typ
);
3674 Op
:= Find_Prim_Op
(Parent_Type
, Name_Of
(Prim
));
3676 if Present
(Op
) then
3679 -- Wrap the object to be initialized into the proper
3680 -- unchecked conversion, to be compatible with the operation
3683 if Nkind
(Cref
) = N_Unchecked_Type_Conversion
then
3684 Cref
:= Unchecked_Convert_To
(Parent_Type
, Expression
(Cref
));
3686 Cref
:= Unchecked_Convert_To
(Parent_Type
, Cref
);
3690 end Check_Visibly_Controlled
;
3692 -------------------------------
3693 -- CW_Or_Has_Controlled_Part --
3694 -------------------------------
3696 function CW_Or_Has_Controlled_Part
(T
: Entity_Id
) return Boolean is
3698 return Is_Class_Wide_Type
(T
) or else Needs_Finalization
(T
);
3699 end CW_Or_Has_Controlled_Part
;
3705 function Convert_View
3708 Ind
: Pos
:= 1) return Node_Id
3710 Fent
: Entity_Id
:= First_Entity
(Proc
);
3715 for J
in 2 .. Ind
loop
3719 Ftyp
:= Etype
(Fent
);
3721 if Nkind_In
(Arg
, N_Type_Conversion
, N_Unchecked_Type_Conversion
) then
3722 Atyp
:= Entity
(Subtype_Mark
(Arg
));
3724 Atyp
:= Etype
(Arg
);
3727 if Is_Abstract_Subprogram
(Proc
) and then Is_Tagged_Type
(Ftyp
) then
3728 return Unchecked_Convert_To
(Class_Wide_Type
(Ftyp
), Arg
);
3731 and then Present
(Atyp
)
3732 and then (Is_Private_Type
(Ftyp
) or else Is_Private_Type
(Atyp
))
3733 and then Base_Type
(Underlying_Type
(Atyp
)) =
3734 Base_Type
(Underlying_Type
(Ftyp
))
3736 return Unchecked_Convert_To
(Ftyp
, Arg
);
3738 -- If the argument is already a conversion, as generated by
3739 -- Make_Init_Call, set the target type to the type of the formal
3740 -- directly, to avoid spurious typing problems.
3742 elsif Nkind_In
(Arg
, N_Unchecked_Type_Conversion
, N_Type_Conversion
)
3743 and then not Is_Class_Wide_Type
(Atyp
)
3745 Set_Subtype_Mark
(Arg
, New_Occurrence_Of
(Ftyp
, Sloc
(Arg
)));
3746 Set_Etype
(Arg
, Ftyp
);
3749 -- Otherwise, introduce a conversion when the designated object
3750 -- has a type derived from the formal of the controlled routine.
3752 elsif Is_Private_Type
(Ftyp
)
3753 and then Present
(Atyp
)
3754 and then Is_Derived_Type
(Underlying_Type
(Base_Type
(Atyp
)))
3756 return Unchecked_Convert_To
(Ftyp
, Arg
);
3763 ------------------------
3764 -- Enclosing_Function --
3765 ------------------------
3767 function Enclosing_Function
(E
: Entity_Id
) return Entity_Id
is
3768 Func_Id
: Entity_Id
;
3772 while Present
(Func_Id
) and then Func_Id
/= Standard_Standard
loop
3773 if Ekind
(Func_Id
) = E_Function
then
3777 Func_Id
:= Scope
(Func_Id
);
3781 end Enclosing_Function
;
3783 -------------------------------
3784 -- Establish_Transient_Scope --
3785 -------------------------------
3787 -- This procedure is called each time a transient block has to be inserted
3788 -- that is to say for each call to a function with unconstrained or tagged
3789 -- result. It creates a new scope on the stack scope in order to enclose
3790 -- all transient variables generated.
3792 procedure Establish_Transient_Scope
(N
: Node_Id
; Sec_Stack
: Boolean) is
3793 Loc
: constant Source_Ptr
:= Sloc
(N
);
3794 Iter_Loop
: Entity_Id
;
3795 Wrap_Node
: Node_Id
;
3798 -- Do not create a transient scope if we are already inside one
3800 for S
in reverse Scope_Stack
.First
.. Scope_Stack
.Last
loop
3801 if Scope_Stack
.Table
(S
).Is_Transient
then
3803 Set_Uses_Sec_Stack
(Scope_Stack
.Table
(S
).Entity
);
3808 -- If we encounter Standard there are no enclosing transient scopes
3810 elsif Scope_Stack
.Table
(S
).Entity
= Standard_Standard
then
3815 Wrap_Node
:= Find_Node_To_Be_Wrapped
(N
);
3817 -- The context does not contain a node that requires a transient scope,
3820 if No
(Wrap_Node
) then
3823 -- If the node to wrap is an iteration_scheme, the expression is one of
3824 -- the bounds, and the expansion will make an explicit declaration for
3825 -- it (see Analyze_Iteration_Scheme, sem_ch5.adb), so do not apply any
3826 -- transformations here. Same for an Ada 2012 iterator specification,
3827 -- where a block is created for the expression that build the container.
3829 elsif Nkind_In
(Wrap_Node
, N_Iteration_Scheme
,
3830 N_Iterator_Specification
)
3834 -- In formal verification mode, if the node to wrap is a pragma check,
3835 -- this node and enclosed expression are not expanded, so do not apply
3836 -- any transformations here.
3838 elsif GNATprove_Mode
3839 and then Nkind
(Wrap_Node
) = N_Pragma
3840 and then Get_Pragma_Id
(Wrap_Node
) = Pragma_Check
3844 -- Create a block entity to act as a transient scope. Note that when the
3845 -- node to be wrapped is an expression or a statement, a real physical
3846 -- block is constructed (see routines Wrap_Transient_Expression and
3847 -- Wrap_Transient_Statement) and inserted into the tree.
3850 Push_Scope
(New_Internal_Entity
(E_Block
, Current_Scope
, Loc
, 'B'));
3851 Set_Scope_Is_Transient
;
3853 -- The transient scope must also take care of the secondary stack
3857 Set_Uses_Sec_Stack
(Current_Scope
);
3858 Check_Restriction
(No_Secondary_Stack
, N
);
3860 -- The expansion of iterator loops generates references to objects
3861 -- in order to extract elements from a container:
3863 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
3864 -- Obj : <object type> renames Ref.all.Element.all;
3866 -- These references are controlled and returned on the secondary
3867 -- stack. A new reference is created at each iteration of the loop
3868 -- and as a result it must be finalized and the space occupied by
3869 -- it on the secondary stack reclaimed at the end of the current
3872 -- When the context that requires a transient scope is a call to
3873 -- routine Reference, the node to be wrapped is the source object:
3875 -- for Obj of Container loop
3877 -- Routine Wrap_Transient_Declaration however does not generate a
3878 -- physical block as wrapping a declaration will kill it too ealy.
3879 -- To handle this peculiar case, mark the related iterator loop as
3880 -- requiring the secondary stack. This signals the finalization
3881 -- machinery to manage the secondary stack (see routine
3882 -- Process_Statements_For_Controlled_Objects).
3884 Iter_Loop
:= Find_Enclosing_Iterator_Loop
(Current_Scope
);
3886 if Present
(Iter_Loop
) then
3887 Set_Uses_Sec_Stack
(Iter_Loop
);
3891 Set_Etype
(Current_Scope
, Standard_Void_Type
);
3892 Set_Node_To_Be_Wrapped
(Wrap_Node
);
3894 if Debug_Flag_W
then
3895 Write_Str
(" <Transient>");
3899 end Establish_Transient_Scope
;
3901 ----------------------------
3902 -- Expand_Cleanup_Actions --
3903 ----------------------------
3905 procedure Expand_Cleanup_Actions
(N
: Node_Id
) is
3906 Scop
: constant Entity_Id
:= Current_Scope
;
3908 Is_Asynchronous_Call
: constant Boolean :=
3909 Nkind
(N
) = N_Block_Statement
3910 and then Is_Asynchronous_Call_Block
(N
);
3911 Is_Master
: constant Boolean :=
3912 Nkind
(N
) /= N_Entry_Body
3913 and then Is_Task_Master
(N
);
3914 Is_Protected_Body
: constant Boolean :=
3915 Nkind
(N
) = N_Subprogram_Body
3916 and then Is_Protected_Subprogram_Body
(N
);
3917 Is_Task_Allocation
: constant Boolean :=
3918 Nkind
(N
) = N_Block_Statement
3919 and then Is_Task_Allocation_Block
(N
);
3920 Is_Task_Body
: constant Boolean :=
3921 Nkind
(Original_Node
(N
)) = N_Task_Body
;
3922 Needs_Sec_Stack_Mark
: constant Boolean :=
3923 Uses_Sec_Stack
(Scop
)
3925 not Sec_Stack_Needed_For_Return
(Scop
)
3926 and then VM_Target
= No_VM
;
3927 Needs_Custom_Cleanup
: constant Boolean :=
3928 Nkind
(N
) = N_Block_Statement
3929 and then Present
(Cleanup_Actions
(N
));
3931 Actions_Required
: constant Boolean :=
3932 Requires_Cleanup_Actions
(N
, True)
3933 or else Is_Asynchronous_Call
3935 or else Is_Protected_Body
3936 or else Is_Task_Allocation
3937 or else Is_Task_Body
3938 or else Needs_Sec_Stack_Mark
3939 or else Needs_Custom_Cleanup
;
3941 HSS
: Node_Id
:= Handled_Statement_Sequence
(N
);
3945 procedure Wrap_HSS_In_Block
;
3946 -- Move HSS inside a new block along with the original exception
3947 -- handlers. Make the newly generated block the sole statement of HSS.
3949 -----------------------
3950 -- Wrap_HSS_In_Block --
3951 -----------------------
3953 procedure Wrap_HSS_In_Block
is
3958 -- Preserve end label to provide proper cross-reference information
3960 End_Lab
:= End_Label
(HSS
);
3962 Make_Block_Statement
(Loc
, Handled_Statement_Sequence
=> HSS
);
3964 -- Signal the finalization machinery that this particular block
3965 -- contains the original context.
3967 Set_Is_Finalization_Wrapper
(Block
);
3969 Set_Handled_Statement_Sequence
(N
,
3970 Make_Handled_Sequence_Of_Statements
(Loc
, New_List
(Block
)));
3971 HSS
:= Handled_Statement_Sequence
(N
);
3973 Set_First_Real_Statement
(HSS
, Block
);
3974 Set_End_Label
(HSS
, End_Lab
);
3976 -- Comment needed here, see RH for 1.306 ???
3978 if Nkind
(N
) = N_Subprogram_Body
then
3979 Set_Has_Nested_Block_With_Handler
(Scop
);
3981 end Wrap_HSS_In_Block
;
3983 -- Start of processing for Expand_Cleanup_Actions
3986 -- The current construct does not need any form of servicing
3988 if not Actions_Required
then
3991 -- If the current node is a rewritten task body and the descriptors have
3992 -- not been delayed (due to some nested instantiations), do not generate
3993 -- redundant cleanup actions.
3996 and then Nkind
(N
) = N_Subprogram_Body
3997 and then not Delay_Subprogram_Descriptors
(Corresponding_Spec
(N
))
4002 if Needs_Custom_Cleanup
then
4003 Cln
:= Cleanup_Actions
(N
);
4009 Decls
: List_Id
:= Declarations
(N
);
4011 Mark
: Entity_Id
:= Empty
;
4012 New_Decls
: List_Id
;
4016 -- If we are generating expanded code for debugging purposes, use the
4017 -- Sloc of the point of insertion for the cleanup code. The Sloc will
4018 -- be updated subsequently to reference the proper line in .dg files.
4019 -- If we are not debugging generated code, use No_Location instead,
4020 -- so that no debug information is generated for the cleanup code.
4021 -- This makes the behavior of the NEXT command in GDB monotonic, and
4022 -- makes the placement of breakpoints more accurate.
4024 if Debug_Generated_Code
then
4030 -- Set polling off. The finalization and cleanup code is executed
4031 -- with aborts deferred.
4033 Old_Poll
:= Polling_Required
;
4034 Polling_Required
:= False;
4036 -- A task activation call has already been built for a task
4037 -- allocation block.
4039 if not Is_Task_Allocation
then
4040 Build_Task_Activation_Call
(N
);
4044 Establish_Task_Master
(N
);
4047 New_Decls
:= New_List
;
4049 -- If secondary stack is in use, generate:
4051 -- Mnn : constant Mark_Id := SS_Mark;
4053 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
4054 -- secondary stack is never used on a VM.
4056 if Needs_Sec_Stack_Mark
then
4057 Mark
:= Make_Temporary
(Loc
, 'M');
4059 Append_To
(New_Decls
, Build_SS_Mark_Call
(Loc
, Mark
));
4060 Set_Uses_Sec_Stack
(Scop
, False);
4063 -- If exception handlers are present, wrap the sequence of statements
4064 -- in a block since it is not possible to have exception handlers and
4065 -- an At_End handler in the same construct.
4067 if Present
(Exception_Handlers
(HSS
)) then
4070 -- Ensure that the First_Real_Statement field is set
4072 elsif No
(First_Real_Statement
(HSS
)) then
4073 Set_First_Real_Statement
(HSS
, First
(Statements
(HSS
)));
4076 -- Do not move the Activation_Chain declaration in the context of
4077 -- task allocation blocks. Task allocation blocks use _chain in their
4078 -- cleanup handlers and gigi complains if it is declared in the
4079 -- sequence of statements of the scope that declares the handler.
4081 if Is_Task_Allocation
then
4083 Chain
: constant Entity_Id
:= Activation_Chain_Entity
(N
);
4087 Decl
:= First
(Decls
);
4088 while Nkind
(Decl
) /= N_Object_Declaration
4089 or else Defining_Identifier
(Decl
) /= Chain
4093 -- A task allocation block should always include a _chain
4096 pragma Assert
(Present
(Decl
));
4100 Prepend_To
(New_Decls
, Decl
);
4104 -- Ensure the presence of a declaration list in order to successfully
4105 -- append all original statements to it.
4108 Set_Declarations
(N
, New_List
);
4109 Decls
:= Declarations
(N
);
4112 -- Move the declarations into the sequence of statements in order to
4113 -- have them protected by the At_End handler. It may seem weird to
4114 -- put declarations in the sequence of statement but in fact nothing
4115 -- forbids that at the tree level.
4117 Append_List_To
(Decls
, Statements
(HSS
));
4118 Set_Statements
(HSS
, Decls
);
4120 -- Reset the Sloc of the handled statement sequence to properly
4121 -- reflect the new initial "statement" in the sequence.
4123 Set_Sloc
(HSS
, Sloc
(First
(Decls
)));
4125 -- The declarations of finalizer spec and auxiliary variables replace
4126 -- the old declarations that have been moved inward.
4128 Set_Declarations
(N
, New_Decls
);
4129 Analyze_Declarations
(New_Decls
);
4131 -- Generate finalization calls for all controlled objects appearing
4132 -- in the statements of N. Add context specific cleanup for various
4137 Clean_Stmts
=> Build_Cleanup_Statements
(N
, Cln
),
4139 Top_Decls
=> New_Decls
,
4140 Defer_Abort
=> Nkind
(Original_Node
(N
)) = N_Task_Body
4144 if Present
(Fin_Id
) then
4145 Build_Finalizer_Call
(N
, Fin_Id
);
4148 -- Restore saved polling mode
4150 Polling_Required
:= Old_Poll
;
4152 end Expand_Cleanup_Actions
;
4154 ---------------------------
4155 -- Expand_N_Package_Body --
4156 ---------------------------
4158 -- Add call to Activate_Tasks if body is an activator (actual processing
4159 -- is in chapter 9).
4161 -- Generate subprogram descriptor for elaboration routine
4163 -- Encode entity names in package body
4165 procedure Expand_N_Package_Body
(N
: Node_Id
) is
4166 Spec_Ent
: constant Entity_Id
:= Corresponding_Spec
(N
);
4170 -- This is done only for non-generic packages
4172 if Ekind
(Spec_Ent
) = E_Package
then
4173 Push_Scope
(Corresponding_Spec
(N
));
4175 -- Build dispatch tables of library level tagged types
4177 if Tagged_Type_Expansion
4178 and then Is_Library_Level_Entity
(Spec_Ent
)
4180 Build_Static_Dispatch_Tables
(N
);
4183 Build_Task_Activation_Call
(N
);
4185 -- When the package is subject to pragma Initial_Condition, the
4186 -- assertion expression must be verified at the end of the body
4189 if Present
(Get_Pragma
(Spec_Ent
, Pragma_Initial_Condition
)) then
4190 Expand_Pragma_Initial_Condition
(N
);
4196 Set_Elaboration_Flag
(N
, Corresponding_Spec
(N
));
4197 Set_In_Package_Body
(Spec_Ent
, False);
4199 -- Set to encode entity names in package body before gigi is called
4201 Qualify_Entity_Names
(N
);
4203 if Ekind
(Spec_Ent
) /= E_Generic_Package
then
4206 Clean_Stmts
=> No_List
,
4208 Top_Decls
=> No_List
,
4209 Defer_Abort
=> False,
4212 if Present
(Fin_Id
) then
4214 Body_Ent
: Node_Id
:= Defining_Unit_Name
(N
);
4217 if Nkind
(Body_Ent
) = N_Defining_Program_Unit_Name
then
4218 Body_Ent
:= Defining_Identifier
(Body_Ent
);
4221 Set_Finalizer
(Body_Ent
, Fin_Id
);
4225 end Expand_N_Package_Body
;
4227 ----------------------------------
4228 -- Expand_N_Package_Declaration --
4229 ----------------------------------
4231 -- Add call to Activate_Tasks if there are tasks declared and the package
4232 -- has no body. Note that in Ada 83 this may result in premature activation
4233 -- of some tasks, given that we cannot tell whether a body will eventually
4236 procedure Expand_N_Package_Declaration
(N
: Node_Id
) is
4237 Id
: constant Entity_Id
:= Defining_Entity
(N
);
4238 Spec
: constant Node_Id
:= Specification
(N
);
4242 No_Body
: Boolean := False;
4243 -- True in the case of a package declaration that is a compilation
4244 -- unit and for which no associated body will be compiled in this
4248 -- Case of a package declaration other than a compilation unit
4250 if Nkind
(Parent
(N
)) /= N_Compilation_Unit
then
4253 -- Case of a compilation unit that does not require a body
4255 elsif not Body_Required
(Parent
(N
))
4256 and then not Unit_Requires_Body
(Id
)
4260 -- Special case of generating calling stubs for a remote call interface
4261 -- package: even though the package declaration requires one, the body
4262 -- won't be processed in this compilation (so any stubs for RACWs
4263 -- declared in the package must be generated here, along with the spec).
4265 elsif Parent
(N
) = Cunit
(Main_Unit
)
4266 and then Is_Remote_Call_Interface
(Id
)
4267 and then Distribution_Stub_Mode
= Generate_Caller_Stub_Body
4272 -- For a nested instance, delay processing until freeze point
4274 if Has_Delayed_Freeze
(Id
)
4275 and then Nkind
(Parent
(N
)) /= N_Compilation_Unit
4280 -- For a package declaration that implies no associated body, generate
4281 -- task activation call and RACW supporting bodies now (since we won't
4282 -- have a specific separate compilation unit for that).
4287 -- Generate RACW subprogram bodies
4289 if Has_RACW
(Id
) then
4290 Decls
:= Private_Declarations
(Spec
);
4293 Decls
:= Visible_Declarations
(Spec
);
4298 Set_Visible_Declarations
(Spec
, Decls
);
4301 Append_RACW_Bodies
(Decls
, Id
);
4302 Analyze_List
(Decls
);
4305 -- Generate task activation call as last step of elaboration
4307 if Present
(Activation_Chain_Entity
(N
)) then
4308 Build_Task_Activation_Call
(N
);
4311 -- When the package is subject to pragma Initial_Condition and lacks
4312 -- a body, the assertion expression must be verified at the end of
4313 -- the visible declarations. Otherwise the check is performed at the
4314 -- end of the body statements (see Expand_N_Package_Body).
4316 if Present
(Get_Pragma
(Id
, Pragma_Initial_Condition
)) then
4317 Expand_Pragma_Initial_Condition
(N
);
4323 -- Build dispatch tables of library level tagged types
4325 if Tagged_Type_Expansion
4326 and then (Is_Compilation_Unit
(Id
)
4327 or else (Is_Generic_Instance
(Id
)
4328 and then Is_Library_Level_Entity
(Id
)))
4330 Build_Static_Dispatch_Tables
(N
);
4333 -- Note: it is not necessary to worry about generating a subprogram
4334 -- descriptor, since the only way to get exception handlers into a
4335 -- package spec is to include instantiations, and that would cause
4336 -- generation of subprogram descriptors to be delayed in any case.
4338 -- Set to encode entity names in package spec before gigi is called
4340 Qualify_Entity_Names
(N
);
4342 if Ekind
(Id
) /= E_Generic_Package
then
4345 Clean_Stmts
=> No_List
,
4347 Top_Decls
=> No_List
,
4348 Defer_Abort
=> False,
4351 Set_Finalizer
(Id
, Fin_Id
);
4353 end Expand_N_Package_Declaration
;
4355 -----------------------------
4356 -- Find_Node_To_Be_Wrapped --
4357 -----------------------------
4359 function Find_Node_To_Be_Wrapped
(N
: Node_Id
) return Node_Id
is
4361 The_Parent
: Node_Id
;
4367 case Nkind
(The_Parent
) is
4369 -- Simple statement can be wrapped
4374 -- Usually assignments are good candidate for wrapping except
4375 -- when they have been generated as part of a controlled aggregate
4376 -- where the wrapping should take place more globally. Note that
4377 -- No_Ctrl_Actions may be set also for non-controlled assignements
4378 -- in order to disable the use of dispatching _assign, so we need
4379 -- to test explicitly for a controlled type here.
4381 when N_Assignment_Statement
=>
4382 if No_Ctrl_Actions
(The_Parent
)
4383 and then Needs_Finalization
(Etype
(Name
(The_Parent
)))
4390 -- An entry call statement is a special case if it occurs in the
4391 -- context of a Timed_Entry_Call. In this case we wrap the entire
4392 -- timed entry call.
4394 when N_Entry_Call_Statement |
4395 N_Procedure_Call_Statement
=>
4396 if Nkind
(Parent
(The_Parent
)) = N_Entry_Call_Alternative
4397 and then Nkind_In
(Parent
(Parent
(The_Parent
)),
4399 N_Conditional_Entry_Call
)
4401 return Parent
(Parent
(The_Parent
));
4406 -- Object declarations are also a boundary for the transient scope
4407 -- even if they are not really wrapped. For further details, see
4408 -- Wrap_Transient_Declaration.
4410 when N_Object_Declaration |
4411 N_Object_Renaming_Declaration |
4412 N_Subtype_Declaration
=>
4415 -- The expression itself is to be wrapped if its parent is a
4416 -- compound statement or any other statement where the expression
4417 -- is known to be scalar.
4419 when N_Accept_Alternative |
4420 N_Attribute_Definition_Clause |
4423 N_Delay_Alternative |
4424 N_Delay_Until_Statement |
4425 N_Delay_Relative_Statement |
4426 N_Discriminant_Association |
4428 N_Entry_Body_Formal_Part |
4431 N_Iteration_Scheme |
4432 N_Terminate_Alternative
=>
4433 pragma Assert
(Present
(P
));
4436 when N_Attribute_Reference
=>
4438 if Is_Procedure_Attribute_Name
4439 (Attribute_Name
(The_Parent
))
4444 -- A raise statement can be wrapped. This will arise when the
4445 -- expression in a raise_with_expression uses the secondary
4446 -- stack, for example.
4448 when N_Raise_Statement
=>
4451 -- If the expression is within the iteration scheme of a loop,
4452 -- we must create a declaration for it, followed by an assignment
4453 -- in order to have a usable statement to wrap.
4455 when N_Loop_Parameter_Specification
=>
4456 return Parent
(The_Parent
);
4458 -- The following nodes contains "dummy calls" which don't need to
4461 when N_Parameter_Specification |
4462 N_Discriminant_Specification |
4463 N_Component_Declaration
=>
4466 -- The return statement is not to be wrapped when the function
4467 -- itself needs wrapping at the outer-level
4469 when N_Simple_Return_Statement
=>
4471 Applies_To
: constant Entity_Id
:=
4473 (Return_Statement_Entity
(The_Parent
));
4474 Return_Type
: constant Entity_Id
:= Etype
(Applies_To
);
4476 if Requires_Transient_Scope
(Return_Type
) then
4483 -- If we leave a scope without having been able to find a node to
4484 -- wrap, something is going wrong but this can happen in error
4485 -- situation that are not detected yet (such as a dynamic string
4486 -- in a pragma export)
4488 when N_Subprogram_Body |
4489 N_Package_Declaration |
4491 N_Block_Statement
=>
4494 -- Otherwise continue the search
4501 The_Parent
:= Parent
(P
);
4503 end Find_Node_To_Be_Wrapped
;
4505 ----------------------------------
4506 -- Has_New_Controlled_Component --
4507 ----------------------------------
4509 function Has_New_Controlled_Component
(E
: Entity_Id
) return Boolean is
4513 if not Is_Tagged_Type
(E
) then
4514 return Has_Controlled_Component
(E
);
4515 elsif not Is_Derived_Type
(E
) then
4516 return Has_Controlled_Component
(E
);
4519 Comp
:= First_Component
(E
);
4520 while Present
(Comp
) loop
4521 if Chars
(Comp
) = Name_uParent
then
4524 elsif Scope
(Original_Record_Component
(Comp
)) = E
4525 and then Needs_Finalization
(Etype
(Comp
))
4530 Next_Component
(Comp
);
4534 end Has_New_Controlled_Component
;
4536 ---------------------------------
4537 -- Has_Simple_Protected_Object --
4538 ---------------------------------
4540 function Has_Simple_Protected_Object
(T
: Entity_Id
) return Boolean is
4542 if Has_Task
(T
) then
4545 elsif Is_Simple_Protected_Type
(T
) then
4548 elsif Is_Array_Type
(T
) then
4549 return Has_Simple_Protected_Object
(Component_Type
(T
));
4551 elsif Is_Record_Type
(T
) then
4556 Comp
:= First_Component
(T
);
4557 while Present
(Comp
) loop
4558 if Has_Simple_Protected_Object
(Etype
(Comp
)) then
4562 Next_Component
(Comp
);
4571 end Has_Simple_Protected_Object
;
4573 ------------------------------------
4574 -- Insert_Actions_In_Scope_Around --
4575 ------------------------------------
4577 procedure Insert_Actions_In_Scope_Around
4580 Manage_SS
: Boolean)
4582 Act_Before
: constant List_Id
:=
4583 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Before
);
4584 Act_After
: constant List_Id
:=
4585 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(After
);
4586 Act_Cleanup
: constant List_Id
:=
4587 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Cleanup
);
4588 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
4589 -- Last), but this was incorrect as Process_Transient_Object may
4590 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
4592 procedure Process_Transient_Objects
4593 (First_Object
: Node_Id
;
4594 Last_Object
: Node_Id
;
4595 Related_Node
: Node_Id
);
4596 -- First_Object and Last_Object define a list which contains potential
4597 -- controlled transient objects. Finalization flags are inserted before
4598 -- First_Object and finalization calls are inserted after Last_Object.
4599 -- Related_Node is the node for which transient objects have been
4602 -------------------------------
4603 -- Process_Transient_Objects --
4604 -------------------------------
4606 procedure Process_Transient_Objects
4607 (First_Object
: Node_Id
;
4608 Last_Object
: Node_Id
;
4609 Related_Node
: Node_Id
)
4611 Must_Hook
: Boolean := False;
4612 -- Flag denoting whether the context requires transient variable
4613 -- export to the outer finalizer.
4615 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
;
4616 -- Determine whether an arbitrary node denotes a subprogram call
4618 procedure Detect_Subprogram_Call
is
4619 new Traverse_Proc
(Is_Subprogram_Call
);
4621 ------------------------
4622 -- Is_Subprogram_Call --
4623 ------------------------
4625 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
is
4627 -- Complex constructs are factored out by the expander and their
4628 -- occurrences are replaced with references to temporaries or
4629 -- object renamings. Due to this expansion activity, inspect the
4630 -- original tree to detect subprogram calls.
4632 if Nkind_In
(N
, N_Identifier
,
4633 N_Object_Renaming_Declaration
)
4634 and then Original_Node
(N
) /= N
4636 Detect_Subprogram_Call
(Original_Node
(N
));
4638 -- The original construct contains a subprogram call, there is
4639 -- no point in continuing the tree traversal.
4647 -- The original construct contains a subprogram call, there is no
4648 -- point in continuing the tree traversal.
4650 elsif Nkind
(N
) = N_Object_Declaration
4651 and then Present
(Expression
(N
))
4652 and then Nkind
(Original_Node
(Expression
(N
))) = N_Function_Call
4657 -- A regular procedure or function call
4659 elsif Nkind
(N
) in N_Subprogram_Call
then
4668 end Is_Subprogram_Call
;
4672 Built
: Boolean := False;
4673 Desig_Typ
: Entity_Id
;
4675 Fin_Block
: Node_Id
;
4676 Fin_Data
: Finalization_Exception_Data
;
4677 Fin_Decls
: List_Id
;
4678 Fin_Insrt
: Node_Id
;
4679 Last_Fin
: Node_Id
:= Empty
;
4683 Obj_Typ
: Entity_Id
;
4684 Prev_Fin
: Node_Id
:= Empty
;
4688 Temp_Id
: Entity_Id
;
4691 -- Start of processing for Process_Transient_Objects
4694 -- Recognize a scenario where the transient context is an object
4695 -- declaration initialized by a build-in-place function call:
4697 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
4699 -- The rough expansion of the above is:
4701 -- Temp : ... := Ctrl_Func_Call;
4703 -- Res : ... := BIP_Func_Call (..., Obj, ...);
4705 -- The finalization of any controlled transient must happen after
4706 -- the build-in-place function call is executed.
4708 if Nkind
(N
) = N_Object_Declaration
4709 and then Present
(BIP_Initialization_Call
(Defining_Identifier
(N
)))
4712 Fin_Insrt
:= BIP_Initialization_Call
(Defining_Identifier
(N
));
4714 -- Search the context for at least one subprogram call. If found, the
4715 -- machinery exports all transient objects to the enclosing finalizer
4716 -- due to the possibility of abnormal call termination.
4719 Detect_Subprogram_Call
(N
);
4720 Fin_Insrt
:= Last_Object
;
4723 -- Examine all objects in the list First_Object .. Last_Object
4725 Stmt
:= First_Object
;
4726 while Present
(Stmt
) loop
4727 if Nkind
(Stmt
) = N_Object_Declaration
4728 and then Analyzed
(Stmt
)
4729 and then Is_Finalizable_Transient
(Stmt
, N
)
4731 -- Do not process the node to be wrapped since it will be
4732 -- handled by the enclosing finalizer.
4734 and then Stmt
/= Related_Node
4737 Obj_Id
:= Defining_Identifier
(Stmt
);
4738 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
4739 Desig_Typ
:= Obj_Typ
;
4741 Set_Is_Processed_Transient
(Obj_Id
);
4743 -- Handle access types
4745 if Is_Access_Type
(Desig_Typ
) then
4746 Desig_Typ
:= Available_View
(Designated_Type
(Desig_Typ
));
4749 -- Create the necessary entities and declarations the first
4754 Fin_Decls
:= New_List
;
4756 Build_Object_Declarations
(Fin_Data
, Fin_Decls
, Loc
);
4759 -- Transient variables associated with subprogram calls need
4760 -- extra processing. These variables are usually created right
4761 -- before the call and finalized immediately after the call.
4762 -- If an exception occurs during the call, the clean up code
4763 -- is skipped due to the sudden change in control and the
4764 -- transient is never finalized.
4766 -- To handle this case, such variables are "exported" to the
4767 -- enclosing sequence of statements where their corresponding
4768 -- "hooks" are picked up by the finalization machinery.
4772 -- Step 1: Create an access type which provides a reference
4773 -- to the transient object. Generate:
4775 -- Ann : access [all] <Desig_Typ>;
4777 Ptr_Id
:= Make_Temporary
(Loc
, 'A');
4779 Insert_Action
(Stmt
,
4780 Make_Full_Type_Declaration
(Loc
,
4781 Defining_Identifier
=> Ptr_Id
,
4783 Make_Access_To_Object_Definition
(Loc
,
4785 Ekind
(Obj_Typ
) = E_General_Access_Type
,
4786 Subtype_Indication
=>
4787 New_Occurrence_Of
(Desig_Typ
, Loc
))));
4789 -- Step 2: Create a temporary which acts as a hook to the
4790 -- transient object. Generate:
4792 -- Temp : Ptr_Id := null;
4794 Temp_Id
:= Make_Temporary
(Loc
, 'T');
4796 Insert_Action
(Stmt
,
4797 Make_Object_Declaration
(Loc
,
4798 Defining_Identifier
=> Temp_Id
,
4799 Object_Definition
=>
4800 New_Occurrence_Of
(Ptr_Id
, Loc
)));
4802 -- Mark the temporary as a transient hook. This signals the
4803 -- machinery in Build_Finalizer to recognize this special
4806 Set_Status_Flag_Or_Transient_Decl
(Temp_Id
, Stmt
);
4808 -- Step 3: Hook the transient object to the temporary
4810 if Is_Access_Type
(Obj_Typ
) then
4812 Convert_To
(Ptr_Id
, New_Occurrence_Of
(Obj_Id
, Loc
));
4815 Make_Attribute_Reference
(Loc
,
4816 Prefix
=> New_Occurrence_Of
(Obj_Id
, Loc
),
4817 Attribute_Name
=> Name_Unrestricted_Access
);
4821 -- Temp := Ptr_Id (Obj_Id);
4823 -- Temp := Obj_Id'Unrestricted_Access;
4825 -- When the transient object is initialized by an aggregate,
4826 -- the hook must capture the object after the last component
4827 -- assignment takes place. Only then is the object fully
4830 if Ekind
(Obj_Id
) = E_Variable
4831 and then Present
(Last_Aggregate_Assignment
(Obj_Id
))
4833 Temp_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
4835 -- Otherwise the hook seizes the related object immediately
4841 Insert_After_And_Analyze
(Temp_Ins
,
4842 Make_Assignment_Statement
(Loc
,
4843 Name
=> New_Occurrence_Of
(Temp_Id
, Loc
),
4844 Expression
=> Expr
));
4849 -- The transient object is about to be finalized by the clean
4850 -- up code following the subprogram call. In order to avoid
4851 -- double finalization, clear the hook.
4858 Make_Assignment_Statement
(Loc
,
4859 Name
=> New_Occurrence_Of
(Temp_Id
, Loc
),
4860 Expression
=> Make_Null
(Loc
)));
4864 -- [Deep_]Finalize (Obj_Ref);
4866 -- Set type of dereference, so that proper conversion are
4867 -- generated when operation is inherited.
4869 Obj_Ref
:= New_Occurrence_Of
(Obj_Id
, Loc
);
4871 if Is_Access_Type
(Obj_Typ
) then
4872 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
4873 Set_Etype
(Obj_Ref
, Directly_Designated_Type
(Obj_Typ
));
4877 Make_Final_Call
(Obj_Ref
=> Obj_Ref
, Typ
=> Desig_Typ
));
4882 -- [Deep_]Finalize (Obj_Ref);
4886 -- if not Raised then
4889 -- (Enn, Get_Current_Excep.all.all);
4894 Make_Block_Statement
(Loc
,
4895 Handled_Statement_Sequence
=>
4896 Make_Handled_Sequence_Of_Statements
(Loc
,
4897 Statements
=> Stmts
,
4898 Exception_Handlers
=> New_List
(
4899 Build_Exception_Handler
(Fin_Data
))));
4901 -- The single raise statement must be inserted after all the
4902 -- finalization blocks, and we put everything into a wrapper
4903 -- block to clearly expose the construct to the back-end.
4905 if Present
(Prev_Fin
) then
4906 Insert_Before_And_Analyze
(Prev_Fin
, Fin_Block
);
4908 Insert_After_And_Analyze
(Fin_Insrt
,
4909 Make_Block_Statement
(Loc
,
4910 Declarations
=> Fin_Decls
,
4911 Handled_Statement_Sequence
=>
4912 Make_Handled_Sequence_Of_Statements
(Loc
,
4913 Statements
=> New_List
(Fin_Block
))));
4915 Last_Fin
:= Fin_Block
;
4918 Prev_Fin
:= Fin_Block
;
4921 -- Terminate the scan after the last object has been processed to
4922 -- avoid touching unrelated code.
4924 if Stmt
= Last_Object
then
4932 if Present
(Prev_Fin
) then
4933 Insert_List_Before_And_Analyze
(Prev_Fin
, Act_Cleanup
);
4935 Insert_List_After_And_Analyze
(Fin_Insrt
, Act_Cleanup
);
4940 -- if Raised and then not Abort then
4941 -- Raise_From_Controlled_Operation (E);
4944 if Built
and then Present
(Last_Fin
) then
4945 Insert_After_And_Analyze
(Last_Fin
,
4946 Build_Raise_Statement
(Fin_Data
));
4948 end Process_Transient_Objects
;
4952 Loc
: constant Source_Ptr
:= Sloc
(N
);
4953 Node_To_Wrap
: constant Node_Id
:= Node_To_Be_Wrapped
;
4954 First_Obj
: Node_Id
;
4956 Mark_Id
: Entity_Id
;
4959 -- Start of processing for Insert_Actions_In_Scope_Around
4962 if No
(Act_Before
) and then No
(Act_After
) and then No
(Act_Cleanup
) then
4966 -- If the node to be wrapped is the trigger of an asynchronous select,
4967 -- it is not part of a statement list. The actions must be inserted
4968 -- before the select itself, which is part of some list of statements.
4969 -- Note that the triggering alternative includes the triggering
4970 -- statement and an optional statement list. If the node to be
4971 -- wrapped is part of that list, the normal insertion applies.
4973 if Nkind
(Parent
(Node_To_Wrap
)) = N_Triggering_Alternative
4974 and then not Is_List_Member
(Node_To_Wrap
)
4976 Target
:= Parent
(Parent
(Node_To_Wrap
));
4981 First_Obj
:= Target
;
4984 -- Add all actions associated with a transient scope into the main tree.
4985 -- There are several scenarios here:
4987 -- +--- Before ----+ +----- After ---+
4988 -- 1) First_Obj ....... Target ........ Last_Obj
4990 -- 2) First_Obj ....... Target
4992 -- 3) Target ........ Last_Obj
4994 -- Flag declarations are inserted before the first object
4996 if Present
(Act_Before
) then
4997 First_Obj
:= First
(Act_Before
);
4998 Insert_List_Before
(Target
, Act_Before
);
5001 -- Finalization calls are inserted after the last object
5003 if Present
(Act_After
) then
5004 Last_Obj
:= Last
(Act_After
);
5005 Insert_List_After
(Target
, Act_After
);
5008 -- Mark and release the secondary stack when the context warrants it
5011 Mark_Id
:= Make_Temporary
(Loc
, 'M');
5014 -- Mnn : constant Mark_Id := SS_Mark;
5016 Insert_Before_And_Analyze
5017 (First_Obj
, Build_SS_Mark_Call
(Loc
, Mark_Id
));
5020 -- SS_Release (Mnn);
5022 Insert_After_And_Analyze
5023 (Last_Obj
, Build_SS_Release_Call
(Loc
, Mark_Id
));
5026 -- Check for transient controlled objects associated with Target and
5027 -- generate the appropriate finalization actions for them.
5029 Process_Transient_Objects
5030 (First_Object
=> First_Obj
,
5031 Last_Object
=> Last_Obj
,
5032 Related_Node
=> Target
);
5034 -- Reset the action lists
5037 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Before
) := No_List
;
5039 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(After
) := No_List
;
5043 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Cleanup
) := No_List
;
5045 end Insert_Actions_In_Scope_Around
;
5047 ------------------------------
5048 -- Is_Simple_Protected_Type --
5049 ------------------------------
5051 function Is_Simple_Protected_Type
(T
: Entity_Id
) return Boolean is
5054 Is_Protected_Type
(T
)
5055 and then not Uses_Lock_Free
(T
)
5056 and then not Has_Entries
(T
)
5057 and then Is_RTE
(Find_Protection_Type
(T
), RE_Protection
);
5058 end Is_Simple_Protected_Type
;
5060 -----------------------
5061 -- Make_Adjust_Call --
5062 -----------------------
5064 function Make_Adjust_Call
5067 Skip_Self
: Boolean := False) return Node_Id
5069 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
5070 Adj_Id
: Entity_Id
:= Empty
;
5071 Ref
: Node_Id
:= Obj_Ref
;
5075 -- Recover the proper type which contains Deep_Adjust
5077 if Is_Class_Wide_Type
(Typ
) then
5078 Utyp
:= Root_Type
(Typ
);
5083 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
5084 Set_Assignment_OK
(Ref
);
5086 -- Deal with untagged derivation of private views
5088 if Is_Untagged_Derivation
(Typ
) then
5089 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
5090 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
5091 Set_Assignment_OK
(Ref
);
5094 -- When dealing with the completion of a private type, use the base
5097 if Utyp
/= Base_Type
(Utyp
) then
5098 pragma Assert
(Is_Private_Type
(Typ
));
5100 Utyp
:= Base_Type
(Utyp
);
5101 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
5105 if Has_Controlled_Component
(Utyp
) then
5106 if Is_Tagged_Type
(Utyp
) then
5107 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5109 Adj_Id
:= TSS
(Utyp
, TSS_Deep_Adjust
);
5113 -- Class-wide types, interfaces and types with controlled components
5115 elsif Is_Class_Wide_Type
(Typ
)
5116 or else Is_Interface
(Typ
)
5117 or else Has_Controlled_Component
(Utyp
)
5119 if Is_Tagged_Type
(Utyp
) then
5120 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5122 Adj_Id
:= TSS
(Utyp
, TSS_Deep_Adjust
);
5125 -- Derivations from [Limited_]Controlled
5127 elsif Is_Controlled
(Utyp
) then
5128 if Has_Controlled_Component
(Utyp
) then
5129 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5131 Adj_Id
:= Find_Prim_Op
(Utyp
, Name_Of
(Adjust_Case
));
5136 elsif Is_Tagged_Type
(Utyp
) then
5137 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5140 raise Program_Error
;
5143 if Present
(Adj_Id
) then
5145 -- If the object is unanalyzed, set its expected type for use in
5146 -- Convert_View in case an additional conversion is needed.
5149 and then Nkind
(Ref
) /= N_Unchecked_Type_Conversion
5151 Set_Etype
(Ref
, Typ
);
5154 -- The object reference may need another conversion depending on the
5155 -- type of the formal and that of the actual.
5157 if not Is_Class_Wide_Type
(Typ
) then
5158 Ref
:= Convert_View
(Adj_Id
, Ref
);
5164 Param
=> New_Copy_Tree
(Ref
),
5165 Skip_Self
=> Skip_Self
);
5169 end Make_Adjust_Call
;
5171 ----------------------
5172 -- Make_Attach_Call --
5173 ----------------------
5175 function Make_Attach_Call
5177 Ptr_Typ
: Entity_Id
) return Node_Id
5179 pragma Assert
(VM_Target
/= No_VM
);
5181 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
5184 Make_Procedure_Call_Statement
(Loc
,
5186 New_Occurrence_Of
(RTE
(RE_Attach
), Loc
),
5187 Parameter_Associations
=> New_List
(
5188 New_Occurrence_Of
(Finalization_Master
(Ptr_Typ
), Loc
),
5189 Unchecked_Convert_To
(RTE
(RE_Root_Controlled_Ptr
), Obj_Ref
)));
5190 end Make_Attach_Call
;
5192 ----------------------
5193 -- Make_Detach_Call --
5194 ----------------------
5196 function Make_Detach_Call
(Obj_Ref
: Node_Id
) return Node_Id
is
5197 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
5201 Make_Procedure_Call_Statement
(Loc
,
5203 New_Occurrence_Of
(RTE
(RE_Detach
), Loc
),
5204 Parameter_Associations
=> New_List
(
5205 Unchecked_Convert_To
(RTE
(RE_Root_Controlled_Ptr
), Obj_Ref
)));
5206 end Make_Detach_Call
;
5214 Proc_Id
: Entity_Id
;
5216 Skip_Self
: Boolean := False) return Node_Id
5218 Params
: constant List_Id
:= New_List
(Param
);
5221 -- Do not apply the controlled action to the object itself by signaling
5222 -- the related routine to avoid self.
5225 Append_To
(Params
, New_Occurrence_Of
(Standard_False
, Loc
));
5229 Make_Procedure_Call_Statement
(Loc
,
5230 Name
=> New_Occurrence_Of
(Proc_Id
, Loc
),
5231 Parameter_Associations
=> Params
);
5234 --------------------------
5235 -- Make_Deep_Array_Body --
5236 --------------------------
5238 function Make_Deep_Array_Body
5239 (Prim
: Final_Primitives
;
5240 Typ
: Entity_Id
) return List_Id
5242 function Build_Adjust_Or_Finalize_Statements
5243 (Typ
: Entity_Id
) return List_Id
;
5244 -- Create the statements necessary to adjust or finalize an array of
5245 -- controlled elements. Generate:
5248 -- Abort : constant Boolean := Triggered_By_Abort;
5250 -- Abort : constant Boolean := False; -- no abort
5252 -- E : Exception_Occurrence;
5253 -- Raised : Boolean := False;
5256 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
5257 -- ^-- in the finalization case
5259 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
5261 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
5265 -- if not Raised then
5267 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5274 -- if Raised and then not Abort then
5275 -- Raise_From_Controlled_Operation (E);
5279 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
;
5280 -- Create the statements necessary to initialize an array of controlled
5281 -- elements. Include a mechanism to carry out partial finalization if an
5282 -- exception occurs. Generate:
5285 -- Counter : Integer := 0;
5288 -- for J1 in V'Range (1) loop
5290 -- for JN in V'Range (N) loop
5292 -- [Deep_]Initialize (V (J1, ..., JN));
5294 -- Counter := Counter + 1;
5299 -- Abort : constant Boolean := Triggered_By_Abort;
5301 -- Abort : constant Boolean := False; -- no abort
5302 -- E : Exception_Occurence;
5303 -- Raised : Boolean := False;
5310 -- V'Length (N) - Counter;
5312 -- for F1 in reverse V'Range (1) loop
5314 -- for FN in reverse V'Range (N) loop
5315 -- if Counter > 0 then
5316 -- Counter := Counter - 1;
5319 -- [Deep_]Finalize (V (F1, ..., FN));
5323 -- if not Raised then
5325 -- Save_Occurrence (E,
5326 -- Get_Current_Excep.all.all);
5335 -- if Raised and then not Abort then
5336 -- Raise_From_Controlled_Operation (E);
5345 function New_References_To
5347 Loc
: Source_Ptr
) return List_Id
;
5348 -- Given a list of defining identifiers, return a list of references to
5349 -- the original identifiers, in the same order as they appear.
5351 -----------------------------------------
5352 -- Build_Adjust_Or_Finalize_Statements --
5353 -----------------------------------------
5355 function Build_Adjust_Or_Finalize_Statements
5356 (Typ
: Entity_Id
) return List_Id
5358 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5359 Index_List
: constant List_Id
:= New_List
;
5360 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5361 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5362 Finalizer_Decls
: List_Id
:= No_List
;
5363 Finalizer_Data
: Finalization_Exception_Data
;
5366 Core_Loop
: Node_Id
;
5369 Loop_Id
: Entity_Id
;
5372 Exceptions_OK
: constant Boolean :=
5373 not Restriction_Active
(No_Exception_Propagation
);
5375 procedure Build_Indexes
;
5376 -- Generate the indexes used in the dimension loops
5382 procedure Build_Indexes
is
5384 -- Generate the following identifiers:
5385 -- Jnn - for initialization
5387 for Dim
in 1 .. Num_Dims
loop
5388 Append_To
(Index_List
,
5389 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5393 -- Start of processing for Build_Adjust_Or_Finalize_Statements
5396 Finalizer_Decls
:= New_List
;
5399 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
5402 Make_Indexed_Component
(Loc
,
5403 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5404 Expressions
=> New_References_To
(Index_List
, Loc
));
5405 Set_Etype
(Comp_Ref
, Comp_Typ
);
5408 -- [Deep_]Adjust (V (J1, ..., JN))
5410 if Prim
= Adjust_Case
then
5411 Call
:= Make_Adjust_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5414 -- [Deep_]Finalize (V (J1, ..., JN))
5416 else pragma Assert
(Prim
= Finalize_Case
);
5417 Call
:= Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5420 -- Generate the block which houses the adjust or finalize call:
5422 -- <adjust or finalize call>; -- No_Exception_Propagation
5424 -- begin -- Exception handlers allowed
5425 -- <adjust or finalize call>
5429 -- if not Raised then
5431 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5435 if Exceptions_OK
then
5437 Make_Block_Statement
(Loc
,
5438 Handled_Statement_Sequence
=>
5439 Make_Handled_Sequence_Of_Statements
(Loc
,
5440 Statements
=> New_List
(Call
),
5441 Exception_Handlers
=> New_List
(
5442 Build_Exception_Handler
(Finalizer_Data
))));
5447 -- Generate the dimension loops starting from the innermost one
5449 -- for Jnn in [reverse] V'Range (Dim) loop
5453 J
:= Last
(Index_List
);
5455 while Present
(J
) and then Dim
> 0 loop
5461 Make_Loop_Statement
(Loc
,
5463 Make_Iteration_Scheme
(Loc
,
5464 Loop_Parameter_Specification
=>
5465 Make_Loop_Parameter_Specification
(Loc
,
5466 Defining_Identifier
=> Loop_Id
,
5467 Discrete_Subtype_Definition
=>
5468 Make_Attribute_Reference
(Loc
,
5469 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5470 Attribute_Name
=> Name_Range
,
5471 Expressions
=> New_List
(
5472 Make_Integer_Literal
(Loc
, Dim
))),
5474 Reverse_Present
=> Prim
= Finalize_Case
)),
5476 Statements
=> New_List
(Core_Loop
),
5477 End_Label
=> Empty
);
5482 -- Generate the block which contains the core loop, the declarations
5483 -- of the abort flag, the exception occurrence, the raised flag and
5484 -- the conditional raise:
5487 -- Abort : constant Boolean := Triggered_By_Abort;
5489 -- Abort : constant Boolean := False; -- no abort
5491 -- E : Exception_Occurrence;
5492 -- Raised : Boolean := False;
5497 -- if Raised and then not Abort then -- Expection handlers OK
5498 -- Raise_From_Controlled_Operation (E);
5502 Stmts
:= New_List
(Core_Loop
);
5504 if Exceptions_OK
then
5506 Build_Raise_Statement
(Finalizer_Data
));
5511 Make_Block_Statement
(Loc
,
5514 Handled_Statement_Sequence
=>
5515 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
5516 end Build_Adjust_Or_Finalize_Statements
;
5518 ---------------------------------
5519 -- Build_Initialize_Statements --
5520 ---------------------------------
5522 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
is
5523 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5524 Final_List
: constant List_Id
:= New_List
;
5525 Index_List
: constant List_Id
:= New_List
;
5526 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5527 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5528 Counter_Id
: Entity_Id
;
5532 Final_Block
: Node_Id
;
5533 Final_Loop
: Node_Id
;
5534 Finalizer_Data
: Finalization_Exception_Data
;
5535 Finalizer_Decls
: List_Id
:= No_List
;
5536 Init_Loop
: Node_Id
;
5541 Exceptions_OK
: constant Boolean :=
5542 not Restriction_Active
(No_Exception_Propagation
);
5544 function Build_Counter_Assignment
return Node_Id
;
5545 -- Generate the following assignment:
5546 -- Counter := V'Length (1) *
5548 -- V'Length (N) - Counter;
5550 function Build_Finalization_Call
return Node_Id
;
5551 -- Generate a deep finalization call for an array element
5553 procedure Build_Indexes
;
5554 -- Generate the initialization and finalization indexes used in the
5557 function Build_Initialization_Call
return Node_Id
;
5558 -- Generate a deep initialization call for an array element
5560 ------------------------------
5561 -- Build_Counter_Assignment --
5562 ------------------------------
5564 function Build_Counter_Assignment
return Node_Id
is
5569 -- Start from the first dimension and generate:
5574 Make_Attribute_Reference
(Loc
,
5575 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5576 Attribute_Name
=> Name_Length
,
5577 Expressions
=> New_List
(Make_Integer_Literal
(Loc
, Dim
)));
5579 -- Process the rest of the dimensions, generate:
5580 -- Expr * V'Length (N)
5583 while Dim
<= Num_Dims
loop
5585 Make_Op_Multiply
(Loc
,
5588 Make_Attribute_Reference
(Loc
,
5589 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5590 Attribute_Name
=> Name_Length
,
5591 Expressions
=> New_List
(
5592 Make_Integer_Literal
(Loc
, Dim
))));
5598 -- Counter := Expr - Counter;
5601 Make_Assignment_Statement
(Loc
,
5602 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5604 Make_Op_Subtract
(Loc
,
5606 Right_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
)));
5607 end Build_Counter_Assignment
;
5609 -----------------------------
5610 -- Build_Finalization_Call --
5611 -----------------------------
5613 function Build_Finalization_Call
return Node_Id
is
5614 Comp_Ref
: constant Node_Id
:=
5615 Make_Indexed_Component
(Loc
,
5616 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5617 Expressions
=> New_References_To
(Final_List
, Loc
));
5620 Set_Etype
(Comp_Ref
, Comp_Typ
);
5623 -- [Deep_]Finalize (V);
5625 return Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5626 end Build_Finalization_Call
;
5632 procedure Build_Indexes
is
5634 -- Generate the following identifiers:
5635 -- Jnn - for initialization
5636 -- Fnn - for finalization
5638 for Dim
in 1 .. Num_Dims
loop
5639 Append_To
(Index_List
,
5640 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5642 Append_To
(Final_List
,
5643 Make_Defining_Identifier
(Loc
, New_External_Name
('F', Dim
)));
5647 -------------------------------
5648 -- Build_Initialization_Call --
5649 -------------------------------
5651 function Build_Initialization_Call
return Node_Id
is
5652 Comp_Ref
: constant Node_Id
:=
5653 Make_Indexed_Component
(Loc
,
5654 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5655 Expressions
=> New_References_To
(Index_List
, Loc
));
5658 Set_Etype
(Comp_Ref
, Comp_Typ
);
5661 -- [Deep_]Initialize (V (J1, ..., JN));
5663 return Make_Init_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5664 end Build_Initialization_Call
;
5666 -- Start of processing for Build_Initialize_Statements
5669 Counter_Id
:= Make_Temporary
(Loc
, 'C');
5670 Finalizer_Decls
:= New_List
;
5673 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
5675 -- Generate the block which houses the finalization call, the index
5676 -- guard and the handler which triggers Program_Error later on.
5678 -- if Counter > 0 then
5679 -- Counter := Counter - 1;
5681 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5683 -- begin -- Exceptions allowed
5684 -- [Deep_]Finalize (V (F1, ..., FN));
5687 -- if not Raised then
5689 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5694 if Exceptions_OK
then
5696 Make_Block_Statement
(Loc
,
5697 Handled_Statement_Sequence
=>
5698 Make_Handled_Sequence_Of_Statements
(Loc
,
5699 Statements
=> New_List
(Build_Finalization_Call
),
5700 Exception_Handlers
=> New_List
(
5701 Build_Exception_Handler
(Finalizer_Data
))));
5703 Fin_Stmt
:= Build_Finalization_Call
;
5706 -- This is the core of the loop, the dimension iterators are added
5707 -- one by one in reverse.
5710 Make_If_Statement
(Loc
,
5713 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5714 Right_Opnd
=> Make_Integer_Literal
(Loc
, 0)),
5716 Then_Statements
=> New_List
(
5717 Make_Assignment_Statement
(Loc
,
5718 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5720 Make_Op_Subtract
(Loc
,
5721 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5722 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)))),
5724 Else_Statements
=> New_List
(Fin_Stmt
));
5726 -- Generate all finalization loops starting from the innermost
5729 -- for Fnn in reverse V'Range (Dim) loop
5733 F
:= Last
(Final_List
);
5735 while Present
(F
) and then Dim
> 0 loop
5741 Make_Loop_Statement
(Loc
,
5743 Make_Iteration_Scheme
(Loc
,
5744 Loop_Parameter_Specification
=>
5745 Make_Loop_Parameter_Specification
(Loc
,
5746 Defining_Identifier
=> Loop_Id
,
5747 Discrete_Subtype_Definition
=>
5748 Make_Attribute_Reference
(Loc
,
5749 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5750 Attribute_Name
=> Name_Range
,
5751 Expressions
=> New_List
(
5752 Make_Integer_Literal
(Loc
, Dim
))),
5754 Reverse_Present
=> True)),
5756 Statements
=> New_List
(Final_Loop
),
5757 End_Label
=> Empty
);
5762 -- Generate the block which contains the finalization loops, the
5763 -- declarations of the abort flag, the exception occurrence, the
5764 -- raised flag and the conditional raise.
5767 -- Abort : constant Boolean := Triggered_By_Abort;
5769 -- Abort : constant Boolean := False; -- no abort
5771 -- E : Exception_Occurrence;
5772 -- Raised : Boolean := False;
5778 -- V'Length (N) - Counter;
5782 -- if Raised and then not Abort then -- Exception handlers OK
5783 -- Raise_From_Controlled_Operation (E);
5786 -- raise; -- Exception handlers OK
5789 Stmts
:= New_List
(Build_Counter_Assignment
, Final_Loop
);
5791 if Exceptions_OK
then
5793 Build_Raise_Statement
(Finalizer_Data
));
5794 Append_To
(Stmts
, Make_Raise_Statement
(Loc
));
5798 Make_Block_Statement
(Loc
,
5801 Handled_Statement_Sequence
=>
5802 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
));
5804 -- Generate the block which contains the initialization call and
5805 -- the partial finalization code.
5808 -- [Deep_]Initialize (V (J1, ..., JN));
5810 -- Counter := Counter + 1;
5814 -- <finalization code>
5818 Make_Block_Statement
(Loc
,
5819 Handled_Statement_Sequence
=>
5820 Make_Handled_Sequence_Of_Statements
(Loc
,
5821 Statements
=> New_List
(Build_Initialization_Call
),
5822 Exception_Handlers
=> New_List
(
5823 Make_Exception_Handler
(Loc
,
5824 Exception_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
5825 Statements
=> New_List
(Final_Block
)))));
5827 Append_To
(Statements
(Handled_Statement_Sequence
(Init_Loop
)),
5828 Make_Assignment_Statement
(Loc
,
5829 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5832 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5833 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1))));
5835 -- Generate all initialization loops starting from the innermost
5838 -- for Jnn in V'Range (Dim) loop
5842 J
:= Last
(Index_List
);
5844 while Present
(J
) and then Dim
> 0 loop
5850 Make_Loop_Statement
(Loc
,
5852 Make_Iteration_Scheme
(Loc
,
5853 Loop_Parameter_Specification
=>
5854 Make_Loop_Parameter_Specification
(Loc
,
5855 Defining_Identifier
=> Loop_Id
,
5856 Discrete_Subtype_Definition
=>
5857 Make_Attribute_Reference
(Loc
,
5858 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5859 Attribute_Name
=> Name_Range
,
5860 Expressions
=> New_List
(
5861 Make_Integer_Literal
(Loc
, Dim
))))),
5863 Statements
=> New_List
(Init_Loop
),
5864 End_Label
=> Empty
);
5869 -- Generate the block which contains the counter variable and the
5870 -- initialization loops.
5873 -- Counter : Integer := 0;
5880 Make_Block_Statement
(Loc
,
5881 Declarations
=> New_List
(
5882 Make_Object_Declaration
(Loc
,
5883 Defining_Identifier
=> Counter_Id
,
5884 Object_Definition
=>
5885 New_Occurrence_Of
(Standard_Integer
, Loc
),
5886 Expression
=> Make_Integer_Literal
(Loc
, 0))),
5888 Handled_Statement_Sequence
=>
5889 Make_Handled_Sequence_Of_Statements
(Loc
,
5890 Statements
=> New_List
(Init_Loop
))));
5891 end Build_Initialize_Statements
;
5893 -----------------------
5894 -- New_References_To --
5895 -----------------------
5897 function New_References_To
5899 Loc
: Source_Ptr
) return List_Id
5901 Refs
: constant List_Id
:= New_List
;
5906 while Present
(Id
) loop
5907 Append_To
(Refs
, New_Occurrence_Of
(Id
, Loc
));
5912 end New_References_To
;
5914 -- Start of processing for Make_Deep_Array_Body
5918 when Address_Case
=>
5919 return Make_Finalize_Address_Stmts
(Typ
);
5923 return Build_Adjust_Or_Finalize_Statements
(Typ
);
5925 when Initialize_Case
=>
5926 return Build_Initialize_Statements
(Typ
);
5928 end Make_Deep_Array_Body
;
5930 --------------------
5931 -- Make_Deep_Proc --
5932 --------------------
5934 function Make_Deep_Proc
5935 (Prim
: Final_Primitives
;
5937 Stmts
: List_Id
) return Entity_Id
5939 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5941 Proc_Id
: Entity_Id
;
5944 -- Create the object formal, generate:
5945 -- V : System.Address
5947 if Prim
= Address_Case
then
5948 Formals
:= New_List
(
5949 Make_Parameter_Specification
(Loc
,
5950 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
5952 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)));
5959 Formals
:= New_List
(
5960 Make_Parameter_Specification
(Loc
,
5961 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
5963 Out_Present
=> True,
5964 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
)));
5966 -- F : Boolean := True
5968 if Prim
= Adjust_Case
5969 or else Prim
= Finalize_Case
5972 Make_Parameter_Specification
(Loc
,
5973 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
5975 New_Occurrence_Of
(Standard_Boolean
, Loc
),
5977 New_Occurrence_Of
(Standard_True
, Loc
)));
5982 Make_Defining_Identifier
(Loc
,
5983 Chars
=> Make_TSS_Name
(Typ
, Deep_Name_Of
(Prim
)));
5986 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5989 -- exception -- Finalize and Adjust cases only
5990 -- raise Program_Error;
5991 -- end Deep_Initialize / Adjust / Finalize;
5995 -- procedure Finalize_Address (V : System.Address) is
5998 -- end Finalize_Address;
6001 Make_Subprogram_Body
(Loc
,
6003 Make_Procedure_Specification
(Loc
,
6004 Defining_Unit_Name
=> Proc_Id
,
6005 Parameter_Specifications
=> Formals
),
6007 Declarations
=> Empty_List
,
6009 Handled_Statement_Sequence
=>
6010 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
)));
6015 ---------------------------
6016 -- Make_Deep_Record_Body --
6017 ---------------------------
6019 function Make_Deep_Record_Body
6020 (Prim
: Final_Primitives
;
6022 Is_Local
: Boolean := False) return List_Id
6024 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
;
6025 -- Build the statements necessary to adjust a record type. The type may
6026 -- have discriminants and contain variant parts. Generate:
6030 -- [Deep_]Adjust (V.Comp_1);
6032 -- when Id : others =>
6033 -- if not Raised then
6035 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6040 -- [Deep_]Adjust (V.Comp_N);
6042 -- when Id : others =>
6043 -- if not Raised then
6045 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6050 -- Deep_Adjust (V._parent, False); -- If applicable
6052 -- when Id : others =>
6053 -- if not Raised then
6055 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6061 -- Adjust (V); -- If applicable
6064 -- if not Raised then
6066 -- Save_Occurence (E, Get_Current_Excep.all.all);
6071 -- if Raised and then not Abort then
6072 -- Raise_From_Controlled_Operation (E);
6076 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
;
6077 -- Build the statements necessary to finalize a record type. The type
6078 -- may have discriminants and contain variant parts. Generate:
6081 -- Abort : constant Boolean := Triggered_By_Abort;
6083 -- Abort : constant Boolean := False; -- no abort
6084 -- E : Exception_Occurence;
6085 -- Raised : Boolean := False;
6090 -- Finalize (V); -- If applicable
6093 -- if not Raised then
6095 -- Save_Occurence (E, Get_Current_Excep.all.all);
6100 -- case Variant_1 is
6102 -- case State_Counter_N => -- If Is_Local is enabled
6112 -- <<LN>> -- If Is_Local is enabled
6114 -- [Deep_]Finalize (V.Comp_N);
6117 -- if not Raised then
6119 -- Save_Occurence (E, Get_Current_Excep.all.all);
6125 -- [Deep_]Finalize (V.Comp_1);
6128 -- if not Raised then
6130 -- Save_Occurence (E, Get_Current_Excep.all.all);
6136 -- case State_Counter_1 => -- If Is_Local is enabled
6142 -- Deep_Finalize (V._parent, False); -- If applicable
6144 -- when Id : others =>
6145 -- if not Raised then
6147 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6151 -- if Raised and then not Abort then
6152 -- Raise_From_Controlled_Operation (E);
6156 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
;
6157 -- Given a derived tagged type Typ, traverse all components, find field
6158 -- _parent and return its type.
6160 procedure Preprocess_Components
6162 Num_Comps
: out Int
;
6163 Has_POC
: out Boolean);
6164 -- Examine all components in component list Comps, count all controlled
6165 -- components and determine whether at least one of them is per-object
6166 -- constrained. Component _parent is always skipped.
6168 -----------------------------
6169 -- Build_Adjust_Statements --
6170 -----------------------------
6172 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
is
6173 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6174 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
6175 Bod_Stmts
: List_Id
;
6176 Finalizer_Data
: Finalization_Exception_Data
;
6177 Finalizer_Decls
: List_Id
:= No_List
;
6181 Exceptions_OK
: constant Boolean :=
6182 not Restriction_Active
(No_Exception_Propagation
);
6184 function Process_Component_List_For_Adjust
6185 (Comps
: Node_Id
) return List_Id
;
6186 -- Build all necessary adjust statements for a single component list
6188 ---------------------------------------
6189 -- Process_Component_List_For_Adjust --
6190 ---------------------------------------
6192 function Process_Component_List_For_Adjust
6193 (Comps
: Node_Id
) return List_Id
6195 Stmts
: constant List_Id
:= New_List
;
6197 Decl_Id
: Entity_Id
;
6198 Decl_Typ
: Entity_Id
;
6202 procedure Process_Component_For_Adjust
(Decl
: Node_Id
);
6203 -- Process the declaration of a single controlled component
6205 ----------------------------------
6206 -- Process_Component_For_Adjust --
6207 ----------------------------------
6209 procedure Process_Component_For_Adjust
(Decl
: Node_Id
) is
6210 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
6211 Typ
: constant Entity_Id
:= Etype
(Id
);
6216 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
6218 -- begin -- Exception handlers allowed
6219 -- [Deep_]Adjust (V.Id);
6222 -- if not Raised then
6224 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6231 Make_Selected_Component
(Loc
,
6232 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6233 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
6236 if Exceptions_OK
then
6238 Make_Block_Statement
(Loc
,
6239 Handled_Statement_Sequence
=>
6240 Make_Handled_Sequence_Of_Statements
(Loc
,
6241 Statements
=> New_List
(Adj_Stmt
),
6242 Exception_Handlers
=> New_List
(
6243 Build_Exception_Handler
(Finalizer_Data
))));
6246 Append_To
(Stmts
, Adj_Stmt
);
6247 end Process_Component_For_Adjust
;
6249 -- Start of processing for Process_Component_List_For_Adjust
6252 -- Perform an initial check, determine the number of controlled
6253 -- components in the current list and whether at least one of them
6254 -- is per-object constrained.
6256 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
6258 -- The processing in this routine is done in the following order:
6259 -- 1) Regular components
6260 -- 2) Per-object constrained components
6263 if Num_Comps
> 0 then
6265 -- Process all regular components in order of declarations
6267 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6268 while Present
(Decl
) loop
6269 Decl_Id
:= Defining_Identifier
(Decl
);
6270 Decl_Typ
:= Etype
(Decl_Id
);
6272 -- Skip _parent as well as per-object constrained components
6274 if Chars
(Decl_Id
) /= Name_uParent
6275 and then Needs_Finalization
(Decl_Typ
)
6277 if Has_Access_Constraint
(Decl_Id
)
6278 and then No
(Expression
(Decl
))
6282 Process_Component_For_Adjust
(Decl
);
6286 Next_Non_Pragma
(Decl
);
6289 -- Process all per-object constrained components in order of
6293 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6294 while Present
(Decl
) loop
6295 Decl_Id
:= Defining_Identifier
(Decl
);
6296 Decl_Typ
:= Etype
(Decl_Id
);
6300 if Chars
(Decl_Id
) /= Name_uParent
6301 and then Needs_Finalization
(Decl_Typ
)
6302 and then Has_Access_Constraint
(Decl_Id
)
6303 and then No
(Expression
(Decl
))
6305 Process_Component_For_Adjust
(Decl
);
6308 Next_Non_Pragma
(Decl
);
6313 -- Process all variants, if any
6316 if Present
(Variant_Part
(Comps
)) then
6318 Var_Alts
: constant List_Id
:= New_List
;
6322 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
6323 while Present
(Var
) loop
6326 -- when <discrete choices> =>
6327 -- <adjust statements>
6329 Append_To
(Var_Alts
,
6330 Make_Case_Statement_Alternative
(Loc
,
6332 New_Copy_List
(Discrete_Choices
(Var
)),
6334 Process_Component_List_For_Adjust
(
6335 Component_List
(Var
))));
6337 Next_Non_Pragma
(Var
);
6341 -- case V.<discriminant> is
6342 -- when <discrete choices 1> =>
6343 -- <adjust statements 1>
6345 -- when <discrete choices N> =>
6346 -- <adjust statements N>
6350 Make_Case_Statement
(Loc
,
6352 Make_Selected_Component
(Loc
,
6353 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6355 Make_Identifier
(Loc
,
6356 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
6357 Alternatives
=> Var_Alts
);
6361 -- Add the variant case statement to the list of statements
6363 if Present
(Var_Case
) then
6364 Append_To
(Stmts
, Var_Case
);
6367 -- If the component list did not have any controlled components
6368 -- nor variants, return null.
6370 if Is_Empty_List
(Stmts
) then
6371 Append_To
(Stmts
, Make_Null_Statement
(Loc
));
6375 end Process_Component_List_For_Adjust
;
6377 -- Start of processing for Build_Adjust_Statements
6380 Finalizer_Decls
:= New_List
;
6381 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
6383 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
6384 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
6389 -- Create an adjust sequence for all record components
6391 if Present
(Component_List
(Rec_Def
)) then
6393 Process_Component_List_For_Adjust
(Component_List
(Rec_Def
));
6396 -- A derived record type must adjust all inherited components. This
6397 -- action poses the following problem:
6399 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
6404 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
6406 -- Deep_Adjust (Obj._parent);
6411 -- Adjusting the derived type will invoke Adjust of the parent and
6412 -- then that of the derived type. This is undesirable because both
6413 -- routines may modify shared components. Only the Adjust of the
6414 -- derived type should be invoked.
6416 -- To prevent this double adjustment of shared components,
6417 -- Deep_Adjust uses a flag to control the invocation of Adjust:
6419 -- procedure Deep_Adjust
6420 -- (Obj : in out Some_Type;
6421 -- Flag : Boolean := True)
6429 -- When Deep_Adjust is invokes for field _parent, a value of False is
6430 -- provided for the flag:
6432 -- Deep_Adjust (Obj._parent, False);
6434 if Is_Tagged_Type
(Typ
) and then Is_Derived_Type
(Typ
) then
6436 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
6441 if Needs_Finalization
(Par_Typ
) then
6445 Make_Selected_Component
(Loc
,
6446 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6448 Make_Identifier
(Loc
, Name_uParent
)),
6453 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
6455 -- begin -- Exceptions OK
6456 -- Deep_Adjust (V._parent, False);
6458 -- when Id : others =>
6459 -- if not Raised then
6461 -- Save_Occurrence (E,
6462 -- Get_Current_Excep.all.all);
6466 if Present
(Call
) then
6469 if Exceptions_OK
then
6471 Make_Block_Statement
(Loc
,
6472 Handled_Statement_Sequence
=>
6473 Make_Handled_Sequence_Of_Statements
(Loc
,
6474 Statements
=> New_List
(Adj_Stmt
),
6475 Exception_Handlers
=> New_List
(
6476 Build_Exception_Handler
(Finalizer_Data
))));
6479 Prepend_To
(Bod_Stmts
, Adj_Stmt
);
6485 -- Adjust the object. This action must be performed last after all
6486 -- components have been adjusted.
6488 if Is_Controlled
(Typ
) then
6494 Proc
:= Find_Prim_Op
(Typ
, Name_Adjust
);
6498 -- Adjust (V); -- No_Exception_Propagation
6500 -- begin -- Exception handlers allowed
6504 -- if not Raised then
6506 -- Save_Occurrence (E,
6507 -- Get_Current_Excep.all.all);
6512 if Present
(Proc
) then
6514 Make_Procedure_Call_Statement
(Loc
,
6515 Name
=> New_Occurrence_Of
(Proc
, Loc
),
6516 Parameter_Associations
=> New_List
(
6517 Make_Identifier
(Loc
, Name_V
)));
6519 if Exceptions_OK
then
6521 Make_Block_Statement
(Loc
,
6522 Handled_Statement_Sequence
=>
6523 Make_Handled_Sequence_Of_Statements
(Loc
,
6524 Statements
=> New_List
(Adj_Stmt
),
6525 Exception_Handlers
=> New_List
(
6526 Build_Exception_Handler
6527 (Finalizer_Data
))));
6530 Append_To
(Bod_Stmts
,
6531 Make_If_Statement
(Loc
,
6532 Condition
=> Make_Identifier
(Loc
, Name_F
),
6533 Then_Statements
=> New_List
(Adj_Stmt
)));
6538 -- At this point either all adjustment statements have been generated
6539 -- or the type is not controlled.
6541 if Is_Empty_List
(Bod_Stmts
) then
6542 Append_To
(Bod_Stmts
, Make_Null_Statement
(Loc
));
6548 -- Abort : constant Boolean := Triggered_By_Abort;
6550 -- Abort : constant Boolean := False; -- no abort
6552 -- E : Exception_Occurence;
6553 -- Raised : Boolean := False;
6556 -- <adjust statements>
6558 -- if Raised and then not Abort then
6559 -- Raise_From_Controlled_Operation (E);
6564 if Exceptions_OK
then
6565 Append_To
(Bod_Stmts
,
6566 Build_Raise_Statement
(Finalizer_Data
));
6571 Make_Block_Statement
(Loc
,
6574 Handled_Statement_Sequence
=>
6575 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
6577 end Build_Adjust_Statements
;
6579 -------------------------------
6580 -- Build_Finalize_Statements --
6581 -------------------------------
6583 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
is
6584 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6585 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
6586 Bod_Stmts
: List_Id
;
6588 Finalizer_Data
: Finalization_Exception_Data
;
6589 Finalizer_Decls
: List_Id
:= No_List
;
6593 Exceptions_OK
: constant Boolean :=
6594 not Restriction_Active
(No_Exception_Propagation
);
6596 function Process_Component_List_For_Finalize
6597 (Comps
: Node_Id
) return List_Id
;
6598 -- Build all necessary finalization statements for a single component
6599 -- list. The statements may include a jump circuitry if flag Is_Local
6602 -----------------------------------------
6603 -- Process_Component_List_For_Finalize --
6604 -----------------------------------------
6606 function Process_Component_List_For_Finalize
6607 (Comps
: Node_Id
) return List_Id
6610 Counter_Id
: Entity_Id
;
6612 Decl_Id
: Entity_Id
;
6613 Decl_Typ
: Entity_Id
;
6616 Jump_Block
: Node_Id
;
6618 Label_Id
: Entity_Id
;
6622 procedure Process_Component_For_Finalize
6627 -- Process the declaration of a single controlled component. If
6628 -- flag Is_Local is enabled, create the corresponding label and
6629 -- jump circuitry. Alts is the list of case alternatives, Decls
6630 -- is the top level declaration list where labels are declared
6631 -- and Stmts is the list of finalization actions.
6633 ------------------------------------
6634 -- Process_Component_For_Finalize --
6635 ------------------------------------
6637 procedure Process_Component_For_Finalize
6643 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
6644 Typ
: constant Entity_Id
:= Etype
(Id
);
6651 Label_Id
: Entity_Id
;
6658 Make_Identifier
(Loc
,
6659 Chars
=> New_External_Name
('L', Num_Comps
));
6660 Set_Entity
(Label_Id
,
6661 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
6662 Label
:= Make_Label
(Loc
, Label_Id
);
6665 Make_Implicit_Label_Declaration
(Loc
,
6666 Defining_Identifier
=> Entity
(Label_Id
),
6667 Label_Construct
=> Label
));
6674 Make_Case_Statement_Alternative
(Loc
,
6675 Discrete_Choices
=> New_List
(
6676 Make_Integer_Literal
(Loc
, Num_Comps
)),
6678 Statements
=> New_List
(
6679 Make_Goto_Statement
(Loc
,
6681 New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
6686 Append_To
(Stmts
, Label
);
6688 -- Decrease the number of components to be processed.
6689 -- This action yields a new Label_Id in future calls.
6691 Num_Comps
:= Num_Comps
- 1;
6696 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6698 -- begin -- Exception handlers allowed
6699 -- [Deep_]Finalize (V.Id);
6702 -- if not Raised then
6704 -- Save_Occurrence (E,
6705 -- Get_Current_Excep.all.all);
6712 Make_Selected_Component
(Loc
,
6713 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6714 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
6717 if not Restriction_Active
(No_Exception_Propagation
) then
6719 Make_Block_Statement
(Loc
,
6720 Handled_Statement_Sequence
=>
6721 Make_Handled_Sequence_Of_Statements
(Loc
,
6722 Statements
=> New_List
(Fin_Stmt
),
6723 Exception_Handlers
=> New_List
(
6724 Build_Exception_Handler
(Finalizer_Data
))));
6727 Append_To
(Stmts
, Fin_Stmt
);
6728 end Process_Component_For_Finalize
;
6730 -- Start of processing for Process_Component_List_For_Finalize
6733 -- Perform an initial check, look for controlled and per-object
6734 -- constrained components.
6736 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
6738 -- Create a state counter to service the current component list.
6739 -- This step is performed before the variants are inspected in
6740 -- order to generate the same state counter names as those from
6741 -- Build_Initialize_Statements.
6743 if Num_Comps
> 0 and then Is_Local
then
6744 Counter
:= Counter
+ 1;
6747 Make_Defining_Identifier
(Loc
,
6748 Chars
=> New_External_Name
('C', Counter
));
6751 -- Process the component in the following order:
6753 -- 2) Per-object constrained components
6754 -- 3) Regular components
6756 -- Start with the variant parts
6759 if Present
(Variant_Part
(Comps
)) then
6761 Var_Alts
: constant List_Id
:= New_List
;
6765 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
6766 while Present
(Var
) loop
6769 -- when <discrete choices> =>
6770 -- <finalize statements>
6772 Append_To
(Var_Alts
,
6773 Make_Case_Statement_Alternative
(Loc
,
6775 New_Copy_List
(Discrete_Choices
(Var
)),
6777 Process_Component_List_For_Finalize
(
6778 Component_List
(Var
))));
6780 Next_Non_Pragma
(Var
);
6784 -- case V.<discriminant> is
6785 -- when <discrete choices 1> =>
6786 -- <finalize statements 1>
6788 -- when <discrete choices N> =>
6789 -- <finalize statements N>
6793 Make_Case_Statement
(Loc
,
6795 Make_Selected_Component
(Loc
,
6796 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6798 Make_Identifier
(Loc
,
6799 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
6800 Alternatives
=> Var_Alts
);
6804 -- The current component list does not have a single controlled
6805 -- component, however it may contain variants. Return the case
6806 -- statement for the variants or nothing.
6808 if Num_Comps
= 0 then
6809 if Present
(Var_Case
) then
6810 return New_List
(Var_Case
);
6812 return New_List
(Make_Null_Statement
(Loc
));
6816 -- Prepare all lists
6822 -- Process all per-object constrained components in reverse order
6825 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
6826 while Present
(Decl
) loop
6827 Decl_Id
:= Defining_Identifier
(Decl
);
6828 Decl_Typ
:= Etype
(Decl_Id
);
6832 if Chars
(Decl_Id
) /= Name_uParent
6833 and then Needs_Finalization
(Decl_Typ
)
6834 and then Has_Access_Constraint
(Decl_Id
)
6835 and then No
(Expression
(Decl
))
6837 Process_Component_For_Finalize
(Decl
, Alts
, Decls
, Stmts
);
6840 Prev_Non_Pragma
(Decl
);
6844 -- Process the rest of the components in reverse order
6846 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
6847 while Present
(Decl
) loop
6848 Decl_Id
:= Defining_Identifier
(Decl
);
6849 Decl_Typ
:= Etype
(Decl_Id
);
6853 if Chars
(Decl_Id
) /= Name_uParent
6854 and then Needs_Finalization
(Decl_Typ
)
6856 -- Skip per-object constrained components since they were
6857 -- handled in the above step.
6859 if Has_Access_Constraint
(Decl_Id
)
6860 and then No
(Expression
(Decl
))
6864 Process_Component_For_Finalize
(Decl
, Alts
, Decls
, Stmts
);
6868 Prev_Non_Pragma
(Decl
);
6873 -- LN : label; -- If Is_Local is enabled
6878 -- case CounterX is .
6888 -- <<LN>> -- If Is_Local is enabled
6890 -- [Deep_]Finalize (V.CompY);
6892 -- when Id : others =>
6893 -- if not Raised then
6895 -- Save_Occurrence (E,
6896 -- Get_Current_Excep.all.all);
6900 -- <<L0>> -- If Is_Local is enabled
6905 -- Add the declaration of default jump location L0, its
6906 -- corresponding alternative and its place in the statements.
6908 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
6909 Set_Entity
(Label_Id
,
6910 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
6911 Label
:= Make_Label
(Loc
, Label_Id
);
6913 Append_To
(Decls
, -- declaration
6914 Make_Implicit_Label_Declaration
(Loc
,
6915 Defining_Identifier
=> Entity
(Label_Id
),
6916 Label_Construct
=> Label
));
6918 Append_To
(Alts
, -- alternative
6919 Make_Case_Statement_Alternative
(Loc
,
6920 Discrete_Choices
=> New_List
(
6921 Make_Others_Choice
(Loc
)),
6923 Statements
=> New_List
(
6924 Make_Goto_Statement
(Loc
,
6925 Name
=> New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
6927 Append_To
(Stmts
, Label
); -- statement
6929 -- Create the jump block
6932 Make_Case_Statement
(Loc
,
6933 Expression
=> Make_Identifier
(Loc
, Chars
(Counter_Id
)),
6934 Alternatives
=> Alts
));
6938 Make_Block_Statement
(Loc
,
6939 Declarations
=> Decls
,
6940 Handled_Statement_Sequence
=>
6941 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
));
6943 if Present
(Var_Case
) then
6944 return New_List
(Var_Case
, Jump_Block
);
6946 return New_List
(Jump_Block
);
6948 end Process_Component_List_For_Finalize
;
6950 -- Start of processing for Build_Finalize_Statements
6953 Finalizer_Decls
:= New_List
;
6954 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
6956 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
6957 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
6962 -- Create a finalization sequence for all record components
6964 if Present
(Component_List
(Rec_Def
)) then
6966 Process_Component_List_For_Finalize
(Component_List
(Rec_Def
));
6969 -- A derived record type must finalize all inherited components. This
6970 -- action poses the following problem:
6972 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6977 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6979 -- Deep_Finalize (Obj._parent);
6984 -- Finalizing the derived type will invoke Finalize of the parent and
6985 -- then that of the derived type. This is undesirable because both
6986 -- routines may modify shared components. Only the Finalize of the
6987 -- derived type should be invoked.
6989 -- To prevent this double adjustment of shared components,
6990 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6992 -- procedure Deep_Finalize
6993 -- (Obj : in out Some_Type;
6994 -- Flag : Boolean := True)
7002 -- When Deep_Finalize is invokes for field _parent, a value of False
7003 -- is provided for the flag:
7005 -- Deep_Finalize (Obj._parent, False);
7007 if Is_Tagged_Type
(Typ
) and then Is_Derived_Type
(Typ
) then
7009 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
7014 if Needs_Finalization
(Par_Typ
) then
7018 Make_Selected_Component
(Loc
,
7019 Prefix
=> Make_Identifier
(Loc
, Name_V
),
7021 Make_Identifier
(Loc
, Name_uParent
)),
7026 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
7028 -- begin -- Exceptions OK
7029 -- Deep_Finalize (V._parent, False);
7031 -- when Id : others =>
7032 -- if not Raised then
7034 -- Save_Occurrence (E,
7035 -- Get_Current_Excep.all.all);
7039 if Present
(Call
) then
7042 if Exceptions_OK
then
7044 Make_Block_Statement
(Loc
,
7045 Handled_Statement_Sequence
=>
7046 Make_Handled_Sequence_Of_Statements
(Loc
,
7047 Statements
=> New_List
(Fin_Stmt
),
7048 Exception_Handlers
=> New_List
(
7049 Build_Exception_Handler
7050 (Finalizer_Data
))));
7053 Append_To
(Bod_Stmts
, Fin_Stmt
);
7059 -- Finalize the object. This action must be performed first before
7060 -- all components have been finalized.
7062 if Is_Controlled
(Typ
) and then not Is_Local
then
7068 Proc
:= Find_Prim_Op
(Typ
, Name_Finalize
);
7072 -- Finalize (V); -- No_Exception_Propagation
7078 -- if not Raised then
7080 -- Save_Occurrence (E,
7081 -- Get_Current_Excep.all.all);
7086 if Present
(Proc
) then
7088 Make_Procedure_Call_Statement
(Loc
,
7089 Name
=> New_Occurrence_Of
(Proc
, Loc
),
7090 Parameter_Associations
=> New_List
(
7091 Make_Identifier
(Loc
, Name_V
)));
7093 if Exceptions_OK
then
7095 Make_Block_Statement
(Loc
,
7096 Handled_Statement_Sequence
=>
7097 Make_Handled_Sequence_Of_Statements
(Loc
,
7098 Statements
=> New_List
(Fin_Stmt
),
7099 Exception_Handlers
=> New_List
(
7100 Build_Exception_Handler
7101 (Finalizer_Data
))));
7104 Prepend_To
(Bod_Stmts
,
7105 Make_If_Statement
(Loc
,
7106 Condition
=> Make_Identifier
(Loc
, Name_F
),
7107 Then_Statements
=> New_List
(Fin_Stmt
)));
7112 -- At this point either all finalization statements have been
7113 -- generated or the type is not controlled.
7115 if No
(Bod_Stmts
) then
7116 return New_List
(Make_Null_Statement
(Loc
));
7120 -- Abort : constant Boolean := Triggered_By_Abort;
7122 -- Abort : constant Boolean := False; -- no abort
7124 -- E : Exception_Occurence;
7125 -- Raised : Boolean := False;
7128 -- <finalize statements>
7130 -- if Raised and then not Abort then
7131 -- Raise_From_Controlled_Operation (E);
7136 if Exceptions_OK
then
7137 Append_To
(Bod_Stmts
,
7138 Build_Raise_Statement
(Finalizer_Data
));
7143 Make_Block_Statement
(Loc
,
7146 Handled_Statement_Sequence
=>
7147 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
7149 end Build_Finalize_Statements
;
7151 -----------------------
7152 -- Parent_Field_Type --
7153 -----------------------
7155 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
is
7159 Field
:= First_Entity
(Typ
);
7160 while Present
(Field
) loop
7161 if Chars
(Field
) = Name_uParent
then
7162 return Etype
(Field
);
7165 Next_Entity
(Field
);
7168 -- A derived tagged type should always have a parent field
7170 raise Program_Error
;
7171 end Parent_Field_Type
;
7173 ---------------------------
7174 -- Preprocess_Components --
7175 ---------------------------
7177 procedure Preprocess_Components
7179 Num_Comps
: out Int
;
7180 Has_POC
: out Boolean)
7190 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
7191 while Present
(Decl
) loop
7192 Id
:= Defining_Identifier
(Decl
);
7195 -- Skip field _parent
7197 if Chars
(Id
) /= Name_uParent
7198 and then Needs_Finalization
(Typ
)
7200 Num_Comps
:= Num_Comps
+ 1;
7202 if Has_Access_Constraint
(Id
)
7203 and then No
(Expression
(Decl
))
7209 Next_Non_Pragma
(Decl
);
7211 end Preprocess_Components
;
7213 -- Start of processing for Make_Deep_Record_Body
7217 when Address_Case
=>
7218 return Make_Finalize_Address_Stmts
(Typ
);
7221 return Build_Adjust_Statements
(Typ
);
7223 when Finalize_Case
=>
7224 return Build_Finalize_Statements
(Typ
);
7226 when Initialize_Case
=>
7228 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7231 if Is_Controlled
(Typ
) then
7233 Make_Procedure_Call_Statement
(Loc
,
7236 (Find_Prim_Op
(Typ
, Name_Of
(Prim
)), Loc
),
7237 Parameter_Associations
=> New_List
(
7238 Make_Identifier
(Loc
, Name_V
))));
7244 end Make_Deep_Record_Body
;
7246 ----------------------
7247 -- Make_Final_Call --
7248 ----------------------
7250 function Make_Final_Call
7253 Skip_Self
: Boolean := False) return Node_Id
7255 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
7257 Fin_Id
: Entity_Id
:= Empty
;
7262 -- Recover the proper type which contains [Deep_]Finalize
7264 if Is_Class_Wide_Type
(Typ
) then
7265 Utyp
:= Root_Type
(Typ
);
7269 elsif Is_Concurrent_Type
(Typ
) then
7270 Utyp
:= Corresponding_Record_Type
(Typ
);
7272 Ref
:= Convert_Concurrent
(Obj_Ref
, Typ
);
7274 elsif Is_Private_Type
(Typ
)
7275 and then Present
(Full_View
(Typ
))
7276 and then Is_Concurrent_Type
(Full_View
(Typ
))
7278 Utyp
:= Corresponding_Record_Type
(Full_View
(Typ
));
7280 Ref
:= Convert_Concurrent
(Obj_Ref
, Full_View
(Typ
));
7288 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7289 Set_Assignment_OK
(Ref
);
7291 -- Deal with untagged derivation of private views. If the parent type
7292 -- is a protected type, Deep_Finalize is found on the corresponding
7293 -- record of the ancestor.
7295 if Is_Untagged_Derivation
(Typ
) then
7296 if Is_Protected_Type
(Typ
) then
7297 Utyp
:= Corresponding_Record_Type
(Root_Type
(Base_Type
(Typ
)));
7299 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7301 if Is_Protected_Type
(Utyp
) then
7302 Utyp
:= Corresponding_Record_Type
(Utyp
);
7306 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7307 Set_Assignment_OK
(Ref
);
7310 -- Deal with derived private types which do not inherit primitives from
7311 -- their parents. In this case, [Deep_]Finalize can be found in the full
7312 -- view of the parent type.
7314 if Is_Tagged_Type
(Utyp
)
7315 and then Is_Derived_Type
(Utyp
)
7316 and then Is_Empty_Elmt_List
(Primitive_Operations
(Utyp
))
7317 and then Is_Private_Type
(Etype
(Utyp
))
7318 and then Present
(Full_View
(Etype
(Utyp
)))
7320 Utyp
:= Full_View
(Etype
(Utyp
));
7321 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7322 Set_Assignment_OK
(Ref
);
7325 -- When dealing with the completion of a private type, use the base type
7328 if Utyp
/= Base_Type
(Utyp
) then
7329 pragma Assert
(Present
(Atyp
) and then Is_Private_Type
(Atyp
));
7331 Utyp
:= Base_Type
(Utyp
);
7332 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7333 Set_Assignment_OK
(Ref
);
7337 if Has_Controlled_Component
(Utyp
) then
7338 if Is_Tagged_Type
(Utyp
) then
7339 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7341 Fin_Id
:= TSS
(Utyp
, TSS_Deep_Finalize
);
7345 -- Class-wide types, interfaces and types with controlled components
7347 elsif Is_Class_Wide_Type
(Typ
)
7348 or else Is_Interface
(Typ
)
7349 or else Has_Controlled_Component
(Utyp
)
7351 if Is_Tagged_Type
(Utyp
) then
7352 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7354 Fin_Id
:= TSS
(Utyp
, TSS_Deep_Finalize
);
7357 -- Derivations from [Limited_]Controlled
7359 elsif Is_Controlled
(Utyp
) then
7360 if Has_Controlled_Component
(Utyp
) then
7361 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7363 Fin_Id
:= Find_Prim_Op
(Utyp
, Name_Of
(Finalize_Case
));
7368 elsif Is_Tagged_Type
(Utyp
) then
7369 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7372 raise Program_Error
;
7375 if Present
(Fin_Id
) then
7377 -- When finalizing a class-wide object, do not convert to the root
7378 -- type in order to produce a dispatching call.
7380 if Is_Class_Wide_Type
(Typ
) then
7383 -- Ensure that a finalization routine is at least decorated in order
7384 -- to inspect the object parameter.
7386 elsif Analyzed
(Fin_Id
)
7387 or else Ekind
(Fin_Id
) = E_Procedure
7389 -- In certain cases, such as the creation of Stream_Read, the
7390 -- visible entity of the type is its full view. Since Stream_Read
7391 -- will have to create an object of type Typ, the local object
7392 -- will be finalzed by the scope finalizer generated later on. The
7393 -- object parameter of Deep_Finalize will always use the private
7394 -- view of the type. To avoid such a clash between a private and a
7395 -- full view, perform an unchecked conversion of the object
7396 -- reference to the private view.
7399 Formal_Typ
: constant Entity_Id
:=
7400 Etype
(First_Formal
(Fin_Id
));
7402 if Is_Private_Type
(Formal_Typ
)
7403 and then Present
(Full_View
(Formal_Typ
))
7404 and then Full_View
(Formal_Typ
) = Utyp
7406 Ref
:= Unchecked_Convert_To
(Formal_Typ
, Ref
);
7410 Ref
:= Convert_View
(Fin_Id
, Ref
);
7416 Param
=> New_Copy_Tree
(Ref
),
7417 Skip_Self
=> Skip_Self
);
7421 end Make_Final_Call
;
7423 --------------------------------
7424 -- Make_Finalize_Address_Body --
7425 --------------------------------
7427 procedure Make_Finalize_Address_Body
(Typ
: Entity_Id
) is
7428 Is_Task
: constant Boolean :=
7429 Ekind
(Typ
) = E_Record_Type
7430 and then Is_Concurrent_Record_Type
(Typ
)
7431 and then Ekind
(Corresponding_Concurrent_Type
(Typ
)) =
7433 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7434 Proc_Id
: Entity_Id
;
7438 -- The corresponding records of task types are not controlled by design.
7439 -- For the sake of completeness, create an empty Finalize_Address to be
7440 -- used in task class-wide allocations.
7445 -- Nothing to do if the type is not controlled or it already has a
7446 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
7447 -- come from source. These are usually generated for completeness and
7448 -- do not need the Finalize_Address primitive.
7450 elsif not Needs_Finalization
(Typ
)
7451 or else Present
(TSS
(Typ
, TSS_Finalize_Address
))
7453 (Is_Class_Wide_Type
(Typ
)
7454 and then Ekind
(Root_Type
(Typ
)) = E_Record_Subtype
7455 and then not Comes_From_Source
(Root_Type
(Typ
)))
7461 Make_Defining_Identifier
(Loc
,
7462 Make_TSS_Name
(Typ
, TSS_Finalize_Address
));
7466 -- procedure <Typ>FD (V : System.Address) is
7468 -- null; -- for tasks
7470 -- declare -- for all other types
7471 -- type Pnn is access all Typ;
7472 -- for Pnn'Storage_Size use 0;
7474 -- [Deep_]Finalize (Pnn (V).all);
7479 Stmts
:= New_List
(Make_Null_Statement
(Loc
));
7481 Stmts
:= Make_Finalize_Address_Stmts
(Typ
);
7485 Make_Subprogram_Body
(Loc
,
7487 Make_Procedure_Specification
(Loc
,
7488 Defining_Unit_Name
=> Proc_Id
,
7490 Parameter_Specifications
=> New_List
(
7491 Make_Parameter_Specification
(Loc
,
7492 Defining_Identifier
=>
7493 Make_Defining_Identifier
(Loc
, Name_V
),
7495 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)))),
7497 Declarations
=> No_List
,
7499 Handled_Statement_Sequence
=>
7500 Make_Handled_Sequence_Of_Statements
(Loc
,
7501 Statements
=> Stmts
)));
7503 Set_TSS
(Typ
, Proc_Id
);
7504 end Make_Finalize_Address_Body
;
7506 ---------------------------------
7507 -- Make_Finalize_Address_Stmts --
7508 ---------------------------------
7510 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
is
7511 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7512 Ptr_Typ
: constant Entity_Id
:= Make_Temporary
(Loc
, 'P');
7514 Desg_Typ
: Entity_Id
;
7518 if Is_Array_Type
(Typ
) then
7519 if Is_Constrained
(First_Subtype
(Typ
)) then
7520 Desg_Typ
:= First_Subtype
(Typ
);
7522 Desg_Typ
:= Base_Type
(Typ
);
7525 -- Class-wide types of constrained root types
7527 elsif Is_Class_Wide_Type
(Typ
)
7528 and then Has_Discriminants
(Root_Type
(Typ
))
7530 Is_Empty_Elmt_List
(Discriminant_Constraint
(Root_Type
(Typ
)))
7533 Parent_Typ
: Entity_Id
;
7536 -- Climb the parent type chain looking for a non-constrained type
7538 Parent_Typ
:= Root_Type
(Typ
);
7539 while Parent_Typ
/= Etype
(Parent_Typ
)
7540 and then Has_Discriminants
(Parent_Typ
)
7542 Is_Empty_Elmt_List
(Discriminant_Constraint
(Parent_Typ
))
7544 Parent_Typ
:= Etype
(Parent_Typ
);
7547 -- Handle views created for tagged types with unknown
7550 if Is_Underlying_Record_View
(Parent_Typ
) then
7551 Parent_Typ
:= Underlying_Record_View
(Parent_Typ
);
7554 Desg_Typ
:= Class_Wide_Type
(Underlying_Type
(Parent_Typ
));
7564 -- type Ptr_Typ is access all Typ;
7565 -- for Ptr_Typ'Storage_Size use 0;
7568 Make_Full_Type_Declaration
(Loc
,
7569 Defining_Identifier
=> Ptr_Typ
,
7571 Make_Access_To_Object_Definition
(Loc
,
7572 All_Present
=> True,
7573 Subtype_Indication
=> New_Occurrence_Of
(Desg_Typ
, Loc
))),
7575 Make_Attribute_Definition_Clause
(Loc
,
7576 Name
=> New_Occurrence_Of
(Ptr_Typ
, Loc
),
7577 Chars
=> Name_Storage_Size
,
7578 Expression
=> Make_Integer_Literal
(Loc
, 0)));
7580 Obj_Expr
:= Make_Identifier
(Loc
, Name_V
);
7582 -- Unconstrained arrays require special processing in order to retrieve
7583 -- the elements. To achieve this, we have to skip the dope vector which
7584 -- lays in front of the elements and then use a thin pointer to perform
7585 -- the address-to-access conversion.
7587 if Is_Array_Type
(Typ
)
7588 and then not Is_Constrained
(First_Subtype
(Typ
))
7591 Dope_Id
: Entity_Id
;
7594 -- Ensure that Ptr_Typ a thin pointer, generate:
7595 -- for Ptr_Typ'Size use System.Address'Size;
7598 Make_Attribute_Definition_Clause
(Loc
,
7599 Name
=> New_Occurrence_Of
(Ptr_Typ
, Loc
),
7602 Make_Integer_Literal
(Loc
, System_Address_Size
)));
7605 -- Dnn : constant Storage_Offset :=
7606 -- Desg_Typ'Descriptor_Size / Storage_Unit;
7608 Dope_Id
:= Make_Temporary
(Loc
, 'D');
7611 Make_Object_Declaration
(Loc
,
7612 Defining_Identifier
=> Dope_Id
,
7613 Constant_Present
=> True,
7614 Object_Definition
=>
7615 New_Occurrence_Of
(RTE
(RE_Storage_Offset
), Loc
),
7617 Make_Op_Divide
(Loc
,
7619 Make_Attribute_Reference
(Loc
,
7620 Prefix
=> New_Occurrence_Of
(Desg_Typ
, Loc
),
7621 Attribute_Name
=> Name_Descriptor_Size
),
7623 Make_Integer_Literal
(Loc
, System_Storage_Unit
))));
7625 -- Shift the address from the start of the dope vector to the
7626 -- start of the elements:
7630 -- Note that this is done through a wrapper routine since RTSfind
7631 -- cannot retrieve operations with string names of the form "+".
7634 Make_Function_Call
(Loc
,
7636 New_Occurrence_Of
(RTE
(RE_Add_Offset_To_Address
), Loc
),
7637 Parameter_Associations
=> New_List
(
7639 New_Occurrence_Of
(Dope_Id
, Loc
)));
7643 -- Create the block and the finalization call
7646 Make_Block_Statement
(Loc
,
7647 Declarations
=> Decls
,
7649 Handled_Statement_Sequence
=>
7650 Make_Handled_Sequence_Of_Statements
(Loc
,
7651 Statements
=> New_List
(
7654 Make_Explicit_Dereference
(Loc
,
7655 Prefix
=> Unchecked_Convert_To
(Ptr_Typ
, Obj_Expr
)),
7656 Typ
=> Desg_Typ
)))));
7657 end Make_Finalize_Address_Stmts
;
7659 -------------------------------------
7660 -- Make_Handler_For_Ctrl_Operation --
7661 -------------------------------------
7665 -- when E : others =>
7666 -- Raise_From_Controlled_Operation (E);
7671 -- raise Program_Error [finalize raised exception];
7673 -- depending on whether Raise_From_Controlled_Operation is available
7675 function Make_Handler_For_Ctrl_Operation
7676 (Loc
: Source_Ptr
) return Node_Id
7679 -- Choice parameter (for the first case above)
7681 Raise_Node
: Node_Id
;
7682 -- Procedure call or raise statement
7685 -- Standard run-time, .NET/JVM targets: add choice parameter E and pass
7686 -- it to Raise_From_Controlled_Operation so that the original exception
7687 -- name and message can be recorded in the exception message for
7690 if RTE_Available
(RE_Raise_From_Controlled_Operation
) then
7691 E_Occ
:= Make_Defining_Identifier
(Loc
, Name_E
);
7693 Make_Procedure_Call_Statement
(Loc
,
7696 (RTE
(RE_Raise_From_Controlled_Operation
), Loc
),
7697 Parameter_Associations
=> New_List
(
7698 New_Occurrence_Of
(E_Occ
, Loc
)));
7700 -- Restricted run-time: exception messages are not supported
7705 Make_Raise_Program_Error
(Loc
,
7706 Reason
=> PE_Finalize_Raised_Exception
);
7710 Make_Implicit_Exception_Handler
(Loc
,
7711 Exception_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
7712 Choice_Parameter
=> E_Occ
,
7713 Statements
=> New_List
(Raise_Node
));
7714 end Make_Handler_For_Ctrl_Operation
;
7716 --------------------
7717 -- Make_Init_Call --
7718 --------------------
7720 function Make_Init_Call
7722 Typ
: Entity_Id
) return Node_Id
7724 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
7731 -- Deal with the type and object reference. Depending on the context, an
7732 -- object reference may need several conversions.
7734 if Is_Concurrent_Type
(Typ
) then
7736 Utyp
:= Corresponding_Record_Type
(Typ
);
7737 Ref
:= Convert_Concurrent
(Obj_Ref
, Typ
);
7739 elsif Is_Private_Type
(Typ
)
7740 and then Present
(Full_View
(Typ
))
7741 and then Is_Concurrent_Type
(Underlying_Type
(Typ
))
7744 Utyp
:= Corresponding_Record_Type
(Underlying_Type
(Typ
));
7745 Ref
:= Convert_Concurrent
(Obj_Ref
, Underlying_Type
(Typ
));
7753 Set_Assignment_OK
(Ref
);
7755 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7757 -- Deal with untagged derivation of private views
7759 if Is_Untagged_Derivation
(Typ
) and then not Is_Conc
then
7760 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7761 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7763 -- The following is to prevent problems with UC see 1.156 RH ???
7765 Set_Assignment_OK
(Ref
);
7768 -- If the underlying_type is a subtype, then we are dealing with the
7769 -- completion of a private type. We need to access the base type and
7770 -- generate a conversion to it.
7772 if Utyp
/= Base_Type
(Utyp
) then
7773 pragma Assert
(Is_Private_Type
(Typ
));
7774 Utyp
:= Base_Type
(Utyp
);
7775 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7778 -- Select the appropriate version of initialize
7780 if Has_Controlled_Component
(Utyp
) then
7781 Proc
:= TSS
(Utyp
, Deep_Name_Of
(Initialize_Case
));
7783 Proc
:= Find_Prim_Op
(Utyp
, Name_Of
(Initialize_Case
));
7784 Check_Visibly_Controlled
(Initialize_Case
, Typ
, Proc
, Ref
);
7787 -- The object reference may need another conversion depending on the
7788 -- type of the formal and that of the actual.
7790 Ref
:= Convert_View
(Proc
, Ref
);
7793 -- [Deep_]Initialize (Ref);
7796 Make_Procedure_Call_Statement
(Loc
,
7798 New_Occurrence_Of
(Proc
, Loc
),
7799 Parameter_Associations
=> New_List
(Ref
));
7802 ------------------------------
7803 -- Make_Local_Deep_Finalize --
7804 ------------------------------
7806 function Make_Local_Deep_Finalize
7808 Nam
: Entity_Id
) return Node_Id
7810 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7814 Formals
:= New_List
(
7818 Make_Parameter_Specification
(Loc
,
7819 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
7821 Out_Present
=> True,
7822 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
)),
7824 -- F : Boolean := True
7826 Make_Parameter_Specification
(Loc
,
7827 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
7828 Parameter_Type
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
7829 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)));
7831 -- Add the necessary number of counters to represent the initialization
7832 -- state of an object.
7835 Make_Subprogram_Body
(Loc
,
7837 Make_Procedure_Specification
(Loc
,
7838 Defining_Unit_Name
=> Nam
,
7839 Parameter_Specifications
=> Formals
),
7841 Declarations
=> No_List
,
7843 Handled_Statement_Sequence
=>
7844 Make_Handled_Sequence_Of_Statements
(Loc
,
7845 Statements
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
, True)));
7846 end Make_Local_Deep_Finalize
;
7848 ------------------------------------
7849 -- Make_Set_Finalize_Address_Call --
7850 ------------------------------------
7852 function Make_Set_Finalize_Address_Call
7854 Ptr_Typ
: Entity_Id
) return Node_Id
7856 -- It is possible for Ptr_Typ to be a partial view, if the access type
7857 -- is a full view declared in the private part of a nested package, and
7858 -- the finalization actions take place when completing analysis of the
7859 -- enclosing unit. For this reason use Underlying_Type twice below.
7861 Desig_Typ
: constant Entity_Id
:=
7863 (Designated_Type
(Underlying_Type
(Ptr_Typ
)));
7864 Fin_Addr
: constant Entity_Id
:= Finalize_Address
(Desig_Typ
);
7865 Fin_Mas
: constant Entity_Id
:=
7866 Finalization_Master
(Underlying_Type
(Ptr_Typ
));
7869 -- Both the finalization master and primitive Finalize_Address must be
7872 pragma Assert
(Present
(Fin_Addr
) and Present
(Fin_Mas
));
7875 -- Set_Finalize_Address
7876 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
7879 Make_Procedure_Call_Statement
(Loc
,
7881 New_Occurrence_Of
(RTE
(RE_Set_Finalize_Address
), Loc
),
7882 Parameter_Associations
=> New_List
(
7883 New_Occurrence_Of
(Fin_Mas
, Loc
),
7885 Make_Attribute_Reference
(Loc
,
7886 Prefix
=> New_Occurrence_Of
(Fin_Addr
, Loc
),
7887 Attribute_Name
=> Name_Unrestricted_Access
)));
7888 end Make_Set_Finalize_Address_Call
;
7890 --------------------------
7891 -- Make_Transient_Block --
7892 --------------------------
7894 function Make_Transient_Block
7897 Par
: Node_Id
) return Node_Id
7899 Decls
: constant List_Id
:= New_List
;
7900 Instrs
: constant List_Id
:= New_List
(Action
);
7905 -- Case where only secondary stack use is involved
7907 if VM_Target
= No_VM
7908 and then Uses_Sec_Stack
(Current_Scope
)
7909 and then Nkind
(Action
) /= N_Simple_Return_Statement
7910 and then Nkind
(Par
) /= N_Exception_Handler
7916 S
:= Scope
(Current_Scope
);
7918 -- At the outer level, no need to release the sec stack
7920 if S
= Standard_Standard
then
7921 Set_Uses_Sec_Stack
(Current_Scope
, False);
7924 -- In a function, only release the sec stack if the function
7925 -- does not return on the sec stack otherwise the result may
7926 -- be lost. The caller is responsible for releasing.
7928 elsif Ekind
(S
) = E_Function
then
7929 Set_Uses_Sec_Stack
(Current_Scope
, False);
7931 if not Requires_Transient_Scope
(Etype
(S
)) then
7932 Set_Uses_Sec_Stack
(S
, True);
7933 Check_Restriction
(No_Secondary_Stack
, Action
);
7938 -- In a loop or entry we should install a block encompassing
7939 -- all the construct. For now just release right away.
7941 elsif Ekind_In
(S
, E_Entry
, E_Loop
) then
7944 -- In a procedure or a block, we release on exit of the
7945 -- procedure or block. ??? memory leak can be created by
7948 elsif Ekind_In
(S
, E_Block
, E_Procedure
) then
7949 Set_Uses_Sec_Stack
(S
, True);
7950 Check_Restriction
(No_Secondary_Stack
, Action
);
7951 Set_Uses_Sec_Stack
(Current_Scope
, False);
7961 -- Create the transient block. Set the parent now since the block itself
7962 -- is not part of the tree. The current scope is the E_Block entity
7963 -- that has been pushed by Establish_Transient_Scope.
7965 pragma Assert
(Ekind
(Current_Scope
) = E_Block
);
7967 Make_Block_Statement
(Loc
,
7968 Identifier
=> New_Occurrence_Of
(Current_Scope
, Loc
),
7969 Declarations
=> Decls
,
7970 Handled_Statement_Sequence
=>
7971 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Instrs
),
7972 Has_Created_Identifier
=> True);
7973 Set_Parent
(Block
, Par
);
7975 -- Insert actions stuck in the transient scopes as well as all freezing
7976 -- nodes needed by those actions. Do not insert cleanup actions here,
7977 -- they will be transferred to the newly created block.
7979 Insert_Actions_In_Scope_Around
7980 (Action
, Clean
=> False, Manage_SS
=> False);
7982 Insert
:= Prev
(Action
);
7983 if Present
(Insert
) then
7984 Freeze_All
(First_Entity
(Current_Scope
), Insert
);
7987 -- Transfer cleanup actions to the newly created block
7990 Cleanup_Actions
: List_Id
7991 renames Scope_Stack
.Table
(Scope_Stack
.Last
).
7992 Actions_To_Be_Wrapped
(Cleanup
);
7994 Set_Cleanup_Actions
(Block
, Cleanup_Actions
);
7995 Cleanup_Actions
:= No_List
;
7998 -- When the transient scope was established, we pushed the entry for the
7999 -- transient scope onto the scope stack, so that the scope was active
8000 -- for the installation of finalizable entities etc. Now we must remove
8001 -- this entry, since we have constructed a proper block.
8006 end Make_Transient_Block
;
8008 ------------------------
8009 -- Node_To_Be_Wrapped --
8010 ------------------------
8012 function Node_To_Be_Wrapped
return Node_Id
is
8014 return Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
;
8015 end Node_To_Be_Wrapped
;
8017 ----------------------------
8018 -- Set_Node_To_Be_Wrapped --
8019 ----------------------------
8021 procedure Set_Node_To_Be_Wrapped
(N
: Node_Id
) is
8023 Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
:= N
;
8024 end Set_Node_To_Be_Wrapped
;
8026 ----------------------------
8027 -- Store_Actions_In_Scope --
8028 ----------------------------
8030 procedure Store_Actions_In_Scope
(AK
: Scope_Action_Kind
; L
: List_Id
) is
8031 SE
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Scope_Stack
.Last
);
8032 Actions
: List_Id
renames SE
.Actions_To_Be_Wrapped
(AK
);
8035 if No
(Actions
) then
8038 if Is_List_Member
(SE
.Node_To_Be_Wrapped
) then
8039 Set_Parent
(L
, Parent
(SE
.Node_To_Be_Wrapped
));
8041 Set_Parent
(L
, SE
.Node_To_Be_Wrapped
);
8046 elsif AK
= Before
then
8047 Insert_List_After_And_Analyze
(Last
(Actions
), L
);
8050 Insert_List_Before_And_Analyze
(First
(Actions
), L
);
8052 end Store_Actions_In_Scope
;
8054 ----------------------------------
8055 -- Store_After_Actions_In_Scope --
8056 ----------------------------------
8058 procedure Store_After_Actions_In_Scope
(L
: List_Id
) is
8060 Store_Actions_In_Scope
(After
, L
);
8061 end Store_After_Actions_In_Scope
;
8063 -----------------------------------
8064 -- Store_Before_Actions_In_Scope --
8065 -----------------------------------
8067 procedure Store_Before_Actions_In_Scope
(L
: List_Id
) is
8069 Store_Actions_In_Scope
(Before
, L
);
8070 end Store_Before_Actions_In_Scope
;
8072 -----------------------------------
8073 -- Store_Cleanup_Actions_In_Scope --
8074 -----------------------------------
8076 procedure Store_Cleanup_Actions_In_Scope
(L
: List_Id
) is
8078 Store_Actions_In_Scope
(Cleanup
, L
);
8079 end Store_Cleanup_Actions_In_Scope
;
8081 --------------------------------
8082 -- Wrap_Transient_Declaration --
8083 --------------------------------
8085 -- If a transient scope has been established during the processing of the
8086 -- Expression of an Object_Declaration, it is not possible to wrap the
8087 -- declaration into a transient block as usual case, otherwise the object
8088 -- would be itself declared in the wrong scope. Therefore, all entities (if
8089 -- any) defined in the transient block are moved to the proper enclosing
8090 -- scope. Furthermore, if they are controlled variables they are finalized
8091 -- right after the declaration. The finalization list of the transient
8092 -- scope is defined as a renaming of the enclosing one so during their
8093 -- initialization they will be attached to the proper finalization list.
8094 -- For instance, the following declaration :
8096 -- X : Typ := F (G (A), G (B));
8098 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
8099 -- is expanded into :
8101 -- X : Typ := [ complex Expression-Action ];
8102 -- [Deep_]Finalize (_v1);
8103 -- [Deep_]Finalize (_v2);
8105 procedure Wrap_Transient_Declaration
(N
: Node_Id
) is
8110 Curr_S
:= Current_Scope
;
8111 Encl_S
:= Scope
(Curr_S
);
8113 -- Insert all actions inluding cleanup generated while analyzing or
8114 -- expanding the transient context back into the tree. Manage the
8115 -- secondary stack when the object declaration appears in a library
8116 -- level package [body]. This is not needed for .NET/JVM as those do
8117 -- not support the secondary stack.
8119 Insert_Actions_In_Scope_Around
8124 and then Uses_Sec_Stack
(Curr_S
)
8125 and then Nkind
(N
) = N_Object_Declaration
8126 and then Ekind_In
(Encl_S
, E_Package
, E_Package_Body
)
8127 and then Is_Library_Level_Entity
(Encl_S
));
8130 -- Relocate local entities declared within the transient scope to the
8131 -- enclosing scope. This action sets their Is_Public flag accordingly.
8133 Transfer_Entities
(Curr_S
, Encl_S
);
8135 -- Mark the enclosing dynamic scope to ensure that the secondary stack
8136 -- is properly released upon exiting the said scope. This is not needed
8137 -- for .NET/JVM as those do not support the secondary stack.
8139 if VM_Target
= No_VM
and then Uses_Sec_Stack
(Curr_S
) then
8140 Curr_S
:= Enclosing_Dynamic_Scope
(Curr_S
);
8142 -- Do not mark a function that returns on the secondary stack as the
8143 -- reclamation is done by the caller.
8145 if Ekind
(Curr_S
) = E_Function
8146 and then Requires_Transient_Scope
(Etype
(Curr_S
))
8150 -- Otherwise mark the enclosing dynamic scope
8153 Set_Uses_Sec_Stack
(Curr_S
);
8154 Check_Restriction
(No_Secondary_Stack
, N
);
8157 end Wrap_Transient_Declaration
;
8159 -------------------------------
8160 -- Wrap_Transient_Expression --
8161 -------------------------------
8163 procedure Wrap_Transient_Expression
(N
: Node_Id
) is
8164 Loc
: constant Source_Ptr
:= Sloc
(N
);
8165 Expr
: Node_Id
:= Relocate_Node
(N
);
8166 Temp
: constant Entity_Id
:= Make_Temporary
(Loc
, 'E', N
);
8167 Typ
: constant Entity_Id
:= Etype
(N
);
8174 -- M : constant Mark_Id := SS_Mark;
8175 -- procedure Finalizer is ... (See Build_Finalizer)
8178 -- Temp := <Expr>; -- general case
8179 -- Temp := (if <Expr> then True else False); -- boolean case
8185 -- A special case is made for Boolean expressions so that the back-end
8186 -- knows to generate a conditional branch instruction, if running with
8187 -- -fpreserve-control-flow. This ensures that a control flow change
8188 -- signalling the decision outcome occurs before the cleanup actions.
8190 if Opt
.Suppress_Control_Flow_Optimizations
8191 and then Is_Boolean_Type
(Typ
)
8194 Make_If_Expression
(Loc
,
8195 Expressions
=> New_List
(
8197 New_Occurrence_Of
(Standard_True
, Loc
),
8198 New_Occurrence_Of
(Standard_False
, Loc
)));
8201 Insert_Actions
(N
, New_List
(
8202 Make_Object_Declaration
(Loc
,
8203 Defining_Identifier
=> Temp
,
8204 Object_Definition
=> New_Occurrence_Of
(Typ
, Loc
)),
8206 Make_Transient_Block
(Loc
,
8208 Make_Assignment_Statement
(Loc
,
8209 Name
=> New_Occurrence_Of
(Temp
, Loc
),
8210 Expression
=> Expr
),
8211 Par
=> Parent
(N
))));
8213 Rewrite
(N
, New_Occurrence_Of
(Temp
, Loc
));
8214 Analyze_And_Resolve
(N
, Typ
);
8215 end Wrap_Transient_Expression
;
8217 ------------------------------
8218 -- Wrap_Transient_Statement --
8219 ------------------------------
8221 procedure Wrap_Transient_Statement
(N
: Node_Id
) is
8222 Loc
: constant Source_Ptr
:= Sloc
(N
);
8223 New_Stmt
: constant Node_Id
:= Relocate_Node
(N
);
8228 -- M : constant Mark_Id := SS_Mark;
8229 -- procedure Finalizer is ... (See Build_Finalizer)
8239 Make_Transient_Block
(Loc
,
8241 Par
=> Parent
(N
)));
8243 -- With the scope stack back to normal, we can call analyze on the
8244 -- resulting block. At this point, the transient scope is being
8245 -- treated like a perfectly normal scope, so there is nothing
8246 -- special about it.
8248 -- Note: Wrap_Transient_Statement is called with the node already
8249 -- analyzed (i.e. Analyzed (N) is True). This is important, since
8250 -- otherwise we would get a recursive processing of the node when
8251 -- we do this Analyze call.
8254 end Wrap_Transient_Statement
;