1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2013, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License --
17 -- for more details. You should have received a copy of the GNU General --
18 -- Public License distributed with GNAT; see file COPYING3. If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license. --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
24 ------------------------------------------------------------------------------
26 -- This package contains virtually all expansion mechanisms related to
30 with Atree
; use Atree
;
31 with Debug
; use Debug
;
32 with Einfo
; use Einfo
;
33 with Elists
; use Elists
;
34 with Errout
; use Errout
;
35 with Exp_Ch6
; use Exp_Ch6
;
36 with Exp_Ch9
; use Exp_Ch9
;
37 with Exp_Ch11
; use Exp_Ch11
;
38 with Exp_Dbug
; use Exp_Dbug
;
39 with Exp_Dist
; use Exp_Dist
;
40 with Exp_Disp
; use Exp_Disp
;
41 with Exp_Tss
; use Exp_Tss
;
42 with Exp_Util
; use Exp_Util
;
43 with Freeze
; use Freeze
;
45 with Nlists
; use Nlists
;
46 with Nmake
; use Nmake
;
48 with Output
; use Output
;
49 with Restrict
; use Restrict
;
50 with Rident
; use Rident
;
51 with Rtsfind
; use Rtsfind
;
52 with Sinfo
; use Sinfo
;
54 with Sem_Aux
; use Sem_Aux
;
55 with Sem_Ch3
; use Sem_Ch3
;
56 with Sem_Ch7
; use Sem_Ch7
;
57 with Sem_Ch8
; use Sem_Ch8
;
58 with Sem_Res
; use Sem_Res
;
59 with Sem_Util
; use Sem_Util
;
60 with Snames
; use Snames
;
61 with Stand
; use Stand
;
62 with Targparm
; use Targparm
;
63 with Tbuild
; use Tbuild
;
64 with Ttypes
; use Ttypes
;
65 with Uintp
; use Uintp
;
67 package body Exp_Ch7
is
69 --------------------------------
70 -- Transient Scope Management --
71 --------------------------------
73 -- A transient scope is created when temporary objects are created by the
74 -- compiler. These temporary objects are allocated on the secondary stack
75 -- and the transient scope is responsible for finalizing the object when
76 -- appropriate and reclaiming the memory at the right time. The temporary
77 -- objects are generally the objects allocated to store the result of a
78 -- function returning an unconstrained or a tagged value. Expressions
79 -- needing to be wrapped in a transient scope (functions calls returning
80 -- unconstrained or tagged values) may appear in 3 different contexts which
81 -- lead to 3 different kinds of transient scope expansion:
83 -- 1. In a simple statement (procedure call, assignment, ...). In this
84 -- case the instruction is wrapped into a transient block. See
85 -- Wrap_Transient_Statement for details.
87 -- 2. In an expression of a control structure (test in a IF statement,
88 -- expression in a CASE statement, ...). See Wrap_Transient_Expression
91 -- 3. In a expression of an object_declaration. No wrapping is possible
92 -- here, so the finalization actions, if any, are done right after the
93 -- declaration and the secondary stack deallocation is done in the
94 -- proper enclosing scope. See Wrap_Transient_Declaration for details.
96 -- Note about functions returning tagged types: it has been decided to
97 -- always allocate their result in the secondary stack, even though is not
98 -- absolutely mandatory when the tagged type is constrained because the
99 -- caller knows the size of the returned object and thus could allocate the
100 -- result in the primary stack. An exception to this is when the function
101 -- builds its result in place, as is done for functions with inherently
102 -- limited result types for Ada 2005. In that case, certain callers may
103 -- pass the address of a constrained object as the target object for the
106 -- By allocating tagged results in the secondary stack a number of
107 -- implementation difficulties are avoided:
109 -- - If it is a dispatching function call, the computation of the size of
110 -- the result is possible but complex from the outside.
112 -- - If the returned type is controlled, the assignment of the returned
113 -- value to the anonymous object involves an Adjust, and we have no
114 -- easy way to access the anonymous object created by the back end.
116 -- - If the returned type is class-wide, this is an unconstrained type
119 -- Furthermore, the small loss in efficiency which is the result of this
120 -- decision is not such a big deal because functions returning tagged types
121 -- are not as common in practice compared to functions returning access to
124 --------------------------------------------------
125 -- Transient Blocks and Finalization Management --
126 --------------------------------------------------
128 function Find_Node_To_Be_Wrapped
(N
: Node_Id
) return Node_Id
;
129 -- N is a node which may generate a transient scope. Loop over the parent
130 -- pointers of N until it find the appropriate node to wrap. If it returns
131 -- Empty, it means that no transient scope is needed in this context.
133 procedure Insert_Actions_In_Scope_Around
(N
: Node_Id
);
134 -- Insert the before-actions kept in the scope stack before N, and the
135 -- after-actions after N, which must be a member of a list.
137 function Make_Transient_Block
140 Par
: Node_Id
) return Node_Id
;
141 -- Action is a single statement or object declaration. Par is the proper
142 -- parent of the generated block. Create a transient block whose name is
143 -- the current scope and the only handled statement is Action. If Action
144 -- involves controlled objects or secondary stack usage, the corresponding
145 -- cleanup actions are performed at the end of the block.
147 procedure Set_Node_To_Be_Wrapped
(N
: Node_Id
);
148 -- Set the field Node_To_Be_Wrapped of the current scope
150 -- ??? The entire comment needs to be rewritten
151 -- ??? which entire comment?
153 -----------------------------
154 -- Finalization Management --
155 -----------------------------
157 -- This part describe how Initialization/Adjustment/Finalization procedures
158 -- are generated and called. Two cases must be considered, types that are
159 -- Controlled (Is_Controlled flag set) and composite types that contain
160 -- controlled components (Has_Controlled_Component flag set). In the first
161 -- case the procedures to call are the user-defined primitive operations
162 -- Initialize/Adjust/Finalize. In the second case, GNAT generates
163 -- Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
164 -- of calling the former procedures on the controlled components.
166 -- For records with Has_Controlled_Component set, a hidden "controller"
167 -- component is inserted. This controller component contains its own
168 -- finalization list on which all controlled components are attached
169 -- creating an indirection on the upper-level Finalization list. This
170 -- technique facilitates the management of objects whose number of
171 -- controlled components changes during execution. This controller
172 -- component is itself controlled and is attached to the upper-level
173 -- finalization chain. Its adjust primitive is in charge of calling adjust
174 -- on the components and adjusting the finalization pointer to match their
175 -- new location (see a-finali.adb).
177 -- It is not possible to use a similar technique for arrays that have
178 -- Has_Controlled_Component set. In this case, deep procedures are
179 -- generated that call initialize/adjust/finalize + attachment or
180 -- detachment on the finalization list for all component.
182 -- Initialize calls: they are generated for declarations or dynamic
183 -- allocations of Controlled objects with no initial value. They are always
184 -- followed by an attachment to the current Finalization Chain. For the
185 -- dynamic allocation case this the chain attached to the scope of the
186 -- access type definition otherwise, this is the chain of the current
189 -- Adjust Calls: They are generated on 2 occasions: (1) for declarations
190 -- or dynamic allocations of Controlled objects with an initial value.
191 -- (2) after an assignment. In the first case they are followed by an
192 -- attachment to the final chain, in the second case they are not.
194 -- Finalization Calls: They are generated on (1) scope exit, (2)
195 -- assignments, (3) unchecked deallocations. In case (3) they have to
196 -- be detached from the final chain, in case (2) they must not and in
197 -- case (1) this is not important since we are exiting the scope anyway.
201 -- Type extensions will have a new record controller at each derivation
202 -- level containing controlled components. The record controller for
203 -- the parent/ancestor is attached to the finalization list of the
204 -- extension's record controller (i.e. the parent is like a component
205 -- of the extension).
207 -- For types that are both Is_Controlled and Has_Controlled_Components,
208 -- the record controller and the object itself are handled separately.
209 -- It could seem simpler to attach the object at the end of its record
210 -- controller but this would not tackle view conversions properly.
212 -- A classwide type can always potentially have controlled components
213 -- but the record controller of the corresponding actual type may not
214 -- be known at compile time so the dispatch table contains a special
215 -- field that allows to compute the offset of the record controller
216 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
218 -- Here is a simple example of the expansion of a controlled block :
222 -- Y : Controlled := Init;
228 -- Z : R := (C => X);
238 -- _L : System.FI.Finalizable_Ptr;
240 -- procedure _Clean is
243 -- System.FI.Finalize_List (_L);
251 -- Attach_To_Final_List (_L, Finalizable (X), 1);
252 -- at end: Abort_Undefer;
253 -- Y : Controlled := Init;
255 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
263 -- Deep_Initialize (W, _L, 1);
264 -- at end: Abort_Under;
265 -- Z : R := (C => X);
266 -- Deep_Adjust (Z, _L, 1);
270 -- Deep_Finalize (W, False);
271 -- <save W's final pointers>
273 -- <restore W's final pointers>
274 -- Deep_Adjust (W, _L, 0);
279 type Final_Primitives
is
280 (Initialize_Case
, Adjust_Case
, Finalize_Case
, Address_Case
);
281 -- This enumeration type is defined in order to ease sharing code for
282 -- building finalization procedures for composite types.
284 Name_Of
: constant array (Final_Primitives
) of Name_Id
:=
285 (Initialize_Case
=> Name_Initialize
,
286 Adjust_Case
=> Name_Adjust
,
287 Finalize_Case
=> Name_Finalize
,
288 Address_Case
=> Name_Finalize_Address
);
289 Deep_Name_Of
: constant array (Final_Primitives
) of TSS_Name_Type
:=
290 (Initialize_Case
=> TSS_Deep_Initialize
,
291 Adjust_Case
=> TSS_Deep_Adjust
,
292 Finalize_Case
=> TSS_Deep_Finalize
,
293 Address_Case
=> TSS_Finalize_Address
);
295 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
);
296 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
297 -- Has_Controlled_Component set and store them using the TSS mechanism.
299 function Build_Cleanup_Statements
(N
: Node_Id
) return List_Id
;
300 -- Create the clean up calls for an asynchronous call block, task master,
301 -- protected subprogram body, task allocation block or task body. If the
302 -- context does not contain the above constructs, the routine returns an
305 procedure Build_Finalizer
307 Clean_Stmts
: List_Id
;
310 Defer_Abort
: Boolean;
311 Fin_Id
: out Entity_Id
);
312 -- N may denote an accept statement, block, entry body, package body,
313 -- package spec, protected body, subprogram body, or a task body. Create
314 -- a procedure which contains finalization calls for all controlled objects
315 -- declared in the declarative or statement region of N. The calls are
316 -- built in reverse order relative to the original declarations. In the
317 -- case of a task body, the routine delays the creation of the finalizer
318 -- until all statements have been moved to the task body procedure.
319 -- Clean_Stmts may contain additional context-dependent code used to abort
320 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
321 -- Mark_Id is the secondary stack used in the current context or Empty if
322 -- missing. Top_Decls is the list on which the declaration of the finalizer
323 -- is attached in the non-package case. Defer_Abort indicates that the
324 -- statements passed in perform actions that require abort to be deferred,
325 -- such as for task termination. Fin_Id is the finalizer declaration
328 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
);
329 -- N is a construct which contains a handled sequence of statements, Fin_Id
330 -- is the entity of a finalizer. Create an At_End handler which covers the
331 -- statements of N and calls Fin_Id. If the handled statement sequence has
332 -- an exception handler, the statements will be wrapped in a block to avoid
333 -- unwanted interaction with the new At_End handler.
335 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
);
336 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
337 -- Has_Component_Component set and store them using the TSS mechanism.
339 procedure Check_Visibly_Controlled
340 (Prim
: Final_Primitives
;
342 E
: in out Entity_Id
;
343 Cref
: in out Node_Id
);
344 -- The controlled operation declared for a derived type may not be
345 -- overriding, if the controlled operations of the parent type are hidden,
346 -- for example when the parent is a private type whose full view is
347 -- controlled. For other primitive operations we modify the name of the
348 -- operation to indicate that it is not overriding, but this is not
349 -- possible for Initialize, etc. because they have to be retrievable by
350 -- name. Before generating the proper call to one of these operations we
351 -- check whether Typ is known to be controlled at the point of definition.
352 -- If it is not then we must retrieve the hidden operation of the parent
353 -- and use it instead. This is one case that might be solved more cleanly
354 -- once Overriding pragmas or declarations are in place.
356 function Convert_View
359 Ind
: Pos
:= 1) return Node_Id
;
360 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
361 -- argument being passed to it. Ind indicates which formal of procedure
362 -- Proc we are trying to match. This function will, if necessary, generate
363 -- a conversion between the partial and full view of Arg to match the type
364 -- of the formal of Proc, or force a conversion to the class-wide type in
365 -- the case where the operation is abstract.
367 function Enclosing_Function
(E
: Entity_Id
) return Entity_Id
;
368 -- Given an arbitrary entity, traverse the scope chain looking for the
369 -- first enclosing function. Return Empty if no function was found.
371 procedure Expand_Pragma_Initial_Condition
(N
: Node_Id
);
372 -- Subsidiary to the expansion of package specs and bodies. Generate a
373 -- runtime check needed to verify the assumption introduced by pragma
374 -- Initial_Condition. N denotes the package spec or body.
380 For_Parent
: Boolean := False) return Node_Id
;
381 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
382 -- routine [Deep_]Adjust / Finalize and an object parameter, create an
383 -- adjust / finalization call. Flag For_Parent should be set when field
384 -- _parent is being processed.
386 function Make_Deep_Proc
387 (Prim
: Final_Primitives
;
389 Stmts
: List_Id
) return Node_Id
;
390 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
391 -- Deep_Finalize procedures according to the first parameter, these
392 -- procedures operate on the type Typ. The Stmts parameter gives the body
395 function Make_Deep_Array_Body
396 (Prim
: Final_Primitives
;
397 Typ
: Entity_Id
) return List_Id
;
398 -- This function generates the list of statements for implementing
399 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
400 -- the first parameter, these procedures operate on the array type Typ.
402 function Make_Deep_Record_Body
403 (Prim
: Final_Primitives
;
405 Is_Local
: Boolean := False) return List_Id
;
406 -- This function generates the list of statements for implementing
407 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
408 -- the first parameter, these procedures operate on the record type Typ.
409 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
410 -- whether the inner logic should be dictated by state counters.
412 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
;
413 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
414 -- Make_Deep_Record_Body. Generate the following statements:
417 -- type Acc_Typ is access all Typ;
418 -- for Acc_Typ'Storage_Size use 0;
420 -- [Deep_]Finalize (Acc_Typ (V).all);
423 ----------------------------
424 -- Build_Array_Deep_Procs --
425 ----------------------------
427 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
) is
431 (Prim
=> Initialize_Case
,
433 Stmts
=> Make_Deep_Array_Body
(Initialize_Case
, Typ
)));
435 if not Is_Limited_View
(Typ
) then
438 (Prim
=> Adjust_Case
,
440 Stmts
=> Make_Deep_Array_Body
(Adjust_Case
, Typ
)));
443 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
444 -- suppressed since these routine will not be used.
446 if not Restriction_Active
(No_Finalization
) then
449 (Prim
=> Finalize_Case
,
451 Stmts
=> Make_Deep_Array_Body
(Finalize_Case
, Typ
)));
453 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
454 -- .NET do not support address arithmetic and unchecked conversions.
456 if VM_Target
= No_VM
then
459 (Prim
=> Address_Case
,
461 Stmts
=> Make_Deep_Array_Body
(Address_Case
, Typ
)));
464 end Build_Array_Deep_Procs
;
466 ------------------------------
467 -- Build_Cleanup_Statements --
468 ------------------------------
470 function Build_Cleanup_Statements
(N
: Node_Id
) return List_Id
is
471 Is_Asynchronous_Call
: constant Boolean :=
472 Nkind
(N
) = N_Block_Statement
473 and then Is_Asynchronous_Call_Block
(N
);
474 Is_Master
: constant Boolean :=
475 Nkind
(N
) /= N_Entry_Body
476 and then Is_Task_Master
(N
);
477 Is_Protected_Body
: constant Boolean :=
478 Nkind
(N
) = N_Subprogram_Body
479 and then Is_Protected_Subprogram_Body
(N
);
480 Is_Task_Allocation
: constant Boolean :=
481 Nkind
(N
) = N_Block_Statement
482 and then Is_Task_Allocation_Block
(N
);
483 Is_Task_Body
: constant Boolean :=
484 Nkind
(Original_Node
(N
)) = N_Task_Body
;
486 Loc
: constant Source_Ptr
:= Sloc
(N
);
487 Stmts
: constant List_Id
:= New_List
;
491 if Restricted_Profile
then
493 Build_Runtime_Call
(Loc
, RE_Complete_Restricted_Task
));
495 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Task
));
499 if Restriction_Active
(No_Task_Hierarchy
) = False then
500 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Master
));
503 -- Add statements to unlock the protected object parameter and to
504 -- undefer abort. If the context is a protected procedure and the object
505 -- has entries, call the entry service routine.
507 -- NOTE: The generated code references _object, a parameter to the
510 elsif Is_Protected_Body
then
512 Spec
: constant Node_Id
:= Parent
(Corresponding_Spec
(N
));
513 Conc_Typ
: Entity_Id
;
515 Param_Typ
: Entity_Id
;
518 -- Find the _object parameter representing the protected object
520 Param
:= First
(Parameter_Specifications
(Spec
));
522 Param_Typ
:= Etype
(Parameter_Type
(Param
));
524 if Ekind
(Param_Typ
) = E_Record_Type
then
525 Conc_Typ
:= Corresponding_Concurrent_Type
(Param_Typ
);
528 exit when No
(Param
) or else Present
(Conc_Typ
);
532 pragma Assert
(Present
(Param
));
534 -- Historical note: In earlier versions of GNAT, there was code
535 -- at this point to generate stuff to service entry queues. It is
536 -- now abstracted in Build_Protected_Subprogram_Call_Cleanup.
538 Build_Protected_Subprogram_Call_Cleanup
539 (Specification
(N
), Conc_Typ
, Loc
, Stmts
);
542 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
543 -- tasks. Other unactivated tasks are completed by Complete_Task or
546 -- NOTE: The generated code references _chain, a local object
548 elsif Is_Task_Allocation
then
551 -- Expunge_Unactivated_Tasks (_chain);
553 -- where _chain is the list of tasks created by the allocator but not
554 -- yet activated. This list will be empty unless the block completes
558 Make_Procedure_Call_Statement
(Loc
,
561 (RTE
(RE_Expunge_Unactivated_Tasks
), Loc
),
562 Parameter_Associations
=> New_List
(
563 New_Reference_To
(Activation_Chain_Entity
(N
), Loc
))));
565 -- Attempt to cancel an asynchronous entry call whenever the block which
566 -- contains the abortable part is exited.
568 -- NOTE: The generated code references Cnn, a local object
570 elsif Is_Asynchronous_Call
then
572 Cancel_Param
: constant Entity_Id
:=
573 Entry_Cancel_Parameter
(Entity
(Identifier
(N
)));
576 -- If it is of type Communication_Block, this must be a protected
577 -- entry call. Generate:
579 -- if Enqueued (Cancel_Param) then
580 -- Cancel_Protected_Entry_Call (Cancel_Param);
583 if Is_RTE
(Etype
(Cancel_Param
), RE_Communication_Block
) then
585 Make_If_Statement
(Loc
,
587 Make_Function_Call
(Loc
,
589 New_Reference_To
(RTE
(RE_Enqueued
), Loc
),
590 Parameter_Associations
=> New_List
(
591 New_Reference_To
(Cancel_Param
, Loc
))),
593 Then_Statements
=> New_List
(
594 Make_Procedure_Call_Statement
(Loc
,
597 (RTE
(RE_Cancel_Protected_Entry_Call
), Loc
),
598 Parameter_Associations
=> New_List
(
599 New_Reference_To
(Cancel_Param
, Loc
))))));
601 -- Asynchronous delay, generate:
602 -- Cancel_Async_Delay (Cancel_Param);
604 elsif Is_RTE
(Etype
(Cancel_Param
), RE_Delay_Block
) then
606 Make_Procedure_Call_Statement
(Loc
,
608 New_Reference_To
(RTE
(RE_Cancel_Async_Delay
), Loc
),
609 Parameter_Associations
=> New_List
(
610 Make_Attribute_Reference
(Loc
,
612 New_Reference_To
(Cancel_Param
, Loc
),
613 Attribute_Name
=> Name_Unchecked_Access
))));
615 -- Task entry call, generate:
616 -- Cancel_Task_Entry_Call (Cancel_Param);
620 Make_Procedure_Call_Statement
(Loc
,
622 New_Reference_To
(RTE
(RE_Cancel_Task_Entry_Call
), Loc
),
623 Parameter_Associations
=> New_List
(
624 New_Reference_To
(Cancel_Param
, Loc
))));
630 end Build_Cleanup_Statements
;
632 -----------------------------
633 -- Build_Controlling_Procs --
634 -----------------------------
636 procedure Build_Controlling_Procs
(Typ
: Entity_Id
) is
638 if Is_Array_Type
(Typ
) then
639 Build_Array_Deep_Procs
(Typ
);
640 else pragma Assert
(Is_Record_Type
(Typ
));
641 Build_Record_Deep_Procs
(Typ
);
643 end Build_Controlling_Procs
;
645 -----------------------------
646 -- Build_Exception_Handler --
647 -----------------------------
649 function Build_Exception_Handler
650 (Data
: Finalization_Exception_Data
;
651 For_Library
: Boolean := False) return Node_Id
654 Proc_To_Call
: Entity_Id
;
659 pragma Assert
(Present
(Data
.Raised_Id
));
661 if Exception_Extra_Info
662 or else (For_Library
and not Restricted_Profile
)
664 if Exception_Extra_Info
then
668 -- Get_Current_Excep.all
671 Make_Function_Call
(Data
.Loc
,
673 Make_Explicit_Dereference
(Data
.Loc
,
676 (RTE
(RE_Get_Current_Excep
), Data
.Loc
)));
683 Except
:= Make_Null
(Data
.Loc
);
686 if For_Library
and then not Restricted_Profile
then
687 Proc_To_Call
:= RTE
(RE_Save_Library_Occurrence
);
688 Actuals
:= New_List
(Except
);
691 Proc_To_Call
:= RTE
(RE_Save_Occurrence
);
693 -- The dereference occurs only when Exception_Extra_Info is true,
694 -- and therefore Except is not null.
698 New_Reference_To
(Data
.E_Id
, Data
.Loc
),
699 Make_Explicit_Dereference
(Data
.Loc
, Except
));
705 -- if not Raised_Id then
706 -- Raised_Id := True;
708 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
710 -- Save_Library_Occurrence (Get_Current_Excep.all);
715 Make_If_Statement
(Data
.Loc
,
717 Make_Op_Not
(Data
.Loc
,
718 Right_Opnd
=> New_Reference_To
(Data
.Raised_Id
, Data
.Loc
)),
720 Then_Statements
=> New_List
(
721 Make_Assignment_Statement
(Data
.Loc
,
722 Name
=> New_Reference_To
(Data
.Raised_Id
, Data
.Loc
),
723 Expression
=> New_Reference_To
(Standard_True
, Data
.Loc
)),
725 Make_Procedure_Call_Statement
(Data
.Loc
,
727 New_Reference_To
(Proc_To_Call
, Data
.Loc
),
728 Parameter_Associations
=> Actuals
))));
733 -- Raised_Id := True;
736 Make_Assignment_Statement
(Data
.Loc
,
737 Name
=> New_Reference_To
(Data
.Raised_Id
, Data
.Loc
),
738 Expression
=> New_Reference_To
(Standard_True
, Data
.Loc
)));
746 Make_Exception_Handler
(Data
.Loc
,
747 Exception_Choices
=> New_List
(Make_Others_Choice
(Data
.Loc
)),
748 Statements
=> Stmts
);
749 end Build_Exception_Handler
;
751 -------------------------------
752 -- Build_Finalization_Master --
753 -------------------------------
755 procedure Build_Finalization_Master
757 Ins_Node
: Node_Id
:= Empty
;
758 Encl_Scope
: Entity_Id
:= Empty
)
760 Desig_Typ
: constant Entity_Id
:= Directly_Designated_Type
(Typ
);
761 Ptr_Typ
: Entity_Id
:= Root_Type
(Base_Type
(Typ
));
763 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean;
764 -- Determine whether entity E is inside a wrapper package created for
765 -- an instance of Ada.Unchecked_Deallocation.
767 ------------------------------
768 -- In_Deallocation_Instance --
769 ------------------------------
771 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean is
772 Pkg
: constant Entity_Id
:= Scope
(E
);
773 Par
: Node_Id
:= Empty
;
776 if Ekind
(Pkg
) = E_Package
777 and then Present
(Related_Instance
(Pkg
))
778 and then Ekind
(Related_Instance
(Pkg
)) = E_Procedure
780 Par
:= Generic_Parent
(Parent
(Related_Instance
(Pkg
)));
784 and then Chars
(Par
) = Name_Unchecked_Deallocation
785 and then Chars
(Scope
(Par
)) = Name_Ada
786 and then Scope
(Scope
(Par
)) = Standard_Standard
;
790 end In_Deallocation_Instance
;
792 -- Start of processing for Build_Finalization_Master
795 if Is_Private_Type
(Ptr_Typ
)
796 and then Present
(Full_View
(Ptr_Typ
))
798 Ptr_Typ
:= Full_View
(Ptr_Typ
);
801 -- Certain run-time configurations and targets do not provide support
802 -- for controlled types.
804 if Restriction_Active
(No_Finalization
) then
807 -- Do not process C, C++, CIL and Java types since it is assumend that
808 -- the non-Ada side will handle their clean up.
810 elsif Convention
(Desig_Typ
) = Convention_C
811 or else Convention
(Desig_Typ
) = Convention_CIL
812 or else Convention
(Desig_Typ
) = Convention_CPP
813 or else Convention
(Desig_Typ
) = Convention_Java
817 -- Various machinery such as freezing may have already created a
818 -- finalization master.
820 elsif Present
(Finalization_Master
(Ptr_Typ
)) then
823 -- Do not process types that return on the secondary stack
825 elsif Present
(Associated_Storage_Pool
(Ptr_Typ
))
826 and then Is_RTE
(Associated_Storage_Pool
(Ptr_Typ
), RE_SS_Pool
)
830 -- Do not process types which may never allocate an object
832 elsif No_Pool_Assigned
(Ptr_Typ
) then
835 -- Do not process access types coming from Ada.Unchecked_Deallocation
836 -- instances. Even though the designated type may be controlled, the
837 -- access type will never participate in allocation.
839 elsif In_Deallocation_Instance
(Ptr_Typ
) then
842 -- Ignore the general use of anonymous access types unless the context
843 -- requires a finalization master.
845 elsif Ekind
(Ptr_Typ
) = E_Anonymous_Access_Type
846 and then No
(Ins_Node
)
850 -- Do not process non-library access types when restriction No_Nested_
851 -- Finalization is in effect since masters are controlled objects.
853 elsif Restriction_Active
(No_Nested_Finalization
)
854 and then not Is_Library_Level_Entity
(Ptr_Typ
)
858 -- For .NET/JVM targets, allow the processing of access-to-controlled
859 -- types where the designated type is explicitly derived from [Limited_]
862 elsif VM_Target
/= No_VM
863 and then not Is_Controlled
(Desig_Typ
)
867 -- Do not create finalization masters in SPARK mode because they result
868 -- in unwanted expansion.
870 -- More detail would be useful here ???
872 elsif GNATprove_Mode
then
877 Loc
: constant Source_Ptr
:= Sloc
(Ptr_Typ
);
878 Actions
: constant List_Id
:= New_List
;
879 Fin_Mas_Id
: Entity_Id
;
884 -- Fnn : aliased Finalization_Master;
886 -- Source access types use fixed master names since the master is
887 -- inserted in the same source unit only once. The only exception to
888 -- this are instances using the same access type as generic actual.
890 if Comes_From_Source
(Ptr_Typ
)
891 and then not Inside_A_Generic
894 Make_Defining_Identifier
(Loc
,
895 Chars
=> New_External_Name
(Chars
(Ptr_Typ
), "FM"));
897 -- Internally generated access types use temporaries as their names
898 -- due to possible collision with identical names coming from other
902 Fin_Mas_Id
:= Make_Temporary
(Loc
, 'F');
906 Make_Object_Declaration
(Loc
,
907 Defining_Identifier
=> Fin_Mas_Id
,
908 Aliased_Present
=> True,
910 New_Reference_To
(RTE
(RE_Finalization_Master
), Loc
)));
912 -- Storage pool selection and attribute decoration of the generated
913 -- master. Since .NET/JVM compilers do not support pools, this step
916 if VM_Target
= No_VM
then
918 -- If the access type has a user-defined pool, use it as the base
919 -- storage medium for the finalization pool.
921 if Present
(Associated_Storage_Pool
(Ptr_Typ
)) then
922 Pool_Id
:= Associated_Storage_Pool
(Ptr_Typ
);
924 -- The default choice is the global pool
927 Pool_Id
:= Get_Global_Pool_For_Access_Type
(Ptr_Typ
);
928 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
932 -- Set_Base_Pool (Fnn, Pool_Id'Unchecked_Access);
935 Make_Procedure_Call_Statement
(Loc
,
937 New_Reference_To
(RTE
(RE_Set_Base_Pool
), Loc
),
938 Parameter_Associations
=> New_List
(
939 New_Reference_To
(Fin_Mas_Id
, Loc
),
940 Make_Attribute_Reference
(Loc
,
941 Prefix
=> New_Reference_To
(Pool_Id
, Loc
),
942 Attribute_Name
=> Name_Unrestricted_Access
))));
945 Set_Finalization_Master
(Ptr_Typ
, Fin_Mas_Id
);
947 -- A finalization master created for an anonymous access type must be
948 -- inserted before a context-dependent node.
950 if Present
(Ins_Node
) then
951 Push_Scope
(Encl_Scope
);
953 -- Treat use clauses as declarations and insert directly in front
956 if Nkind_In
(Ins_Node
, N_Use_Package_Clause
,
959 Insert_List_Before_And_Analyze
(Ins_Node
, Actions
);
961 Insert_Actions
(Ins_Node
, Actions
);
966 elsif Ekind
(Desig_Typ
) = E_Incomplete_Type
967 and then Has_Completion_In_Body
(Desig_Typ
)
969 Insert_Actions
(Parent
(Ptr_Typ
), Actions
);
971 -- If the designated type is not yet frozen, then append the actions
972 -- to that type's freeze actions. The actions need to be appended to
973 -- whichever type is frozen later, similarly to what Freeze_Type does
974 -- for appending the storage pool declaration for an access type.
975 -- Otherwise, the call to Set_Storage_Pool_Ptr might reference the
976 -- pool object before it's declared. However, it's not clear that
977 -- this is exactly the right test to accomplish that here. ???
979 elsif Present
(Freeze_Node
(Desig_Typ
))
980 and then not Analyzed
(Freeze_Node
(Desig_Typ
))
982 Append_Freeze_Actions
(Desig_Typ
, Actions
);
984 elsif Present
(Freeze_Node
(Ptr_Typ
))
985 and then not Analyzed
(Freeze_Node
(Ptr_Typ
))
987 Append_Freeze_Actions
(Ptr_Typ
, Actions
);
989 -- If there's a pool created locally for the access type, then we
990 -- need to ensure that the master gets created after the pool object,
991 -- because otherwise we can have a forward reference, so we force the
992 -- master actions to be inserted and analyzed after the pool entity.
993 -- Note that both the access type and its designated type may have
994 -- already been frozen and had their freezing actions analyzed at
995 -- this point. (This seems a little unclean.???)
997 elsif VM_Target
= No_VM
998 and then Scope
(Pool_Id
) = Scope
(Ptr_Typ
)
1000 Insert_List_After_And_Analyze
(Parent
(Pool_Id
), Actions
);
1003 Insert_Actions
(Parent
(Ptr_Typ
), Actions
);
1006 end Build_Finalization_Master
;
1008 ---------------------
1009 -- Build_Finalizer --
1010 ---------------------
1012 procedure Build_Finalizer
1014 Clean_Stmts
: List_Id
;
1015 Mark_Id
: Entity_Id
;
1016 Top_Decls
: List_Id
;
1017 Defer_Abort
: Boolean;
1018 Fin_Id
: out Entity_Id
)
1020 Acts_As_Clean
: constant Boolean :=
1023 (Present
(Clean_Stmts
)
1024 and then Is_Non_Empty_List
(Clean_Stmts
));
1025 Exceptions_OK
: constant Boolean :=
1026 not Restriction_Active
(No_Exception_Propagation
);
1027 For_Package_Body
: constant Boolean := Nkind
(N
) = N_Package_Body
;
1028 For_Package_Spec
: constant Boolean := Nkind
(N
) = N_Package_Declaration
;
1029 For_Package
: constant Boolean :=
1030 For_Package_Body
or else For_Package_Spec
;
1031 Loc
: constant Source_Ptr
:= Sloc
(N
);
1033 -- NOTE: Local variable declarations are conservative and do not create
1034 -- structures right from the start. Entities and lists are created once
1035 -- it has been established that N has at least one controlled object.
1037 Components_Built
: Boolean := False;
1038 -- A flag used to avoid double initialization of entities and lists. If
1039 -- the flag is set then the following variables have been initialized:
1045 Counter_Id
: Entity_Id
:= Empty
;
1046 Counter_Val
: Int
:= 0;
1047 -- Name and value of the state counter
1049 Decls
: List_Id
:= No_List
;
1050 -- Declarative region of N (if available). If N is a package declaration
1051 -- Decls denotes the visible declarations.
1053 Finalizer_Data
: Finalization_Exception_Data
;
1054 -- Data for the exception
1056 Finalizer_Decls
: List_Id
:= No_List
;
1057 -- Local variable declarations. This list holds the label declarations
1058 -- of all jump block alternatives as well as the declaration of the
1059 -- local exception occurence and the raised flag:
1060 -- E : Exception_Occurrence;
1061 -- Raised : Boolean := False;
1062 -- L<counter value> : label;
1064 Finalizer_Insert_Nod
: Node_Id
:= Empty
;
1065 -- Insertion point for the finalizer body. Depending on the context
1066 -- (Nkind of N) and the individual grouping of controlled objects, this
1067 -- node may denote a package declaration or body, package instantiation,
1068 -- block statement or a counter update statement.
1070 Finalizer_Stmts
: List_Id
:= No_List
;
1071 -- The statement list of the finalizer body. It contains the following:
1073 -- Abort_Defer; -- Added if abort is allowed
1074 -- <call to Prev_At_End> -- Added if exists
1075 -- <cleanup statements> -- Added if Acts_As_Clean
1076 -- <jump block> -- Added if Has_Ctrl_Objs
1077 -- <finalization statements> -- Added if Has_Ctrl_Objs
1078 -- <stack release> -- Added if Mark_Id exists
1079 -- Abort_Undefer; -- Added if abort is allowed
1081 Has_Ctrl_Objs
: Boolean := False;
1082 -- A general flag which denotes whether N has at least one controlled
1085 Has_Tagged_Types
: Boolean := False;
1086 -- A general flag which indicates whether N has at least one library-
1087 -- level tagged type declaration.
1089 HSS
: Node_Id
:= Empty
;
1090 -- The sequence of statements of N (if available)
1092 Jump_Alts
: List_Id
:= No_List
;
1093 -- Jump block alternatives. Depending on the value of the state counter,
1094 -- the control flow jumps to a sequence of finalization statements. This
1095 -- list contains the following:
1097 -- when <counter value> =>
1098 -- goto L<counter value>;
1100 Jump_Block_Insert_Nod
: Node_Id
:= Empty
;
1101 -- Specific point in the finalizer statements where the jump block is
1104 Last_Top_Level_Ctrl_Construct
: Node_Id
:= Empty
;
1105 -- The last controlled construct encountered when processing the top
1106 -- level lists of N. This can be a nested package, an instantiation or
1107 -- an object declaration.
1109 Prev_At_End
: Entity_Id
:= Empty
;
1110 -- The previous at end procedure of the handled statements block of N
1112 Priv_Decls
: List_Id
:= No_List
;
1113 -- The private declarations of N if N is a package declaration
1115 Spec_Id
: Entity_Id
:= Empty
;
1116 Spec_Decls
: List_Id
:= Top_Decls
;
1117 Stmts
: List_Id
:= No_List
;
1119 Tagged_Type_Stmts
: List_Id
:= No_List
;
1120 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1121 -- tagged types found in N.
1123 -----------------------
1124 -- Local subprograms --
1125 -----------------------
1127 procedure Build_Components
;
1128 -- Create all entites and initialize all lists used in the creation of
1131 procedure Create_Finalizer
;
1132 -- Create the spec and body of the finalizer and insert them in the
1133 -- proper place in the tree depending on the context.
1135 procedure Process_Declarations
1137 Preprocess
: Boolean := False;
1138 Top_Level
: Boolean := False);
1139 -- Inspect a list of declarations or statements which may contain
1140 -- objects that need finalization. When flag Preprocess is set, the
1141 -- routine will simply count the total number of controlled objects in
1142 -- Decls. Flag Top_Level denotes whether the processing is done for
1143 -- objects in nested package declarations or instances.
1145 procedure Process_Object_Declaration
1147 Has_No_Init
: Boolean := False;
1148 Is_Protected
: Boolean := False);
1149 -- Generate all the machinery associated with the finalization of a
1150 -- single object. Flag Has_No_Init is used to denote certain contexts
1151 -- where Decl does not have initialization call(s). Flag Is_Protected
1152 -- is set when Decl denotes a simple protected object.
1154 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
);
1155 -- Generate all the code necessary to unregister the external tag of a
1158 ----------------------
1159 -- Build_Components --
1160 ----------------------
1162 procedure Build_Components
is
1163 Counter_Decl
: Node_Id
;
1164 Counter_Typ
: Entity_Id
;
1165 Counter_Typ_Decl
: Node_Id
;
1168 pragma Assert
(Present
(Decls
));
1170 -- This routine might be invoked several times when dealing with
1171 -- constructs that have two lists (either two declarative regions
1172 -- or declarations and statements). Avoid double initialization.
1174 if Components_Built
then
1178 Components_Built
:= True;
1180 if Has_Ctrl_Objs
then
1182 -- Create entities for the counter, its type, the local exception
1183 -- and the raised flag.
1185 Counter_Id
:= Make_Temporary
(Loc
, 'C');
1186 Counter_Typ
:= Make_Temporary
(Loc
, 'T');
1188 Finalizer_Decls
:= New_List
;
1190 Build_Object_Declarations
1191 (Finalizer_Data
, Finalizer_Decls
, Loc
, For_Package
);
1193 -- Since the total number of controlled objects is always known,
1194 -- build a subtype of Natural with precise bounds. This allows
1195 -- the backend to optimize the case statement. Generate:
1197 -- subtype Tnn is Natural range 0 .. Counter_Val;
1200 Make_Subtype_Declaration
(Loc
,
1201 Defining_Identifier
=> Counter_Typ
,
1202 Subtype_Indication
=>
1203 Make_Subtype_Indication
(Loc
,
1204 Subtype_Mark
=> New_Reference_To
(Standard_Natural
, Loc
),
1206 Make_Range_Constraint
(Loc
,
1210 Make_Integer_Literal
(Loc
, Uint_0
),
1212 Make_Integer_Literal
(Loc
, Counter_Val
)))));
1214 -- Generate the declaration of the counter itself:
1216 -- Counter : Integer := 0;
1219 Make_Object_Declaration
(Loc
,
1220 Defining_Identifier
=> Counter_Id
,
1221 Object_Definition
=> New_Reference_To
(Counter_Typ
, Loc
),
1222 Expression
=> Make_Integer_Literal
(Loc
, 0));
1224 -- Set the type of the counter explicitly to prevent errors when
1225 -- examining object declarations later on.
1227 Set_Etype
(Counter_Id
, Counter_Typ
);
1229 -- The counter and its type are inserted before the source
1230 -- declarations of N.
1232 Prepend_To
(Decls
, Counter_Decl
);
1233 Prepend_To
(Decls
, Counter_Typ_Decl
);
1235 -- The counter and its associated type must be manually analized
1236 -- since N has already been analyzed. Use the scope of the spec
1237 -- when inserting in a package.
1240 Push_Scope
(Spec_Id
);
1241 Analyze
(Counter_Typ_Decl
);
1242 Analyze
(Counter_Decl
);
1246 Analyze
(Counter_Typ_Decl
);
1247 Analyze
(Counter_Decl
);
1250 Jump_Alts
:= New_List
;
1253 -- If the context requires additional clean up, the finalization
1254 -- machinery is added after the clean up code.
1256 if Acts_As_Clean
then
1257 Finalizer_Stmts
:= Clean_Stmts
;
1258 Jump_Block_Insert_Nod
:= Last
(Finalizer_Stmts
);
1260 Finalizer_Stmts
:= New_List
;
1263 if Has_Tagged_Types
then
1264 Tagged_Type_Stmts
:= New_List
;
1266 end Build_Components
;
1268 ----------------------
1269 -- Create_Finalizer --
1270 ----------------------
1272 procedure Create_Finalizer
is
1273 Body_Id
: Entity_Id
;
1276 Jump_Block
: Node_Id
;
1278 Label_Id
: Entity_Id
;
1280 function New_Finalizer_Name
return Name_Id
;
1281 -- Create a fully qualified name of a package spec or body finalizer.
1282 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1284 ------------------------
1285 -- New_Finalizer_Name --
1286 ------------------------
1288 function New_Finalizer_Name
return Name_Id
is
1289 procedure New_Finalizer_Name
(Id
: Entity_Id
);
1290 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1291 -- has a non-standard scope, process the scope first.
1293 ------------------------
1294 -- New_Finalizer_Name --
1295 ------------------------
1297 procedure New_Finalizer_Name
(Id
: Entity_Id
) is
1299 if Scope
(Id
) = Standard_Standard
then
1300 Get_Name_String
(Chars
(Id
));
1303 New_Finalizer_Name
(Scope
(Id
));
1304 Add_Str_To_Name_Buffer
("__");
1305 Add_Str_To_Name_Buffer
(Get_Name_String
(Chars
(Id
)));
1307 end New_Finalizer_Name
;
1309 -- Start of processing for New_Finalizer_Name
1312 -- Create the fully qualified name of the enclosing scope
1314 New_Finalizer_Name
(Spec_Id
);
1317 -- __finalize_[spec|body]
1319 Add_Str_To_Name_Buffer
("__finalize_");
1321 if For_Package_Spec
then
1322 Add_Str_To_Name_Buffer
("spec");
1324 Add_Str_To_Name_Buffer
("body");
1328 end New_Finalizer_Name
;
1330 -- Start of processing for Create_Finalizer
1333 -- Step 1: Creation of the finalizer name
1335 -- Packages must use a distinct name for their finalizers since the
1336 -- binder will have to generate calls to them by name. The name is
1337 -- of the following form:
1339 -- xx__yy__finalize_[spec|body]
1342 Fin_Id
:= Make_Defining_Identifier
(Loc
, New_Finalizer_Name
);
1343 Set_Has_Qualified_Name
(Fin_Id
);
1344 Set_Has_Fully_Qualified_Name
(Fin_Id
);
1346 -- The default name is _finalizer
1350 Make_Defining_Identifier
(Loc
,
1351 Chars
=> New_External_Name
(Name_uFinalizer
));
1353 -- The visibility semantics of AT_END handlers force a strange
1354 -- separation of spec and body for stack-related finalizers:
1356 -- declare : Enclosing_Scope
1357 -- procedure _finalizer;
1359 -- <controlled objects>
1360 -- procedure _finalizer is
1366 -- Both spec and body are within the same construct and scope, but
1367 -- the body is part of the handled sequence of statements. This
1368 -- placement confuses the elaboration mechanism on targets where
1369 -- AT_END handlers are expanded into "when all others" handlers:
1372 -- when all others =>
1373 -- _finalizer; -- appears to require elab checks
1378 -- Since the compiler guarantees that the body of a _finalizer is
1379 -- always inserted in the same construct where the AT_END handler
1380 -- resides, there is no need for elaboration checks.
1382 Set_Kill_Elaboration_Checks
(Fin_Id
);
1385 -- Step 2: Creation of the finalizer specification
1388 -- procedure Fin_Id;
1391 Make_Subprogram_Declaration
(Loc
,
1393 Make_Procedure_Specification
(Loc
,
1394 Defining_Unit_Name
=> Fin_Id
));
1396 -- Step 3: Creation of the finalizer body
1398 if Has_Ctrl_Objs
then
1400 -- Add L0, the default destination to the jump block
1402 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
1403 Set_Entity
(Label_Id
,
1404 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
1405 Label
:= Make_Label
(Loc
, Label_Id
);
1410 Prepend_To
(Finalizer_Decls
,
1411 Make_Implicit_Label_Declaration
(Loc
,
1412 Defining_Identifier
=> Entity
(Label_Id
),
1413 Label_Construct
=> Label
));
1419 Append_To
(Jump_Alts
,
1420 Make_Case_Statement_Alternative
(Loc
,
1421 Discrete_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
1422 Statements
=> New_List
(
1423 Make_Goto_Statement
(Loc
,
1424 Name
=> New_Reference_To
(Entity
(Label_Id
), Loc
)))));
1429 Append_To
(Finalizer_Stmts
, Label
);
1431 -- Create the jump block which controls the finalization flow
1432 -- depending on the value of the state counter.
1435 Make_Case_Statement
(Loc
,
1436 Expression
=> Make_Identifier
(Loc
, Chars
(Counter_Id
)),
1437 Alternatives
=> Jump_Alts
);
1440 and then Present
(Jump_Block_Insert_Nod
)
1442 Insert_After
(Jump_Block_Insert_Nod
, Jump_Block
);
1444 Prepend_To
(Finalizer_Stmts
, Jump_Block
);
1448 -- Add the library-level tagged type unregistration machinery before
1449 -- the jump block circuitry. This ensures that external tags will be
1450 -- removed even if a finalization exception occurs at some point.
1452 if Has_Tagged_Types
then
1453 Prepend_List_To
(Finalizer_Stmts
, Tagged_Type_Stmts
);
1456 -- Add a call to the previous At_End handler if it exists. The call
1457 -- must always precede the jump block.
1459 if Present
(Prev_At_End
) then
1460 Prepend_To
(Finalizer_Stmts
,
1461 Make_Procedure_Call_Statement
(Loc
, Prev_At_End
));
1463 -- Clear the At_End handler since we have already generated the
1464 -- proper replacement call for it.
1466 Set_At_End_Proc
(HSS
, Empty
);
1469 -- Release the secondary stack mark
1471 if Present
(Mark_Id
) then
1472 Append_To
(Finalizer_Stmts
,
1473 Make_Procedure_Call_Statement
(Loc
,
1475 New_Reference_To
(RTE
(RE_SS_Release
), Loc
),
1476 Parameter_Associations
=> New_List
(
1477 New_Reference_To
(Mark_Id
, Loc
))));
1480 -- Protect the statements with abort defer/undefer. This is only when
1481 -- aborts are allowed and the clean up statements require deferral or
1482 -- there are controlled objects to be finalized.
1486 (Defer_Abort
or else Has_Ctrl_Objs
)
1488 Prepend_To
(Finalizer_Stmts
,
1489 Make_Procedure_Call_Statement
(Loc
,
1490 Name
=> New_Reference_To
(RTE
(RE_Abort_Defer
), Loc
)));
1492 Append_To
(Finalizer_Stmts
,
1493 Make_Procedure_Call_Statement
(Loc
,
1494 Name
=> New_Reference_To
(RTE
(RE_Abort_Undefer
), Loc
)));
1497 -- The local exception does not need to be reraised for library-level
1498 -- finalizers. Note that this action must be carried out after object
1499 -- clean up, secondary stack release and abort undeferral. Generate:
1501 -- if Raised and then not Abort then
1502 -- Raise_From_Controlled_Operation (E);
1506 and then Exceptions_OK
1507 and then not For_Package
1509 Append_To
(Finalizer_Stmts
,
1510 Build_Raise_Statement
(Finalizer_Data
));
1514 -- procedure Fin_Id is
1515 -- Abort : constant Boolean := Triggered_By_Abort;
1517 -- Abort : constant Boolean := False; -- no abort
1519 -- E : Exception_Occurrence; -- All added if flag
1520 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1526 -- Abort_Defer; -- Added if abort is allowed
1527 -- <call to Prev_At_End> -- Added if exists
1528 -- <cleanup statements> -- Added if Acts_As_Clean
1529 -- <jump block> -- Added if Has_Ctrl_Objs
1530 -- <finalization statements> -- Added if Has_Ctrl_Objs
1531 -- <stack release> -- Added if Mark_Id exists
1532 -- Abort_Undefer; -- Added if abort is allowed
1533 -- <exception propagation> -- Added if Has_Ctrl_Objs
1536 -- Create the body of the finalizer
1538 Body_Id
:= Make_Defining_Identifier
(Loc
, Chars
(Fin_Id
));
1541 Set_Has_Qualified_Name
(Body_Id
);
1542 Set_Has_Fully_Qualified_Name
(Body_Id
);
1546 Make_Subprogram_Body
(Loc
,
1548 Make_Procedure_Specification
(Loc
,
1549 Defining_Unit_Name
=> Body_Id
),
1550 Declarations
=> Finalizer_Decls
,
1551 Handled_Statement_Sequence
=>
1552 Make_Handled_Sequence_Of_Statements
(Loc
, Finalizer_Stmts
));
1554 -- Step 4: Spec and body insertion, analysis
1558 -- If the package spec has private declarations, the finalizer
1559 -- body must be added to the end of the list in order to have
1560 -- visibility of all private controlled objects.
1562 if For_Package_Spec
then
1563 if Present
(Priv_Decls
) then
1564 Append_To
(Priv_Decls
, Fin_Spec
);
1565 Append_To
(Priv_Decls
, Fin_Body
);
1567 Append_To
(Decls
, Fin_Spec
);
1568 Append_To
(Decls
, Fin_Body
);
1571 -- For package bodies, both the finalizer spec and body are
1572 -- inserted at the end of the package declarations.
1575 Append_To
(Decls
, Fin_Spec
);
1576 Append_To
(Decls
, Fin_Body
);
1579 -- Push the name of the package
1581 Push_Scope
(Spec_Id
);
1589 -- Create the spec for the finalizer. The At_End handler must be
1590 -- able to call the body which resides in a nested structure.
1594 -- procedure Fin_Id; -- Spec
1596 -- <objects and possibly statements>
1597 -- procedure Fin_Id is ... -- Body
1600 -- Fin_Id; -- At_End handler
1603 pragma Assert
(Present
(Spec_Decls
));
1605 Append_To
(Spec_Decls
, Fin_Spec
);
1608 -- When the finalizer acts solely as a clean up routine, the body
1609 -- is inserted right after the spec.
1612 and then not Has_Ctrl_Objs
1614 Insert_After
(Fin_Spec
, Fin_Body
);
1616 -- In all other cases the body is inserted after either:
1618 -- 1) The counter update statement of the last controlled object
1619 -- 2) The last top level nested controlled package
1620 -- 3) The last top level controlled instantiation
1623 -- Manually freeze the spec. This is somewhat of a hack because
1624 -- a subprogram is frozen when its body is seen and the freeze
1625 -- node appears right before the body. However, in this case,
1626 -- the spec must be frozen earlier since the At_End handler
1627 -- must be able to call it.
1630 -- procedure Fin_Id; -- Spec
1631 -- [Fin_Id] -- Freeze node
1635 -- Fin_Id; -- At_End handler
1638 Ensure_Freeze_Node
(Fin_Id
);
1639 Insert_After
(Fin_Spec
, Freeze_Node
(Fin_Id
));
1640 Set_Is_Frozen
(Fin_Id
);
1642 -- In the case where the last construct to contain a controlled
1643 -- object is either a nested package, an instantiation or a
1644 -- freeze node, the body must be inserted directly after the
1647 if Nkind_In
(Last_Top_Level_Ctrl_Construct
,
1649 N_Package_Declaration
,
1652 Finalizer_Insert_Nod
:= Last_Top_Level_Ctrl_Construct
;
1655 Insert_After
(Finalizer_Insert_Nod
, Fin_Body
);
1660 end Create_Finalizer
;
1662 --------------------------
1663 -- Process_Declarations --
1664 --------------------------
1666 procedure Process_Declarations
1668 Preprocess
: Boolean := False;
1669 Top_Level
: Boolean := False)
1674 Obj_Typ
: Entity_Id
;
1675 Pack_Id
: Entity_Id
;
1679 Old_Counter_Val
: Int
;
1680 -- This variable is used to determine whether a nested package or
1681 -- instance contains at least one controlled object.
1683 procedure Processing_Actions
1684 (Has_No_Init
: Boolean := False;
1685 Is_Protected
: Boolean := False);
1686 -- Depending on the mode of operation of Process_Declarations, either
1687 -- increment the controlled object counter, set the controlled object
1688 -- flag and store the last top level construct or process the current
1689 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1690 -- the current declaration may not have initialization proc(s). Flag
1691 -- Is_Protected should be set when the current declaration denotes a
1692 -- simple protected object.
1694 ------------------------
1695 -- Processing_Actions --
1696 ------------------------
1698 procedure Processing_Actions
1699 (Has_No_Init
: Boolean := False;
1700 Is_Protected
: Boolean := False)
1703 -- Library-level tagged type
1705 if Nkind
(Decl
) = N_Full_Type_Declaration
then
1707 Has_Tagged_Types
:= True;
1710 and then No
(Last_Top_Level_Ctrl_Construct
)
1712 Last_Top_Level_Ctrl_Construct
:= Decl
;
1716 Process_Tagged_Type_Declaration
(Decl
);
1719 -- Controlled object declaration
1723 Counter_Val
:= Counter_Val
+ 1;
1724 Has_Ctrl_Objs
:= True;
1727 and then No
(Last_Top_Level_Ctrl_Construct
)
1729 Last_Top_Level_Ctrl_Construct
:= Decl
;
1733 Process_Object_Declaration
(Decl
, Has_No_Init
, Is_Protected
);
1736 end Processing_Actions
;
1738 -- Start of processing for Process_Declarations
1741 if No
(Decls
) or else Is_Empty_List
(Decls
) then
1745 -- Process all declarations in reverse order
1747 Decl
:= Last_Non_Pragma
(Decls
);
1748 while Present
(Decl
) loop
1750 -- Library-level tagged types
1752 if Nkind
(Decl
) = N_Full_Type_Declaration
then
1753 Typ
:= Defining_Identifier
(Decl
);
1755 if Is_Tagged_Type
(Typ
)
1756 and then Is_Library_Level_Entity
(Typ
)
1757 and then Convention
(Typ
) = Convention_Ada
1758 and then Present
(Access_Disp_Table
(Typ
))
1759 and then RTE_Available
(RE_Register_Tag
)
1760 and then not No_Run_Time_Mode
1761 and then not Is_Abstract_Type
(Typ
)
1766 -- Regular object declarations
1768 elsif Nkind
(Decl
) = N_Object_Declaration
then
1769 Obj_Id
:= Defining_Identifier
(Decl
);
1770 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
1771 Expr
:= Expression
(Decl
);
1773 -- Bypass any form of processing for objects which have their
1774 -- finalization disabled. This applies only to objects at the
1778 and then Finalize_Storage_Only
(Obj_Typ
)
1782 -- Transient variables are treated separately in order to
1783 -- minimize the size of the generated code. For details, see
1784 -- Process_Transient_Objects.
1786 elsif Is_Processed_Transient
(Obj_Id
) then
1789 -- The object is of the form:
1790 -- Obj : Typ [:= Expr];
1792 -- Do not process the incomplete view of a deferred constant.
1793 -- Do not consider tag-to-class-wide conversions.
1795 elsif not Is_Imported
(Obj_Id
)
1796 and then Needs_Finalization
(Obj_Typ
)
1797 and then not (Ekind
(Obj_Id
) = E_Constant
1798 and then not Has_Completion
(Obj_Id
))
1799 and then not Is_Tag_To_Class_Wide_Conversion
(Obj_Id
)
1803 -- The object is of the form:
1804 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
1806 -- Obj : Access_Typ :=
1807 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
1809 elsif Is_Access_Type
(Obj_Typ
)
1810 and then Needs_Finalization
1811 (Available_View
(Designated_Type
(Obj_Typ
)))
1812 and then Present
(Expr
)
1814 (Is_Secondary_Stack_BIP_Func_Call
(Expr
)
1816 (Is_Non_BIP_Func_Call
(Expr
)
1817 and then not Is_Related_To_Func_Return
(Obj_Id
)))
1819 Processing_Actions
(Has_No_Init
=> True);
1821 -- Processing for "hook" objects generated for controlled
1822 -- transients declared inside an Expression_With_Actions.
1824 elsif Is_Access_Type
(Obj_Typ
)
1825 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1826 and then Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
1827 N_Object_Declaration
1828 and then Is_Finalizable_Transient
1829 (Status_Flag_Or_Transient_Decl
(Obj_Id
), Decl
)
1831 Processing_Actions
(Has_No_Init
=> True);
1833 -- Process intermediate results of an if expression with one
1834 -- of the alternatives using a controlled function call.
1836 elsif Is_Access_Type
(Obj_Typ
)
1837 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1838 and then Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
1839 N_Defining_Identifier
1840 and then Present
(Expr
)
1841 and then Nkind
(Expr
) = N_Null
1843 Processing_Actions
(Has_No_Init
=> True);
1845 -- Simple protected objects which use type System.Tasking.
1846 -- Protected_Objects.Protection to manage their locks should
1847 -- be treated as controlled since they require manual cleanup.
1848 -- The only exception is illustrated in the following example:
1851 -- type Ctrl is new Controlled ...
1852 -- procedure Finalize (Obj : in out Ctrl);
1856 -- package body Pkg is
1857 -- protected Prot is
1858 -- procedure Do_Something (Obj : in out Ctrl);
1861 -- protected body Prot is
1862 -- procedure Do_Something (Obj : in out Ctrl) is ...
1865 -- procedure Finalize (Obj : in out Ctrl) is
1867 -- Prot.Do_Something (Obj);
1871 -- Since for the most part entities in package bodies depend on
1872 -- those in package specs, Prot's lock should be cleaned up
1873 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
1874 -- This act however attempts to invoke Do_Something and fails
1875 -- because the lock has disappeared.
1877 elsif Ekind
(Obj_Id
) = E_Variable
1878 and then not In_Library_Level_Package_Body
(Obj_Id
)
1880 (Is_Simple_Protected_Type
(Obj_Typ
)
1881 or else Has_Simple_Protected_Object
(Obj_Typ
))
1883 Processing_Actions
(Is_Protected
=> True);
1886 -- Specific cases of object renamings
1888 elsif Nkind
(Decl
) = N_Object_Renaming_Declaration
then
1889 Obj_Id
:= Defining_Identifier
(Decl
);
1890 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
1892 -- Bypass any form of processing for objects which have their
1893 -- finalization disabled. This applies only to objects at the
1897 and then Finalize_Storage_Only
(Obj_Typ
)
1901 -- Return object of a build-in-place function. This case is
1902 -- recognized and marked by the expansion of an extended return
1903 -- statement (see Expand_N_Extended_Return_Statement).
1905 elsif Needs_Finalization
(Obj_Typ
)
1906 and then Is_Return_Object
(Obj_Id
)
1907 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
1909 Processing_Actions
(Has_No_Init
=> True);
1911 -- Detect a case where a source object has been initialized by
1912 -- a controlled function call or another object which was later
1913 -- rewritten as a class-wide conversion of Ada.Tags.Displace.
1915 -- Obj1 : CW_Type := Src_Obj;
1916 -- Obj2 : CW_Type := Function_Call (...);
1918 -- Obj1 : CW_Type renames (... Ada.Tags.Displace (Src_Obj));
1919 -- Tmp : ... := Function_Call (...)'reference;
1920 -- Obj2 : CW_Type renames (... Ada.Tags.Displace (Tmp));
1922 elsif Is_Displacement_Of_Object_Or_Function_Result
(Obj_Id
) then
1923 Processing_Actions
(Has_No_Init
=> True);
1926 -- Inspect the freeze node of an access-to-controlled type and
1927 -- look for a delayed finalization master. This case arises when
1928 -- the freeze actions are inserted at a later time than the
1929 -- expansion of the context. Since Build_Finalizer is never called
1930 -- on a single construct twice, the master will be ultimately
1931 -- left out and never finalized. This is also needed for freeze
1932 -- actions of designated types themselves, since in some cases the
1933 -- finalization master is associated with a designated type's
1934 -- freeze node rather than that of the access type (see handling
1935 -- for freeze actions in Build_Finalization_Master).
1937 elsif Nkind
(Decl
) = N_Freeze_Entity
1938 and then Present
(Actions
(Decl
))
1940 Typ
:= Entity
(Decl
);
1942 if (Is_Access_Type
(Typ
)
1943 and then not Is_Access_Subprogram_Type
(Typ
)
1944 and then Needs_Finalization
1945 (Available_View
(Designated_Type
(Typ
))))
1946 or else (Is_Type
(Typ
) and then Needs_Finalization
(Typ
))
1948 Old_Counter_Val
:= Counter_Val
;
1950 -- Freeze nodes are considered to be identical to packages
1951 -- and blocks in terms of nesting. The difference is that
1952 -- a finalization master created inside the freeze node is
1953 -- at the same nesting level as the node itself.
1955 Process_Declarations
(Actions
(Decl
), Preprocess
);
1957 -- The freeze node contains a finalization master
1961 and then No
(Last_Top_Level_Ctrl_Construct
)
1962 and then Counter_Val
> Old_Counter_Val
1964 Last_Top_Level_Ctrl_Construct
:= Decl
;
1968 -- Nested package declarations, avoid generics
1970 elsif Nkind
(Decl
) = N_Package_Declaration
then
1971 Spec
:= Specification
(Decl
);
1972 Pack_Id
:= Defining_Unit_Name
(Spec
);
1974 if Nkind
(Pack_Id
) = N_Defining_Program_Unit_Name
then
1975 Pack_Id
:= Defining_Identifier
(Pack_Id
);
1978 if Ekind
(Pack_Id
) /= E_Generic_Package
then
1979 Old_Counter_Val
:= Counter_Val
;
1980 Process_Declarations
1981 (Private_Declarations
(Spec
), Preprocess
);
1982 Process_Declarations
1983 (Visible_Declarations
(Spec
), Preprocess
);
1985 -- Either the visible or the private declarations contain a
1986 -- controlled object. The nested package declaration is the
1987 -- last such construct.
1991 and then No
(Last_Top_Level_Ctrl_Construct
)
1992 and then Counter_Val
> Old_Counter_Val
1994 Last_Top_Level_Ctrl_Construct
:= Decl
;
1998 -- Nested package bodies, avoid generics
2000 elsif Nkind
(Decl
) = N_Package_Body
then
2001 Spec
:= Corresponding_Spec
(Decl
);
2003 if Ekind
(Spec
) /= E_Generic_Package
then
2004 Old_Counter_Val
:= Counter_Val
;
2005 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2007 -- The nested package body is the last construct to contain
2008 -- a controlled object.
2012 and then No
(Last_Top_Level_Ctrl_Construct
)
2013 and then Counter_Val
> Old_Counter_Val
2015 Last_Top_Level_Ctrl_Construct
:= Decl
;
2019 -- Handle a rare case caused by a controlled transient variable
2020 -- created as part of a record init proc. The variable is wrapped
2021 -- in a block, but the block is not associated with a transient
2024 elsif Nkind
(Decl
) = N_Block_Statement
2025 and then Inside_Init_Proc
2027 Old_Counter_Val
:= Counter_Val
;
2029 if Present
(Handled_Statement_Sequence
(Decl
)) then
2030 Process_Declarations
2031 (Statements
(Handled_Statement_Sequence
(Decl
)),
2035 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2037 -- Either the declaration or statement list of the block has a
2038 -- controlled object.
2042 and then No
(Last_Top_Level_Ctrl_Construct
)
2043 and then Counter_Val
> Old_Counter_Val
2045 Last_Top_Level_Ctrl_Construct
:= Decl
;
2048 -- Handle the case where the original context has been wrapped in
2049 -- a block to avoid interference between exception handlers and
2050 -- At_End handlers. Treat the block as transparent and process its
2053 elsif Nkind
(Decl
) = N_Block_Statement
2054 and then Is_Finalization_Wrapper
(Decl
)
2056 if Present
(Handled_Statement_Sequence
(Decl
)) then
2057 Process_Declarations
2058 (Statements
(Handled_Statement_Sequence
(Decl
)),
2062 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2065 Prev_Non_Pragma
(Decl
);
2067 end Process_Declarations
;
2069 --------------------------------
2070 -- Process_Object_Declaration --
2071 --------------------------------
2073 procedure Process_Object_Declaration
2075 Has_No_Init
: Boolean := False;
2076 Is_Protected
: Boolean := False)
2078 Obj_Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2079 Loc
: constant Source_Ptr
:= Sloc
(Decl
);
2081 Count_Ins
: Node_Id
;
2083 Fin_Stmts
: List_Id
;
2086 Label_Id
: Entity_Id
;
2088 Obj_Typ
: Entity_Id
;
2090 function Build_BIP_Cleanup_Stmts
(Func_Id
: Entity_Id
) return Node_Id
;
2091 -- Once it has been established that the current object is in fact a
2092 -- return object of build-in-place function Func_Id, generate the
2093 -- following cleanup code:
2095 -- if BIPallocfrom > Secondary_Stack'Pos
2096 -- and then BIPfinalizationmaster /= null
2099 -- type Ptr_Typ is access Obj_Typ;
2100 -- for Ptr_Typ'Storage_Pool
2101 -- use Base_Pool (BIPfinalizationmaster);
2103 -- Free (Ptr_Typ (Temp));
2107 -- Obj_Typ is the type of the current object, Temp is the original
2108 -- allocation which Obj_Id renames.
2110 procedure Find_Last_Init
2113 Last_Init
: out Node_Id
;
2114 Body_Insert
: out Node_Id
);
2115 -- An object declaration has at least one and at most two init calls:
2116 -- that of the type and the user-defined initialize. Given an object
2117 -- declaration, Last_Init denotes the last initialization call which
2118 -- follows the declaration. Body_Insert denotes the place where the
2119 -- finalizer body could be potentially inserted.
2121 -----------------------------
2122 -- Build_BIP_Cleanup_Stmts --
2123 -----------------------------
2125 function Build_BIP_Cleanup_Stmts
2126 (Func_Id
: Entity_Id
) return Node_Id
2128 Decls
: constant List_Id
:= New_List
;
2129 Fin_Mas_Id
: constant Entity_Id
:=
2130 Build_In_Place_Formal
2131 (Func_Id
, BIP_Finalization_Master
);
2132 Obj_Typ
: constant Entity_Id
:= Etype
(Func_Id
);
2133 Temp_Id
: constant Entity_Id
:=
2134 Entity
(Prefix
(Name
(Parent
(Obj_Id
))));
2138 Free_Stmt
: Node_Id
;
2139 Pool_Id
: Entity_Id
;
2140 Ptr_Typ
: Entity_Id
;
2144 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2146 Pool_Id
:= Make_Temporary
(Loc
, 'P');
2149 Make_Object_Renaming_Declaration
(Loc
,
2150 Defining_Identifier
=> Pool_Id
,
2152 New_Reference_To
(RTE
(RE_Root_Storage_Pool
), Loc
),
2154 Make_Explicit_Dereference
(Loc
,
2156 Make_Function_Call
(Loc
,
2158 New_Reference_To
(RTE
(RE_Base_Pool
), Loc
),
2159 Parameter_Associations
=> New_List
(
2160 Make_Explicit_Dereference
(Loc
,
2161 Prefix
=> New_Reference_To
(Fin_Mas_Id
, Loc
)))))));
2163 -- Create an access type which uses the storage pool of the
2164 -- caller's finalization master.
2167 -- type Ptr_Typ is access Obj_Typ;
2169 Ptr_Typ
:= Make_Temporary
(Loc
, 'P');
2172 Make_Full_Type_Declaration
(Loc
,
2173 Defining_Identifier
=> Ptr_Typ
,
2175 Make_Access_To_Object_Definition
(Loc
,
2176 Subtype_Indication
=> New_Reference_To
(Obj_Typ
, Loc
))));
2178 -- Perform minor decoration in order to set the master and the
2179 -- storage pool attributes.
2181 Set_Ekind
(Ptr_Typ
, E_Access_Type
);
2182 Set_Finalization_Master
(Ptr_Typ
, Fin_Mas_Id
);
2183 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
2185 -- Create an explicit free statement. Note that the free uses the
2186 -- caller's pool expressed as a renaming.
2189 Make_Free_Statement
(Loc
,
2191 Unchecked_Convert_To
(Ptr_Typ
,
2192 New_Reference_To
(Temp_Id
, Loc
)));
2194 Set_Storage_Pool
(Free_Stmt
, Pool_Id
);
2196 -- Create a block to house the dummy type and the instantiation as
2197 -- well as to perform the cleanup the temporary.
2203 -- Free (Ptr_Typ (Temp_Id));
2207 Make_Block_Statement
(Loc
,
2208 Declarations
=> Decls
,
2209 Handled_Statement_Sequence
=>
2210 Make_Handled_Sequence_Of_Statements
(Loc
,
2211 Statements
=> New_List
(Free_Stmt
)));
2214 -- if BIPfinalizationmaster /= null then
2218 Left_Opnd
=> New_Reference_To
(Fin_Mas_Id
, Loc
),
2219 Right_Opnd
=> Make_Null
(Loc
));
2221 -- For constrained or tagged results escalate the condition to
2222 -- include the allocation format. Generate:
2224 -- if BIPallocform > Secondary_Stack'Pos
2225 -- and then BIPfinalizationmaster /= null
2228 if not Is_Constrained
(Obj_Typ
)
2229 or else Is_Tagged_Type
(Obj_Typ
)
2232 Alloc
: constant Entity_Id
:=
2233 Build_In_Place_Formal
(Func_Id
, BIP_Alloc_Form
);
2239 Left_Opnd
=> New_Reference_To
(Alloc
, Loc
),
2241 Make_Integer_Literal
(Loc
,
2243 (BIP_Allocation_Form
'Pos (Secondary_Stack
)))),
2245 Right_Opnd
=> Cond
);
2255 Make_If_Statement
(Loc
,
2257 Then_Statements
=> New_List
(Free_Blk
));
2258 end Build_BIP_Cleanup_Stmts
;
2260 --------------------
2261 -- Find_Last_Init --
2262 --------------------
2264 procedure Find_Last_Init
2267 Last_Init
: out Node_Id
;
2268 Body_Insert
: out Node_Id
)
2270 Nod_1
: Node_Id
:= Empty
;
2271 Nod_2
: Node_Id
:= Empty
;
2274 function Is_Init_Call
2276 Typ
: Entity_Id
) return Boolean;
2277 -- Given an arbitrary node, determine whether N is a procedure
2278 -- call and if it is, try to match the name of the call with the
2279 -- [Deep_]Initialize proc of Typ.
2281 function Next_Suitable_Statement
(Stmt
: Node_Id
) return Node_Id
;
2282 -- Given a statement which is part of a list, return the next
2283 -- real statement while skipping over dynamic elab checks.
2289 function Is_Init_Call
2291 Typ
: Entity_Id
) return Boolean
2294 -- A call to [Deep_]Initialize is always direct
2296 if Nkind
(N
) = N_Procedure_Call_Statement
2297 and then Nkind
(Name
(N
)) = N_Identifier
2300 Call_Ent
: constant Entity_Id
:= Entity
(Name
(N
));
2301 Deep_Init
: constant Entity_Id
:=
2302 TSS
(Typ
, TSS_Deep_Initialize
);
2303 Init
: Entity_Id
:= Empty
;
2306 -- A type may have controlled components but not be
2309 if Is_Controlled
(Typ
) then
2310 Init
:= Find_Prim_Op
(Typ
, Name_Initialize
);
2312 if Present
(Init
) then
2313 Init
:= Ultimate_Alias
(Init
);
2318 (Present
(Deep_Init
) and then Call_Ent
= Deep_Init
)
2320 (Present
(Init
) and then Call_Ent
= Init
);
2327 -----------------------------
2328 -- Next_Suitable_Statement --
2329 -----------------------------
2331 function Next_Suitable_Statement
(Stmt
: Node_Id
) return Node_Id
is
2332 Result
: Node_Id
:= Next
(Stmt
);
2335 -- Skip over access-before-elaboration checks
2337 if Dynamic_Elaboration_Checks
2338 and then Nkind
(Result
) = N_Raise_Program_Error
2340 Result
:= Next
(Result
);
2344 end Next_Suitable_Statement
;
2346 -- Start of processing for Find_Last_Init
2350 Body_Insert
:= Empty
;
2352 -- Object renamings and objects associated with controlled
2353 -- function results do not have initialization calls.
2359 if Is_Concurrent_Type
(Typ
) then
2360 Utyp
:= Corresponding_Record_Type
(Typ
);
2365 if Is_Private_Type
(Utyp
)
2366 and then Present
(Full_View
(Utyp
))
2368 Utyp
:= Full_View
(Utyp
);
2371 -- The init procedures are arranged as follows:
2373 -- Object : Controlled_Type;
2374 -- Controlled_TypeIP (Object);
2375 -- [[Deep_]Initialize (Object);]
2377 -- where the user-defined initialize may be optional or may appear
2378 -- inside a block when abort deferral is needed.
2380 Nod_1
:= Next_Suitable_Statement
(Decl
);
2381 if Present
(Nod_1
) then
2382 Nod_2
:= Next_Suitable_Statement
(Nod_1
);
2384 -- The statement following an object declaration is always a
2385 -- call to the type init proc.
2390 -- Optional user-defined init or deep init processing
2392 if Present
(Nod_2
) then
2394 -- The statement following the type init proc may be a block
2395 -- statement in cases where abort deferral is required.
2397 if Nkind
(Nod_2
) = N_Block_Statement
then
2399 HSS
: constant Node_Id
:=
2400 Handled_Statement_Sequence
(Nod_2
);
2405 and then Present
(Statements
(HSS
))
2407 Stmt
:= First
(Statements
(HSS
));
2409 -- Examine individual block statements and locate the
2410 -- call to [Deep_]Initialze.
2412 while Present
(Stmt
) loop
2413 if Is_Init_Call
(Stmt
, Utyp
) then
2415 Body_Insert
:= Nod_2
;
2425 elsif Is_Init_Call
(Nod_2
, Utyp
) then
2431 -- Start of processing for Process_Object_Declaration
2434 Obj_Ref
:= New_Reference_To
(Obj_Id
, Loc
);
2435 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
2437 -- Handle access types
2439 if Is_Access_Type
(Obj_Typ
) then
2440 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
2441 Obj_Typ
:= Directly_Designated_Type
(Obj_Typ
);
2444 Set_Etype
(Obj_Ref
, Obj_Typ
);
2446 -- Set a new value for the state counter and insert the statement
2447 -- after the object declaration. Generate:
2449 -- Counter := <value>;
2452 Make_Assignment_Statement
(Loc
,
2453 Name
=> New_Reference_To
(Counter_Id
, Loc
),
2454 Expression
=> Make_Integer_Literal
(Loc
, Counter_Val
));
2456 -- Insert the counter after all initialization has been done. The
2457 -- place of insertion depends on the context. If an object is being
2458 -- initialized via an aggregate, then the counter must be inserted
2459 -- after the last aggregate assignment.
2461 if Ekind
(Obj_Id
) = E_Variable
2462 and then Present
(Last_Aggregate_Assignment
(Obj_Id
))
2464 Count_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
2467 -- In all other cases the counter is inserted after the last call to
2468 -- either [Deep_]Initialize or the type specific init proc.
2471 Find_Last_Init
(Decl
, Obj_Typ
, Count_Ins
, Body_Ins
);
2474 Insert_After
(Count_Ins
, Inc_Decl
);
2477 -- If the current declaration is the last in the list, the finalizer
2478 -- body needs to be inserted after the set counter statement for the
2479 -- current object declaration. This is complicated by the fact that
2480 -- the set counter statement may appear in abort deferred block. In
2481 -- that case, the proper insertion place is after the block.
2483 if No
(Finalizer_Insert_Nod
) then
2485 -- Insertion after an abort deffered block
2487 if Present
(Body_Ins
) then
2488 Finalizer_Insert_Nod
:= Body_Ins
;
2490 Finalizer_Insert_Nod
:= Inc_Decl
;
2494 -- Create the associated label with this object, generate:
2496 -- L<counter> : label;
2499 Make_Identifier
(Loc
, New_External_Name
('L', Counter_Val
));
2501 (Label_Id
, Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
2502 Label
:= Make_Label
(Loc
, Label_Id
);
2504 Prepend_To
(Finalizer_Decls
,
2505 Make_Implicit_Label_Declaration
(Loc
,
2506 Defining_Identifier
=> Entity
(Label_Id
),
2507 Label_Construct
=> Label
));
2509 -- Create the associated jump with this object, generate:
2511 -- when <counter> =>
2514 Prepend_To
(Jump_Alts
,
2515 Make_Case_Statement_Alternative
(Loc
,
2516 Discrete_Choices
=> New_List
(
2517 Make_Integer_Literal
(Loc
, Counter_Val
)),
2518 Statements
=> New_List
(
2519 Make_Goto_Statement
(Loc
,
2520 Name
=> New_Reference_To
(Entity
(Label_Id
), Loc
)))));
2522 -- Insert the jump destination, generate:
2526 Append_To
(Finalizer_Stmts
, Label
);
2528 -- Processing for simple protected objects. Such objects require
2529 -- manual finalization of their lock managers.
2531 if Is_Protected
then
2532 Fin_Stmts
:= No_List
;
2534 if Is_Simple_Protected_Type
(Obj_Typ
) then
2535 Fin_Call
:= Cleanup_Protected_Object
(Decl
, Obj_Ref
);
2537 if Present
(Fin_Call
) then
2538 Fin_Stmts
:= New_List
(Fin_Call
);
2541 elsif Has_Simple_Protected_Object
(Obj_Typ
) then
2542 if Is_Record_Type
(Obj_Typ
) then
2543 Fin_Stmts
:= Cleanup_Record
(Decl
, Obj_Ref
, Obj_Typ
);
2544 elsif Is_Array_Type
(Obj_Typ
) then
2545 Fin_Stmts
:= Cleanup_Array
(Decl
, Obj_Ref
, Obj_Typ
);
2551 -- System.Tasking.Protected_Objects.Finalize_Protection
2559 if Present
(Fin_Stmts
) then
2560 Append_To
(Finalizer_Stmts
,
2561 Make_Block_Statement
(Loc
,
2562 Handled_Statement_Sequence
=>
2563 Make_Handled_Sequence_Of_Statements
(Loc
,
2564 Statements
=> Fin_Stmts
,
2566 Exception_Handlers
=> New_List
(
2567 Make_Exception_Handler
(Loc
,
2568 Exception_Choices
=> New_List
(
2569 Make_Others_Choice
(Loc
)),
2571 Statements
=> New_List
(
2572 Make_Null_Statement
(Loc
)))))));
2575 -- Processing for regular controlled objects
2579 -- [Deep_]Finalize (Obj); -- No_Exception_Propagation
2581 -- begin -- Exception handlers allowed
2582 -- [Deep_]Finalize (Obj);
2585 -- when Id : others =>
2586 -- if not Raised then
2588 -- Save_Occurrence (E, Id);
2597 -- For CodePeer, the exception handlers normally generated here
2598 -- generate complex flowgraphs which result in capacity problems.
2599 -- Omitting these handlers for CodePeer is justified as follows:
2601 -- If a handler is dead, then omitting it is surely ok
2603 -- If a handler is live, then CodePeer should flag the
2604 -- potentially-exception-raising construct that causes it
2605 -- to be live. That is what we are interested in, not what
2606 -- happens after the exception is raised.
2608 if Exceptions_OK
and not CodePeer_Mode
then
2609 Fin_Stmts
:= New_List
(
2610 Make_Block_Statement
(Loc
,
2611 Handled_Statement_Sequence
=>
2612 Make_Handled_Sequence_Of_Statements
(Loc
,
2613 Statements
=> New_List
(Fin_Call
),
2615 Exception_Handlers
=> New_List
(
2616 Build_Exception_Handler
2617 (Finalizer_Data
, For_Package
)))));
2619 -- When exception handlers are prohibited, the finalization call
2620 -- appears unprotected. Any exception raised during finalization
2621 -- will bypass the circuitry which ensures the cleanup of all
2622 -- remaining objects.
2625 Fin_Stmts
:= New_List
(Fin_Call
);
2628 -- If we are dealing with a return object of a build-in-place
2629 -- function, generate the following cleanup statements:
2631 -- if BIPallocfrom > Secondary_Stack'Pos
2632 -- and then BIPfinalizationmaster /= null
2635 -- type Ptr_Typ is access Obj_Typ;
2636 -- for Ptr_Typ'Storage_Pool use
2637 -- Base_Pool (BIPfinalizationmaster.all).all;
2639 -- Free (Ptr_Typ (Temp));
2643 -- The generated code effectively detaches the temporary from the
2644 -- caller finalization master and deallocates the object. This is
2645 -- disabled on .NET/JVM because pools are not supported.
2647 if VM_Target
= No_VM
and then Is_Return_Object
(Obj_Id
) then
2649 Func_Id
: constant Entity_Id
:= Enclosing_Function
(Obj_Id
);
2651 if Is_Build_In_Place_Function
(Func_Id
)
2652 and then Needs_BIP_Finalization_Master
(Func_Id
)
2654 Append_To
(Fin_Stmts
, Build_BIP_Cleanup_Stmts
(Func_Id
));
2659 if Ekind_In
(Obj_Id
, E_Constant
, E_Variable
)
2660 and then Present
(Status_Flag_Or_Transient_Decl
(Obj_Id
))
2662 -- Temporaries created for the purpose of "exporting" a
2663 -- controlled transient out of an Expression_With_Actions (EWA)
2664 -- need guards. The following illustrates the usage of such
2667 -- Access_Typ : access [all] Obj_Typ;
2668 -- Temp : Access_Typ := null;
2669 -- <Counter> := ...;
2672 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
2673 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
2675 -- Temp := Ctrl_Trans'Unchecked_Access;
2678 -- The finalization machinery does not process EWA nodes as
2679 -- this may lead to premature finalization of expressions. Note
2680 -- that Temp is marked as being properly initialized regardless
2681 -- of whether the initialization of Ctrl_Trans succeeded. Since
2682 -- a failed initialization may leave Temp with a value of null,
2683 -- add a guard to handle this case:
2685 -- if Obj /= null then
2686 -- <object finalization statements>
2689 if Nkind
(Status_Flag_Or_Transient_Decl
(Obj_Id
)) =
2690 N_Object_Declaration
2692 Fin_Stmts
:= New_List
(
2693 Make_If_Statement
(Loc
,
2696 Left_Opnd
=> New_Reference_To
(Obj_Id
, Loc
),
2697 Right_Opnd
=> Make_Null
(Loc
)),
2698 Then_Statements
=> Fin_Stmts
));
2700 -- Return objects use a flag to aid in processing their
2701 -- potential finalization when the enclosing function fails
2702 -- to return properly. Generate:
2705 -- <object finalization statements>
2709 Fin_Stmts
:= New_List
(
2710 Make_If_Statement
(Loc
,
2715 (Status_Flag_Or_Transient_Decl
(Obj_Id
), Loc
)),
2717 Then_Statements
=> Fin_Stmts
));
2722 Append_List_To
(Finalizer_Stmts
, Fin_Stmts
);
2724 -- Since the declarations are examined in reverse, the state counter
2725 -- must be decremented in order to keep with the true position of
2728 Counter_Val
:= Counter_Val
- 1;
2729 end Process_Object_Declaration
;
2731 -------------------------------------
2732 -- Process_Tagged_Type_Declaration --
2733 -------------------------------------
2735 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
) is
2736 Typ
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2737 DT_Ptr
: constant Entity_Id
:=
2738 Node
(First_Elmt
(Access_Disp_Table
(Typ
)));
2741 -- Ada.Tags.Unregister_Tag (<Typ>P);
2743 Append_To
(Tagged_Type_Stmts
,
2744 Make_Procedure_Call_Statement
(Loc
,
2746 New_Reference_To
(RTE
(RE_Unregister_Tag
), Loc
),
2747 Parameter_Associations
=> New_List
(
2748 New_Reference_To
(DT_Ptr
, Loc
))));
2749 end Process_Tagged_Type_Declaration
;
2751 -- Start of processing for Build_Finalizer
2756 -- Do not perform this expansion in SPARK mode because it is not
2759 if GNATprove_Mode
then
2763 -- Step 1: Extract all lists which may contain controlled objects or
2764 -- library-level tagged types.
2766 if For_Package_Spec
then
2767 Decls
:= Visible_Declarations
(Specification
(N
));
2768 Priv_Decls
:= Private_Declarations
(Specification
(N
));
2770 -- Retrieve the package spec id
2772 Spec_Id
:= Defining_Unit_Name
(Specification
(N
));
2774 if Nkind
(Spec_Id
) = N_Defining_Program_Unit_Name
then
2775 Spec_Id
:= Defining_Identifier
(Spec_Id
);
2778 -- Accept statement, block, entry body, package body, protected body,
2779 -- subprogram body or task body.
2782 Decls
:= Declarations
(N
);
2783 HSS
:= Handled_Statement_Sequence
(N
);
2785 if Present
(HSS
) then
2786 if Present
(Statements
(HSS
)) then
2787 Stmts
:= Statements
(HSS
);
2790 if Present
(At_End_Proc
(HSS
)) then
2791 Prev_At_End
:= At_End_Proc
(HSS
);
2795 -- Retrieve the package spec id for package bodies
2797 if For_Package_Body
then
2798 Spec_Id
:= Corresponding_Spec
(N
);
2802 -- Do not process nested packages since those are handled by the
2803 -- enclosing scope's finalizer. Do not process non-expanded package
2804 -- instantiations since those will be re-analyzed and re-expanded.
2808 (not Is_Library_Level_Entity
(Spec_Id
)
2810 -- Nested packages are considered to be library level entities,
2811 -- but do not need to be processed separately. True library level
2812 -- packages have a scope value of 1.
2814 or else Scope_Depth_Value
(Spec_Id
) /= Uint_1
2815 or else (Is_Generic_Instance
(Spec_Id
)
2816 and then Package_Instantiation
(Spec_Id
) /= N
))
2821 -- Step 2: Object [pre]processing
2825 -- Preprocess the visible declarations now in order to obtain the
2826 -- correct number of controlled object by the time the private
2827 -- declarations are processed.
2829 Process_Declarations
(Decls
, Preprocess
=> True, Top_Level
=> True);
2831 -- From all the possible contexts, only package specifications may
2832 -- have private declarations.
2834 if For_Package_Spec
then
2835 Process_Declarations
2836 (Priv_Decls
, Preprocess
=> True, Top_Level
=> True);
2839 -- The current context may lack controlled objects, but require some
2840 -- other form of completion (task termination for instance). In such
2841 -- cases, the finalizer must be created and carry the additional
2844 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
2848 -- The preprocessing has determined that the context has controlled
2849 -- objects or library-level tagged types.
2851 if Has_Ctrl_Objs
or Has_Tagged_Types
then
2853 -- Private declarations are processed first in order to preserve
2854 -- possible dependencies between public and private objects.
2856 if For_Package_Spec
then
2857 Process_Declarations
(Priv_Decls
);
2860 Process_Declarations
(Decls
);
2866 -- Preprocess both declarations and statements
2868 Process_Declarations
(Decls
, Preprocess
=> True, Top_Level
=> True);
2869 Process_Declarations
(Stmts
, Preprocess
=> True, Top_Level
=> True);
2871 -- At this point it is known that N has controlled objects. Ensure
2872 -- that N has a declarative list since the finalizer spec will be
2875 if Has_Ctrl_Objs
and then No
(Decls
) then
2876 Set_Declarations
(N
, New_List
);
2877 Decls
:= Declarations
(N
);
2878 Spec_Decls
:= Decls
;
2881 -- The current context may lack controlled objects, but require some
2882 -- other form of completion (task termination for instance). In such
2883 -- cases, the finalizer must be created and carry the additional
2886 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
2890 if Has_Ctrl_Objs
or Has_Tagged_Types
then
2891 Process_Declarations
(Stmts
);
2892 Process_Declarations
(Decls
);
2896 -- Step 3: Finalizer creation
2898 if Acts_As_Clean
or Has_Ctrl_Objs
or Has_Tagged_Types
then
2901 end Build_Finalizer
;
2903 --------------------------
2904 -- Build_Finalizer_Call --
2905 --------------------------
2907 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
) is
2908 Is_Prot_Body
: constant Boolean :=
2909 Nkind
(N
) = N_Subprogram_Body
2910 and then Is_Protected_Subprogram_Body
(N
);
2911 -- Determine whether N denotes the protected version of a subprogram
2912 -- which belongs to a protected type.
2914 Loc
: constant Source_Ptr
:= Sloc
(N
);
2918 -- Do not perform this expansion in SPARK mode because we do not create
2919 -- finalizers in the first place.
2921 if GNATprove_Mode
then
2925 -- The At_End handler should have been assimilated by the finalizer
2927 HSS
:= Handled_Statement_Sequence
(N
);
2928 pragma Assert
(No
(At_End_Proc
(HSS
)));
2930 -- If the construct to be cleaned up is a protected subprogram body, the
2931 -- finalizer call needs to be associated with the block which wraps the
2932 -- unprotected version of the subprogram. The following illustrates this
2935 -- procedure Prot_SubpP is
2936 -- procedure finalizer is
2938 -- Service_Entries (Prot_Obj);
2945 -- Prot_SubpN (Prot_Obj);
2951 if Is_Prot_Body
then
2952 HSS
:= Handled_Statement_Sequence
(Last
(Statements
(HSS
)));
2954 -- An At_End handler and regular exception handlers cannot coexist in
2955 -- the same statement sequence. Wrap the original statements in a block.
2957 elsif Present
(Exception_Handlers
(HSS
)) then
2959 End_Lab
: constant Node_Id
:= End_Label
(HSS
);
2964 Make_Block_Statement
(Loc
, Handled_Statement_Sequence
=> HSS
);
2966 Set_Handled_Statement_Sequence
(N
,
2967 Make_Handled_Sequence_Of_Statements
(Loc
, New_List
(Block
)));
2969 HSS
:= Handled_Statement_Sequence
(N
);
2970 Set_End_Label
(HSS
, End_Lab
);
2974 Set_At_End_Proc
(HSS
, New_Reference_To
(Fin_Id
, Loc
));
2976 Analyze
(At_End_Proc
(HSS
));
2977 Expand_At_End_Handler
(HSS
, Empty
);
2978 end Build_Finalizer_Call
;
2980 ---------------------
2981 -- Build_Late_Proc --
2982 ---------------------
2984 procedure Build_Late_Proc
(Typ
: Entity_Id
; Nam
: Name_Id
) is
2986 for Final_Prim
in Name_Of
'Range loop
2987 if Name_Of
(Final_Prim
) = Nam
then
2990 (Prim
=> Final_Prim
,
2992 Stmts
=> Make_Deep_Record_Body
(Final_Prim
, Typ
)));
2995 end Build_Late_Proc
;
2997 -------------------------------
2998 -- Build_Object_Declarations --
2999 -------------------------------
3001 procedure Build_Object_Declarations
3002 (Data
: out Finalization_Exception_Data
;
3005 For_Package
: Boolean := False)
3011 pragma Assert
(Decls
/= No_List
);
3013 -- Always set the proper location as it may be needed even when
3014 -- exception propagation is forbidden.
3018 if Restriction_Active
(No_Exception_Propagation
) then
3019 Data
.Abort_Id
:= Empty
;
3021 Data
.Raised_Id
:= Empty
;
3025 Data
.Raised_Id
:= Make_Temporary
(Loc
, 'R');
3027 -- In certain scenarios, finalization can be triggered by an abort. If
3028 -- the finalization itself fails and raises an exception, the resulting
3029 -- Program_Error must be supressed and replaced by an abort signal. In
3030 -- order to detect this scenario, save the state of entry into the
3031 -- finalization code.
3033 -- No need to do this for VM case, since VM version of Ada.Exceptions
3034 -- does not include routine Raise_From_Controlled_Operation which is the
3035 -- the sole user of flag Abort.
3037 -- This is not needed for library-level finalizers as they are called
3038 -- by the environment task and cannot be aborted.
3041 and then VM_Target
= No_VM
3042 and then not For_Package
3044 Data
.Abort_Id
:= Make_Temporary
(Loc
, 'A');
3046 A_Expr
:= New_Reference_To
(RTE
(RE_Triggered_By_Abort
), Loc
);
3050 -- Abort_Id : constant Boolean := <A_Expr>;
3053 Make_Object_Declaration
(Loc
,
3054 Defining_Identifier
=> Data
.Abort_Id
,
3055 Constant_Present
=> True,
3056 Object_Definition
=> New_Reference_To
(Standard_Boolean
, Loc
),
3057 Expression
=> A_Expr
));
3060 -- No abort, .NET/JVM or library-level finalizers
3062 Data
.Abort_Id
:= Empty
;
3065 if Exception_Extra_Info
then
3066 Data
.E_Id
:= Make_Temporary
(Loc
, 'E');
3070 -- E_Id : Exception_Occurrence;
3073 Make_Object_Declaration
(Loc
,
3074 Defining_Identifier
=> Data
.E_Id
,
3075 Object_Definition
=>
3076 New_Reference_To
(RTE
(RE_Exception_Occurrence
), Loc
));
3077 Set_No_Initialization
(E_Decl
);
3079 Append_To
(Decls
, E_Decl
);
3087 -- Raised_Id : Boolean := False;
3090 Make_Object_Declaration
(Loc
,
3091 Defining_Identifier
=> Data
.Raised_Id
,
3092 Object_Definition
=> New_Reference_To
(Standard_Boolean
, Loc
),
3093 Expression
=> New_Reference_To
(Standard_False
, Loc
)));
3094 end Build_Object_Declarations
;
3096 ---------------------------
3097 -- Build_Raise_Statement --
3098 ---------------------------
3100 function Build_Raise_Statement
3101 (Data
: Finalization_Exception_Data
) return Node_Id
3107 -- Standard run-time and .NET/JVM targets use the specialized routine
3108 -- Raise_From_Controlled_Operation.
3110 if Exception_Extra_Info
3111 and then RTE_Available
(RE_Raise_From_Controlled_Operation
)
3114 Make_Procedure_Call_Statement
(Data
.Loc
,
3117 (RTE
(RE_Raise_From_Controlled_Operation
), Data
.Loc
),
3118 Parameter_Associations
=>
3119 New_List
(New_Reference_To
(Data
.E_Id
, Data
.Loc
)));
3121 -- Restricted run-time: exception messages are not supported and hence
3122 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3127 Make_Raise_Program_Error
(Data
.Loc
,
3128 Reason
=> PE_Finalize_Raised_Exception
);
3133 -- Raised_Id and then not Abort_Id
3137 Expr
:= New_Reference_To
(Data
.Raised_Id
, Data
.Loc
);
3139 if Present
(Data
.Abort_Id
) then
3140 Expr
:= Make_And_Then
(Data
.Loc
,
3143 Make_Op_Not
(Data
.Loc
,
3144 Right_Opnd
=> New_Reference_To
(Data
.Abort_Id
, Data
.Loc
)));
3149 -- if Raised_Id and then not Abort_Id then
3150 -- Raise_From_Controlled_Operation (E_Id);
3152 -- raise Program_Error; -- restricted runtime
3156 Make_If_Statement
(Data
.Loc
,
3158 Then_Statements
=> New_List
(Stmt
));
3159 end Build_Raise_Statement
;
3161 -----------------------------
3162 -- Build_Record_Deep_Procs --
3163 -----------------------------
3165 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
) is
3169 (Prim
=> Initialize_Case
,
3171 Stmts
=> Make_Deep_Record_Body
(Initialize_Case
, Typ
)));
3173 if not Is_Limited_View
(Typ
) then
3176 (Prim
=> Adjust_Case
,
3178 Stmts
=> Make_Deep_Record_Body
(Adjust_Case
, Typ
)));
3181 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3182 -- suppressed since these routine will not be used.
3184 if not Restriction_Active
(No_Finalization
) then
3187 (Prim
=> Finalize_Case
,
3189 Stmts
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
)));
3191 -- Create TSS primitive Finalize_Address for non-VM targets. JVM and
3192 -- .NET do not support address arithmetic and unchecked conversions.
3194 if VM_Target
= No_VM
then
3197 (Prim
=> Address_Case
,
3199 Stmts
=> Make_Deep_Record_Body
(Address_Case
, Typ
)));
3202 end Build_Record_Deep_Procs
;
3208 function Cleanup_Array
3211 Typ
: Entity_Id
) return List_Id
3213 Loc
: constant Source_Ptr
:= Sloc
(N
);
3214 Index_List
: constant List_Id
:= New_List
;
3216 function Free_Component
return List_Id
;
3217 -- Generate the code to finalize the task or protected subcomponents
3218 -- of a single component of the array.
3220 function Free_One_Dimension
(Dim
: Int
) return List_Id
;
3221 -- Generate a loop over one dimension of the array
3223 --------------------
3224 -- Free_Component --
3225 --------------------
3227 function Free_Component
return List_Id
is
3228 Stmts
: List_Id
:= New_List
;
3230 C_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
3233 -- Component type is known to contain tasks or protected objects
3236 Make_Indexed_Component
(Loc
,
3237 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3238 Expressions
=> Index_List
);
3240 Set_Etype
(Tsk
, C_Typ
);
3242 if Is_Task_Type
(C_Typ
) then
3243 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3245 elsif Is_Simple_Protected_Type
(C_Typ
) then
3246 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3248 elsif Is_Record_Type
(C_Typ
) then
3249 Stmts
:= Cleanup_Record
(N
, Tsk
, C_Typ
);
3251 elsif Is_Array_Type
(C_Typ
) then
3252 Stmts
:= Cleanup_Array
(N
, Tsk
, C_Typ
);
3258 ------------------------
3259 -- Free_One_Dimension --
3260 ------------------------
3262 function Free_One_Dimension
(Dim
: Int
) return List_Id
is
3266 if Dim
> Number_Dimensions
(Typ
) then
3267 return Free_Component
;
3269 -- Here we generate the required loop
3272 Index
:= Make_Temporary
(Loc
, 'J');
3273 Append
(New_Reference_To
(Index
, Loc
), Index_List
);
3276 Make_Implicit_Loop_Statement
(N
,
3277 Identifier
=> Empty
,
3279 Make_Iteration_Scheme
(Loc
,
3280 Loop_Parameter_Specification
=>
3281 Make_Loop_Parameter_Specification
(Loc
,
3282 Defining_Identifier
=> Index
,
3283 Discrete_Subtype_Definition
=>
3284 Make_Attribute_Reference
(Loc
,
3285 Prefix
=> Duplicate_Subexpr
(Obj
),
3286 Attribute_Name
=> Name_Range
,
3287 Expressions
=> New_List
(
3288 Make_Integer_Literal
(Loc
, Dim
))))),
3289 Statements
=> Free_One_Dimension
(Dim
+ 1)));
3291 end Free_One_Dimension
;
3293 -- Start of processing for Cleanup_Array
3296 return Free_One_Dimension
(1);
3299 --------------------
3300 -- Cleanup_Record --
3301 --------------------
3303 function Cleanup_Record
3306 Typ
: Entity_Id
) return List_Id
3308 Loc
: constant Source_Ptr
:= Sloc
(N
);
3311 Stmts
: constant List_Id
:= New_List
;
3312 U_Typ
: constant Entity_Id
:= Underlying_Type
(Typ
);
3315 if Has_Discriminants
(U_Typ
)
3316 and then Nkind
(Parent
(U_Typ
)) = N_Full_Type_Declaration
3318 Nkind
(Type_Definition
(Parent
(U_Typ
))) = N_Record_Definition
3321 (Variant_Part
(Component_List
(Type_Definition
(Parent
(U_Typ
)))))
3323 -- For now, do not attempt to free a component that may appear in a
3324 -- variant, and instead issue a warning. Doing this "properly" would
3325 -- require building a case statement and would be quite a mess. Note
3326 -- that the RM only requires that free "work" for the case of a task
3327 -- access value, so already we go way beyond this in that we deal
3328 -- with the array case and non-discriminated record cases.
3331 ("task/protected object in variant record will not be freed??", N
);
3332 return New_List
(Make_Null_Statement
(Loc
));
3335 Comp
:= First_Component
(Typ
);
3336 while Present
(Comp
) loop
3337 if Has_Task
(Etype
(Comp
))
3338 or else Has_Simple_Protected_Object
(Etype
(Comp
))
3341 Make_Selected_Component
(Loc
,
3342 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3343 Selector_Name
=> New_Occurrence_Of
(Comp
, Loc
));
3344 Set_Etype
(Tsk
, Etype
(Comp
));
3346 if Is_Task_Type
(Etype
(Comp
)) then
3347 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3349 elsif Is_Simple_Protected_Type
(Etype
(Comp
)) then
3350 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3352 elsif Is_Record_Type
(Etype
(Comp
)) then
3354 -- Recurse, by generating the prefix of the argument to
3355 -- the eventual cleanup call.
3357 Append_List_To
(Stmts
, Cleanup_Record
(N
, Tsk
, Etype
(Comp
)));
3359 elsif Is_Array_Type
(Etype
(Comp
)) then
3360 Append_List_To
(Stmts
, Cleanup_Array
(N
, Tsk
, Etype
(Comp
)));
3364 Next_Component
(Comp
);
3370 ------------------------------
3371 -- Cleanup_Protected_Object --
3372 ------------------------------
3374 function Cleanup_Protected_Object
3376 Ref
: Node_Id
) return Node_Id
3378 Loc
: constant Source_Ptr
:= Sloc
(N
);
3381 -- For restricted run-time libraries (Ravenscar), tasks are
3382 -- non-terminating, and protected objects can only appear at library
3383 -- level, so we do not want finalization of protected objects.
3385 if Restricted_Profile
then
3390 Make_Procedure_Call_Statement
(Loc
,
3392 New_Reference_To
(RTE
(RE_Finalize_Protection
), Loc
),
3393 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3395 end Cleanup_Protected_Object
;
3401 function Cleanup_Task
3403 Ref
: Node_Id
) return Node_Id
3405 Loc
: constant Source_Ptr
:= Sloc
(N
);
3408 -- For restricted run-time libraries (Ravenscar), tasks are
3409 -- non-terminating and they can only appear at library level, so we do
3410 -- not want finalization of task objects.
3412 if Restricted_Profile
then
3417 Make_Procedure_Call_Statement
(Loc
,
3419 New_Reference_To
(RTE
(RE_Free_Task
), Loc
),
3420 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3424 ------------------------------
3425 -- Check_Visibly_Controlled --
3426 ------------------------------
3428 procedure Check_Visibly_Controlled
3429 (Prim
: Final_Primitives
;
3431 E
: in out Entity_Id
;
3432 Cref
: in out Node_Id
)
3434 Parent_Type
: Entity_Id
;
3438 if Is_Derived_Type
(Typ
)
3439 and then Comes_From_Source
(E
)
3440 and then not Present
(Overridden_Operation
(E
))
3442 -- We know that the explicit operation on the type does not override
3443 -- the inherited operation of the parent, and that the derivation
3444 -- is from a private type that is not visibly controlled.
3446 Parent_Type
:= Etype
(Typ
);
3447 Op
:= Find_Prim_Op
(Parent_Type
, Name_Of
(Prim
));
3449 if Present
(Op
) then
3452 -- Wrap the object to be initialized into the proper
3453 -- unchecked conversion, to be compatible with the operation
3456 if Nkind
(Cref
) = N_Unchecked_Type_Conversion
then
3457 Cref
:= Unchecked_Convert_To
(Parent_Type
, Expression
(Cref
));
3459 Cref
:= Unchecked_Convert_To
(Parent_Type
, Cref
);
3463 end Check_Visibly_Controlled
;
3465 -------------------------------
3466 -- CW_Or_Has_Controlled_Part --
3467 -------------------------------
3469 function CW_Or_Has_Controlled_Part
(T
: Entity_Id
) return Boolean is
3471 return Is_Class_Wide_Type
(T
) or else Needs_Finalization
(T
);
3472 end CW_Or_Has_Controlled_Part
;
3478 function Convert_View
3481 Ind
: Pos
:= 1) return Node_Id
3483 Fent
: Entity_Id
:= First_Entity
(Proc
);
3488 for J
in 2 .. Ind
loop
3492 Ftyp
:= Etype
(Fent
);
3494 if Nkind_In
(Arg
, N_Type_Conversion
, N_Unchecked_Type_Conversion
) then
3495 Atyp
:= Entity
(Subtype_Mark
(Arg
));
3497 Atyp
:= Etype
(Arg
);
3500 if Is_Abstract_Subprogram
(Proc
) and then Is_Tagged_Type
(Ftyp
) then
3501 return Unchecked_Convert_To
(Class_Wide_Type
(Ftyp
), Arg
);
3504 and then Present
(Atyp
)
3505 and then (Is_Private_Type
(Ftyp
) or else Is_Private_Type
(Atyp
))
3506 and then Base_Type
(Underlying_Type
(Atyp
)) =
3507 Base_Type
(Underlying_Type
(Ftyp
))
3509 return Unchecked_Convert_To
(Ftyp
, Arg
);
3511 -- If the argument is already a conversion, as generated by
3512 -- Make_Init_Call, set the target type to the type of the formal
3513 -- directly, to avoid spurious typing problems.
3515 elsif Nkind_In
(Arg
, N_Unchecked_Type_Conversion
, N_Type_Conversion
)
3516 and then not Is_Class_Wide_Type
(Atyp
)
3518 Set_Subtype_Mark
(Arg
, New_Occurrence_Of
(Ftyp
, Sloc
(Arg
)));
3519 Set_Etype
(Arg
, Ftyp
);
3527 ------------------------
3528 -- Enclosing_Function --
3529 ------------------------
3531 function Enclosing_Function
(E
: Entity_Id
) return Entity_Id
is
3532 Func_Id
: Entity_Id
;
3536 while Present
(Func_Id
)
3537 and then Func_Id
/= Standard_Standard
3539 if Ekind
(Func_Id
) = E_Function
then
3543 Func_Id
:= Scope
(Func_Id
);
3547 end Enclosing_Function
;
3549 -------------------------------
3550 -- Establish_Transient_Scope --
3551 -------------------------------
3553 -- This procedure is called each time a transient block has to be inserted
3554 -- that is to say for each call to a function with unconstrained or tagged
3555 -- result. It creates a new scope on the stack scope in order to enclose
3556 -- all transient variables generated.
3558 procedure Establish_Transient_Scope
(N
: Node_Id
; Sec_Stack
: Boolean) is
3559 Loc
: constant Source_Ptr
:= Sloc
(N
);
3560 Wrap_Node
: Node_Id
;
3563 -- Do not create a transient scope if we are already inside one
3565 for S
in reverse Scope_Stack
.First
.. Scope_Stack
.Last
loop
3566 if Scope_Stack
.Table
(S
).Is_Transient
then
3568 Set_Uses_Sec_Stack
(Scope_Stack
.Table
(S
).Entity
);
3573 -- If we have encountered Standard there are no enclosing
3574 -- transient scopes.
3576 elsif Scope_Stack
.Table
(S
).Entity
= Standard_Standard
then
3581 Wrap_Node
:= Find_Node_To_Be_Wrapped
(N
);
3583 -- Case of no wrap node, false alert, no transient scope needed
3585 if No
(Wrap_Node
) then
3588 -- If the node to wrap is an iteration_scheme, the expression is
3589 -- one of the bounds, and the expansion will make an explicit
3590 -- declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3591 -- so do not apply any transformations here. Same for an Ada 2012
3592 -- iterator specification, where a block is created for the expression
3593 -- that build the container.
3595 elsif Nkind_In
(Wrap_Node
, N_Iteration_Scheme
,
3596 N_Iterator_Specification
)
3600 -- In formal verification mode, if the node to wrap is a pragma check,
3601 -- this node and enclosed expression are not expanded, so do not apply
3602 -- any transformations here.
3604 elsif GNATprove_Mode
3605 and then Nkind
(Wrap_Node
) = N_Pragma
3606 and then Get_Pragma_Id
(Wrap_Node
) = Pragma_Check
3611 Push_Scope
(New_Internal_Entity
(E_Block
, Current_Scope
, Loc
, 'B'));
3612 Set_Scope_Is_Transient
;
3615 Set_Uses_Sec_Stack
(Current_Scope
);
3616 Check_Restriction
(No_Secondary_Stack
, N
);
3619 Set_Etype
(Current_Scope
, Standard_Void_Type
);
3620 Set_Node_To_Be_Wrapped
(Wrap_Node
);
3622 if Debug_Flag_W
then
3623 Write_Str
(" <Transient>");
3627 end Establish_Transient_Scope
;
3629 ----------------------------
3630 -- Expand_Cleanup_Actions --
3631 ----------------------------
3633 procedure Expand_Cleanup_Actions
(N
: Node_Id
) is
3634 Scop
: constant Entity_Id
:= Current_Scope
;
3636 Is_Asynchronous_Call
: constant Boolean :=
3637 Nkind
(N
) = N_Block_Statement
3638 and then Is_Asynchronous_Call_Block
(N
);
3639 Is_Master
: constant Boolean :=
3640 Nkind
(N
) /= N_Entry_Body
3641 and then Is_Task_Master
(N
);
3642 Is_Protected_Body
: constant Boolean :=
3643 Nkind
(N
) = N_Subprogram_Body
3644 and then Is_Protected_Subprogram_Body
(N
);
3645 Is_Task_Allocation
: constant Boolean :=
3646 Nkind
(N
) = N_Block_Statement
3647 and then Is_Task_Allocation_Block
(N
);
3648 Is_Task_Body
: constant Boolean :=
3649 Nkind
(Original_Node
(N
)) = N_Task_Body
;
3650 Needs_Sec_Stack_Mark
: constant Boolean :=
3651 Uses_Sec_Stack
(Scop
)
3653 not Sec_Stack_Needed_For_Return
(Scop
)
3654 and then VM_Target
= No_VM
;
3656 Actions_Required
: constant Boolean :=
3657 Requires_Cleanup_Actions
(N
, True)
3658 or else Is_Asynchronous_Call
3660 or else Is_Protected_Body
3661 or else Is_Task_Allocation
3662 or else Is_Task_Body
3663 or else Needs_Sec_Stack_Mark
;
3665 HSS
: Node_Id
:= Handled_Statement_Sequence
(N
);
3668 procedure Wrap_HSS_In_Block
;
3669 -- Move HSS inside a new block along with the original exception
3670 -- handlers. Make the newly generated block the sole statement of HSS.
3672 -----------------------
3673 -- Wrap_HSS_In_Block --
3674 -----------------------
3676 procedure Wrap_HSS_In_Block
is
3681 -- Preserve end label to provide proper cross-reference information
3683 End_Lab
:= End_Label
(HSS
);
3685 Make_Block_Statement
(Loc
,
3686 Handled_Statement_Sequence
=> HSS
);
3688 -- Signal the finalization machinery that this particular block
3689 -- contains the original context.
3691 Set_Is_Finalization_Wrapper
(Block
);
3693 Set_Handled_Statement_Sequence
(N
,
3694 Make_Handled_Sequence_Of_Statements
(Loc
, New_List
(Block
)));
3695 HSS
:= Handled_Statement_Sequence
(N
);
3697 Set_First_Real_Statement
(HSS
, Block
);
3698 Set_End_Label
(HSS
, End_Lab
);
3700 -- Comment needed here, see RH for 1.306 ???
3702 if Nkind
(N
) = N_Subprogram_Body
then
3703 Set_Has_Nested_Block_With_Handler
(Scop
);
3705 end Wrap_HSS_In_Block
;
3707 -- Start of processing for Expand_Cleanup_Actions
3710 -- The current construct does not need any form of servicing
3712 if not Actions_Required
then
3715 -- If the current node is a rewritten task body and the descriptors have
3716 -- not been delayed (due to some nested instantiations), do not generate
3717 -- redundant cleanup actions.
3720 and then Nkind
(N
) = N_Subprogram_Body
3721 and then not Delay_Subprogram_Descriptors
(Corresponding_Spec
(N
))
3727 Decls
: List_Id
:= Declarations
(N
);
3729 Mark
: Entity_Id
:= Empty
;
3730 New_Decls
: List_Id
;
3734 -- If we are generating expanded code for debugging purposes, use the
3735 -- Sloc of the point of insertion for the cleanup code. The Sloc will
3736 -- be updated subsequently to reference the proper line in .dg files.
3737 -- If we are not debugging generated code, use No_Location instead,
3738 -- so that no debug information is generated for the cleanup code.
3739 -- This makes the behavior of the NEXT command in GDB monotonic, and
3740 -- makes the placement of breakpoints more accurate.
3742 if Debug_Generated_Code
then
3748 -- Set polling off. The finalization and cleanup code is executed
3749 -- with aborts deferred.
3751 Old_Poll
:= Polling_Required
;
3752 Polling_Required
:= False;
3754 -- A task activation call has already been built for a task
3755 -- allocation block.
3757 if not Is_Task_Allocation
then
3758 Build_Task_Activation_Call
(N
);
3762 Establish_Task_Master
(N
);
3765 New_Decls
:= New_List
;
3767 -- If secondary stack is in use, generate:
3769 -- Mnn : constant Mark_Id := SS_Mark;
3771 -- Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3772 -- secondary stack is never used on a VM.
3774 if Needs_Sec_Stack_Mark
then
3775 Mark
:= Make_Temporary
(Loc
, 'M');
3777 Append_To
(New_Decls
,
3778 Make_Object_Declaration
(Loc
,
3779 Defining_Identifier
=> Mark
,
3780 Object_Definition
=>
3781 New_Reference_To
(RTE
(RE_Mark_Id
), Loc
),
3783 Make_Function_Call
(Loc
,
3784 Name
=> New_Reference_To
(RTE
(RE_SS_Mark
), Loc
))));
3786 Set_Uses_Sec_Stack
(Scop
, False);
3789 -- If exception handlers are present, wrap the sequence of statements
3790 -- in a block since it is not possible to have exception handlers and
3791 -- an At_End handler in the same construct.
3793 if Present
(Exception_Handlers
(HSS
)) then
3796 -- Ensure that the First_Real_Statement field is set
3798 elsif No
(First_Real_Statement
(HSS
)) then
3799 Set_First_Real_Statement
(HSS
, First
(Statements
(HSS
)));
3802 -- Do not move the Activation_Chain declaration in the context of
3803 -- task allocation blocks. Task allocation blocks use _chain in their
3804 -- cleanup handlers and gigi complains if it is declared in the
3805 -- sequence of statements of the scope that declares the handler.
3807 if Is_Task_Allocation
then
3809 Chain
: constant Entity_Id
:= Activation_Chain_Entity
(N
);
3813 Decl
:= First
(Decls
);
3814 while Nkind
(Decl
) /= N_Object_Declaration
3815 or else Defining_Identifier
(Decl
) /= Chain
3819 -- A task allocation block should always include a _chain
3822 pragma Assert
(Present
(Decl
));
3826 Prepend_To
(New_Decls
, Decl
);
3830 -- Ensure the presence of a declaration list in order to successfully
3831 -- append all original statements to it.
3834 Set_Declarations
(N
, New_List
);
3835 Decls
:= Declarations
(N
);
3838 -- Move the declarations into the sequence of statements in order to
3839 -- have them protected by the At_End handler. It may seem weird to
3840 -- put declarations in the sequence of statement but in fact nothing
3841 -- forbids that at the tree level.
3843 Append_List_To
(Decls
, Statements
(HSS
));
3844 Set_Statements
(HSS
, Decls
);
3846 -- Reset the Sloc of the handled statement sequence to properly
3847 -- reflect the new initial "statement" in the sequence.
3849 Set_Sloc
(HSS
, Sloc
(First
(Decls
)));
3851 -- The declarations of finalizer spec and auxiliary variables replace
3852 -- the old declarations that have been moved inward.
3854 Set_Declarations
(N
, New_Decls
);
3855 Analyze_Declarations
(New_Decls
);
3857 -- Generate finalization calls for all controlled objects appearing
3858 -- in the statements of N. Add context specific cleanup for various
3863 Clean_Stmts
=> Build_Cleanup_Statements
(N
),
3865 Top_Decls
=> New_Decls
,
3866 Defer_Abort
=> Nkind
(Original_Node
(N
)) = N_Task_Body
3870 if Present
(Fin_Id
) then
3871 Build_Finalizer_Call
(N
, Fin_Id
);
3874 -- Restore saved polling mode
3876 Polling_Required
:= Old_Poll
;
3878 end Expand_Cleanup_Actions
;
3880 ---------------------------
3881 -- Expand_N_Package_Body --
3882 ---------------------------
3884 -- Add call to Activate_Tasks if body is an activator (actual processing
3885 -- is in chapter 9).
3887 -- Generate subprogram descriptor for elaboration routine
3889 -- Encode entity names in package body
3891 procedure Expand_N_Package_Body
(N
: Node_Id
) is
3892 Spec_Ent
: constant Entity_Id
:= Corresponding_Spec
(N
);
3896 -- This is done only for non-generic packages
3898 if Ekind
(Spec_Ent
) = E_Package
then
3899 Push_Scope
(Corresponding_Spec
(N
));
3901 -- Build dispatch tables of library level tagged types
3903 if Tagged_Type_Expansion
3904 and then Is_Library_Level_Entity
(Spec_Ent
)
3906 Build_Static_Dispatch_Tables
(N
);
3909 Build_Task_Activation_Call
(N
);
3911 -- When the package is subject to pragma Initial_Condition, the
3912 -- assertion expression must be verified at the end of the body
3915 if Present
(Get_Pragma
(Spec_Ent
, Pragma_Initial_Condition
)) then
3916 Expand_Pragma_Initial_Condition
(N
);
3922 Set_Elaboration_Flag
(N
, Corresponding_Spec
(N
));
3923 Set_In_Package_Body
(Spec_Ent
, False);
3925 -- Set to encode entity names in package body before gigi is called
3927 Qualify_Entity_Names
(N
);
3929 if Ekind
(Spec_Ent
) /= E_Generic_Package
then
3932 Clean_Stmts
=> No_List
,
3934 Top_Decls
=> No_List
,
3935 Defer_Abort
=> False,
3938 if Present
(Fin_Id
) then
3940 Body_Ent
: Node_Id
:= Defining_Unit_Name
(N
);
3943 if Nkind
(Body_Ent
) = N_Defining_Program_Unit_Name
then
3944 Body_Ent
:= Defining_Identifier
(Body_Ent
);
3947 Set_Finalizer
(Body_Ent
, Fin_Id
);
3951 end Expand_N_Package_Body
;
3953 ----------------------------------
3954 -- Expand_N_Package_Declaration --
3955 ----------------------------------
3957 -- Add call to Activate_Tasks if there are tasks declared and the package
3958 -- has no body. Note that in Ada 83 this may result in premature activation
3959 -- of some tasks, given that we cannot tell whether a body will eventually
3962 procedure Expand_N_Package_Declaration
(N
: Node_Id
) is
3963 Id
: constant Entity_Id
:= Defining_Entity
(N
);
3964 Spec
: constant Node_Id
:= Specification
(N
);
3968 No_Body
: Boolean := False;
3969 -- True in the case of a package declaration that is a compilation
3970 -- unit and for which no associated body will be compiled in this
3974 -- Case of a package declaration other than a compilation unit
3976 if Nkind
(Parent
(N
)) /= N_Compilation_Unit
then
3979 -- Case of a compilation unit that does not require a body
3981 elsif not Body_Required
(Parent
(N
))
3982 and then not Unit_Requires_Body
(Id
)
3986 -- Special case of generating calling stubs for a remote call interface
3987 -- package: even though the package declaration requires one, the body
3988 -- won't be processed in this compilation (so any stubs for RACWs
3989 -- declared in the package must be generated here, along with the spec).
3991 elsif Parent
(N
) = Cunit
(Main_Unit
)
3992 and then Is_Remote_Call_Interface
(Id
)
3993 and then Distribution_Stub_Mode
= Generate_Caller_Stub_Body
3998 -- For a nested instance, delay processing until freeze point
4000 if Has_Delayed_Freeze
(Id
)
4001 and then Nkind
(Parent
(N
)) /= N_Compilation_Unit
4006 -- For a package declaration that implies no associated body, generate
4007 -- task activation call and RACW supporting bodies now (since we won't
4008 -- have a specific separate compilation unit for that).
4013 -- Generate RACW subprogram bodies
4015 if Has_RACW
(Id
) then
4016 Decls
:= Private_Declarations
(Spec
);
4019 Decls
:= Visible_Declarations
(Spec
);
4024 Set_Visible_Declarations
(Spec
, Decls
);
4027 Append_RACW_Bodies
(Decls
, Id
);
4028 Analyze_List
(Decls
);
4031 -- Generate task activation call as last step of elaboration
4033 if Present
(Activation_Chain_Entity
(N
)) then
4034 Build_Task_Activation_Call
(N
);
4037 -- When the package is subject to pragma Initial_Condition and lacks
4038 -- a body, the assertion expression must be verified at the end of
4039 -- the visible declarations. Otherwise the check is performed at the
4040 -- end of the body statements (see Expand_N_Package_Body).
4042 if Present
(Get_Pragma
(Id
, Pragma_Initial_Condition
)) then
4043 Expand_Pragma_Initial_Condition
(N
);
4049 -- Build dispatch tables of library level tagged types
4051 if Tagged_Type_Expansion
4052 and then (Is_Compilation_Unit
(Id
)
4053 or else (Is_Generic_Instance
(Id
)
4054 and then Is_Library_Level_Entity
(Id
)))
4056 Build_Static_Dispatch_Tables
(N
);
4059 -- Note: it is not necessary to worry about generating a subprogram
4060 -- descriptor, since the only way to get exception handlers into a
4061 -- package spec is to include instantiations, and that would cause
4062 -- generation of subprogram descriptors to be delayed in any case.
4064 -- Set to encode entity names in package spec before gigi is called
4066 Qualify_Entity_Names
(N
);
4068 if Ekind
(Id
) /= E_Generic_Package
then
4071 Clean_Stmts
=> No_List
,
4073 Top_Decls
=> No_List
,
4074 Defer_Abort
=> False,
4077 Set_Finalizer
(Id
, Fin_Id
);
4079 end Expand_N_Package_Declaration
;
4081 -------------------------------------
4082 -- Expand_Pragma_Initial_Condition --
4083 -------------------------------------
4085 procedure Expand_Pragma_Initial_Condition
(N
: Node_Id
) is
4086 Loc
: constant Source_Ptr
:= Sloc
(N
);
4089 Init_Cond
: Node_Id
;
4091 Pack_Id
: Entity_Id
;
4094 if Nkind
(N
) = N_Package_Body
then
4095 Pack_Id
:= Corresponding_Spec
(N
);
4097 if Present
(Handled_Statement_Sequence
(N
)) then
4098 List
:= Statements
(Handled_Statement_Sequence
(N
));
4100 -- The package body lacks statements, create an empty list
4105 Set_Handled_Statement_Sequence
(N
,
4106 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> List
));
4109 elsif Nkind
(N
) = N_Package_Declaration
then
4110 Pack_Id
:= Defining_Entity
(N
);
4112 if Present
(Visible_Declarations
(Specification
(N
))) then
4113 List
:= Visible_Declarations
(Specification
(N
));
4115 -- The package lacks visible declarations, create an empty list
4120 Set_Visible_Declarations
(Specification
(N
), List
);
4123 -- This routine should not be used on anything other than packages
4126 raise Program_Error
;
4129 Init_Cond
:= Get_Pragma
(Pack_Id
, Pragma_Initial_Condition
);
4131 -- The caller should check whether the package is subject to pragma
4132 -- Initial_Condition.
4134 pragma Assert
(Present
(Init_Cond
));
4137 Get_Pragma_Arg
(First
(Pragma_Argument_Associations
(Init_Cond
)));
4139 -- The assertion expression was found to be illegal, do not generate the
4140 -- runtime check as it will repeat the illegality.
4142 if Error_Posted
(Init_Cond
) or else Error_Posted
(Expr
) then
4147 -- pragma Check (Initial_Condition, <Expr>);
4151 Chars
=> Name_Check
,
4152 Pragma_Argument_Associations
=> New_List
(
4153 Make_Pragma_Argument_Association
(Loc
,
4154 Expression
=> Make_Identifier
(Loc
, Name_Initial_Condition
)),
4156 Make_Pragma_Argument_Association
(Loc
,
4157 Expression
=> New_Copy_Tree
(Expr
))));
4159 Append_To
(List
, Check
);
4161 end Expand_Pragma_Initial_Condition
;
4163 -----------------------------
4164 -- Find_Node_To_Be_Wrapped --
4165 -----------------------------
4167 function Find_Node_To_Be_Wrapped
(N
: Node_Id
) return Node_Id
is
4169 The_Parent
: Node_Id
;
4175 pragma Assert
(P
/= Empty
);
4176 The_Parent
:= Parent
(P
);
4178 case Nkind
(The_Parent
) is
4180 -- Simple statement can be wrapped
4185 -- Usually assignments are good candidate for wrapping except
4186 -- when they have been generated as part of a controlled aggregate
4187 -- where the wrapping should take place more globally. Note that
4188 -- No_Ctrl_Actions may be set also for non-controlled assignements
4189 -- in order to disable the use of dispatching _assign, so we need
4190 -- to test explicitly for a controlled type here.
4192 when N_Assignment_Statement
=>
4193 if No_Ctrl_Actions
(The_Parent
)
4194 and then Needs_Finalization
(Etype
(Name
(The_Parent
)))
4201 -- An entry call statement is a special case if it occurs in the
4202 -- context of a Timed_Entry_Call. In this case we wrap the entire
4203 -- timed entry call.
4205 when N_Entry_Call_Statement |
4206 N_Procedure_Call_Statement
=>
4207 if Nkind
(Parent
(The_Parent
)) = N_Entry_Call_Alternative
4208 and then Nkind_In
(Parent
(Parent
(The_Parent
)),
4210 N_Conditional_Entry_Call
)
4212 return Parent
(Parent
(The_Parent
));
4217 -- Object declarations are also a boundary for the transient scope
4218 -- even if they are not really wrapped. For further details, see
4219 -- Wrap_Transient_Declaration.
4221 when N_Object_Declaration |
4222 N_Object_Renaming_Declaration |
4223 N_Subtype_Declaration
=>
4226 -- The expression itself is to be wrapped if its parent is a
4227 -- compound statement or any other statement where the expression
4228 -- is known to be scalar
4230 when N_Accept_Alternative |
4231 N_Attribute_Definition_Clause |
4234 N_Delay_Alternative |
4235 N_Delay_Until_Statement |
4236 N_Delay_Relative_Statement |
4237 N_Discriminant_Association |
4239 N_Entry_Body_Formal_Part |
4242 N_Iteration_Scheme |
4243 N_Terminate_Alternative
=>
4246 when N_Attribute_Reference
=>
4248 if Is_Procedure_Attribute_Name
4249 (Attribute_Name
(The_Parent
))
4254 -- A raise statement can be wrapped. This will arise when the
4255 -- expression in a raise_with_expression uses the secondary
4256 -- stack, for example.
4258 when N_Raise_Statement
=>
4261 -- If the expression is within the iteration scheme of a loop,
4262 -- we must create a declaration for it, followed by an assignment
4263 -- in order to have a usable statement to wrap.
4265 when N_Loop_Parameter_Specification
=>
4266 return Parent
(The_Parent
);
4268 -- The following nodes contains "dummy calls" which don't need to
4271 when N_Parameter_Specification |
4272 N_Discriminant_Specification |
4273 N_Component_Declaration
=>
4276 -- The return statement is not to be wrapped when the function
4277 -- itself needs wrapping at the outer-level
4279 when N_Simple_Return_Statement
=>
4281 Applies_To
: constant Entity_Id
:=
4283 (Return_Statement_Entity
(The_Parent
));
4284 Return_Type
: constant Entity_Id
:= Etype
(Applies_To
);
4286 if Requires_Transient_Scope
(Return_Type
) then
4293 -- If we leave a scope without having been able to find a node to
4294 -- wrap, something is going wrong but this can happen in error
4295 -- situation that are not detected yet (such as a dynamic string
4296 -- in a pragma export)
4298 when N_Subprogram_Body |
4299 N_Package_Declaration |
4301 N_Block_Statement
=>
4304 -- Otherwise continue the search
4310 end Find_Node_To_Be_Wrapped
;
4312 -------------------------------------
4313 -- Get_Global_Pool_For_Access_Type --
4314 -------------------------------------
4316 function Get_Global_Pool_For_Access_Type
(T
: Entity_Id
) return Entity_Id
is
4318 -- Access types whose size is smaller than System.Address size can exist
4319 -- only on VMS. We can't use the usual global pool which returns an
4320 -- object of type Address as truncation will make it invalid. To handle
4321 -- this case, VMS has a dedicated global pool that returns addresses
4322 -- that fit into 32 bit accesses.
4324 if Opt
.True_VMS_Target
and then Esize
(T
) = 32 then
4325 return RTE
(RE_Global_Pool_32_Object
);
4327 return RTE
(RE_Global_Pool_Object
);
4329 end Get_Global_Pool_For_Access_Type
;
4331 ----------------------------------
4332 -- Has_New_Controlled_Component --
4333 ----------------------------------
4335 function Has_New_Controlled_Component
(E
: Entity_Id
) return Boolean is
4339 if not Is_Tagged_Type
(E
) then
4340 return Has_Controlled_Component
(E
);
4341 elsif not Is_Derived_Type
(E
) then
4342 return Has_Controlled_Component
(E
);
4345 Comp
:= First_Component
(E
);
4346 while Present
(Comp
) loop
4347 if Chars
(Comp
) = Name_uParent
then
4350 elsif Scope
(Original_Record_Component
(Comp
)) = E
4351 and then Needs_Finalization
(Etype
(Comp
))
4356 Next_Component
(Comp
);
4360 end Has_New_Controlled_Component
;
4362 ---------------------------------
4363 -- Has_Simple_Protected_Object --
4364 ---------------------------------
4366 function Has_Simple_Protected_Object
(T
: Entity_Id
) return Boolean is
4368 if Has_Task
(T
) then
4371 elsif Is_Simple_Protected_Type
(T
) then
4374 elsif Is_Array_Type
(T
) then
4375 return Has_Simple_Protected_Object
(Component_Type
(T
));
4377 elsif Is_Record_Type
(T
) then
4382 Comp
:= First_Component
(T
);
4383 while Present
(Comp
) loop
4384 if Has_Simple_Protected_Object
(Etype
(Comp
)) then
4388 Next_Component
(Comp
);
4397 end Has_Simple_Protected_Object
;
4399 ------------------------------------
4400 -- Insert_Actions_In_Scope_Around --
4401 ------------------------------------
4403 procedure Insert_Actions_In_Scope_Around
(N
: Node_Id
) is
4404 After
: constant List_Id
:=
4405 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped_After
;
4406 Before
: constant List_Id
:=
4407 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped_Before
;
4408 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
4409 -- Last), but this was incorrect as Process_Transient_Object may
4410 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
4412 procedure Process_Transient_Objects
4413 (First_Object
: Node_Id
;
4414 Last_Object
: Node_Id
;
4415 Related_Node
: Node_Id
);
4416 -- First_Object and Last_Object define a list which contains potential
4417 -- controlled transient objects. Finalization flags are inserted before
4418 -- First_Object and finalization calls are inserted after Last_Object.
4419 -- Related_Node is the node for which transient objects have been
4422 -------------------------------
4423 -- Process_Transient_Objects --
4424 -------------------------------
4426 procedure Process_Transient_Objects
4427 (First_Object
: Node_Id
;
4428 Last_Object
: Node_Id
;
4429 Related_Node
: Node_Id
)
4431 Must_Hook
: Boolean := False;
4432 -- Flag denoting whether the context requires transient variable
4433 -- export to the outer finalizer.
4435 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
;
4436 -- Determine whether an arbitrary node denotes a subprogram call
4438 procedure Detect_Subprogram_Call
is
4439 new Traverse_Proc
(Is_Subprogram_Call
);
4441 ------------------------
4442 -- Is_Subprogram_Call --
4443 ------------------------
4445 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
is
4447 -- Complex constructs are factored out by the expander and their
4448 -- occurrences are replaced with references to temporaries. Due to
4449 -- this expansion activity, inspect the original tree to detect
4450 -- subprogram calls.
4452 if Nkind
(N
) = N_Identifier
and then Original_Node
(N
) /= N
then
4453 Detect_Subprogram_Call
(Original_Node
(N
));
4455 -- The original construct contains a subprogram call, there is
4456 -- no point in continuing the tree traversal.
4464 -- The original construct contains a subprogram call, there is no
4465 -- point in continuing the tree traversal.
4467 elsif Nkind
(N
) = N_Object_Declaration
4468 and then Present
(Expression
(N
))
4469 and then Nkind
(Original_Node
(Expression
(N
))) = N_Function_Call
4474 -- A regular procedure or function call
4476 elsif Nkind
(N
) in N_Subprogram_Call
then
4485 end Is_Subprogram_Call
;
4489 Built
: Boolean := False;
4490 Desig_Typ
: Entity_Id
;
4492 Fin_Block
: Node_Id
;
4493 Fin_Data
: Finalization_Exception_Data
;
4494 Fin_Decls
: List_Id
;
4495 Fin_Insrt
: Node_Id
;
4496 Last_Fin
: Node_Id
:= Empty
;
4500 Obj_Typ
: Entity_Id
;
4501 Prev_Fin
: Node_Id
:= Empty
;
4505 Temp_Id
: Entity_Id
;
4508 -- Start of processing for Process_Transient_Objects
4511 -- Recognize a scenario where the transient context is an object
4512 -- declaration initialized by a build-in-place function call:
4514 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
4516 -- The rough expansion of the above is:
4518 -- Temp : ... := Ctrl_Func_Call;
4520 -- Res : ... := BIP_Func_Call (..., Obj, ...);
4522 -- The finalization of any controlled transient must happen after
4523 -- the build-in-place function call is executed.
4525 if Nkind
(N
) = N_Object_Declaration
4526 and then Present
(BIP_Initialization_Call
(Defining_Identifier
(N
)))
4529 Fin_Insrt
:= BIP_Initialization_Call
(Defining_Identifier
(N
));
4531 -- Search the context for at least one subprogram call. If found, the
4532 -- machinery exports all transient objects to the enclosing finalizer
4533 -- due to the possibility of abnormal call termination.
4536 Detect_Subprogram_Call
(N
);
4537 Fin_Insrt
:= Last_Object
;
4540 -- Examine all objects in the list First_Object .. Last_Object
4542 Stmt
:= First_Object
;
4543 while Present
(Stmt
) loop
4544 if Nkind
(Stmt
) = N_Object_Declaration
4545 and then Analyzed
(Stmt
)
4546 and then Is_Finalizable_Transient
(Stmt
, N
)
4548 -- Do not process the node to be wrapped since it will be
4549 -- handled by the enclosing finalizer.
4551 and then Stmt
/= Related_Node
4554 Obj_Id
:= Defining_Identifier
(Stmt
);
4555 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
4556 Desig_Typ
:= Obj_Typ
;
4558 Set_Is_Processed_Transient
(Obj_Id
);
4560 -- Handle access types
4562 if Is_Access_Type
(Desig_Typ
) then
4563 Desig_Typ
:= Available_View
(Designated_Type
(Desig_Typ
));
4566 -- Create the necessary entities and declarations the first
4571 Fin_Decls
:= New_List
;
4573 Build_Object_Declarations
(Fin_Data
, Fin_Decls
, Loc
);
4576 -- Transient variables associated with subprogram calls need
4577 -- extra processing. These variables are usually created right
4578 -- before the call and finalized immediately after the call.
4579 -- If an exception occurs during the call, the clean up code
4580 -- is skipped due to the sudden change in control and the
4581 -- transient is never finalized.
4583 -- To handle this case, such variables are "exported" to the
4584 -- enclosing sequence of statements where their corresponding
4585 -- "hooks" are picked up by the finalization machinery.
4589 -- Step 1: Create an access type which provides a reference
4590 -- to the transient object. Generate:
4592 -- Ann : access [all] <Desig_Typ>;
4594 Ptr_Id
:= Make_Temporary
(Loc
, 'A');
4596 Insert_Action
(Stmt
,
4597 Make_Full_Type_Declaration
(Loc
,
4598 Defining_Identifier
=> Ptr_Id
,
4600 Make_Access_To_Object_Definition
(Loc
,
4602 Ekind
(Obj_Typ
) = E_General_Access_Type
,
4603 Subtype_Indication
=>
4604 New_Reference_To
(Desig_Typ
, Loc
))));
4606 -- Step 2: Create a temporary which acts as a hook to the
4607 -- transient object. Generate:
4609 -- Temp : Ptr_Id := null;
4611 Temp_Id
:= Make_Temporary
(Loc
, 'T');
4613 Insert_Action
(Stmt
,
4614 Make_Object_Declaration
(Loc
,
4615 Defining_Identifier
=> Temp_Id
,
4616 Object_Definition
=>
4617 New_Reference_To
(Ptr_Id
, Loc
)));
4619 -- Mark the temporary as a transient hook. This signals the
4620 -- machinery in Build_Finalizer to recognize this special
4623 Set_Status_Flag_Or_Transient_Decl
(Temp_Id
, Stmt
);
4625 -- Step 3: Hook the transient object to the temporary
4627 if Is_Access_Type
(Obj_Typ
) then
4629 Convert_To
(Ptr_Id
, New_Reference_To
(Obj_Id
, Loc
));
4632 Make_Attribute_Reference
(Loc
,
4633 Prefix
=> New_Reference_To
(Obj_Id
, Loc
),
4634 Attribute_Name
=> Name_Unrestricted_Access
);
4638 -- Temp := Ptr_Id (Obj_Id);
4640 -- Temp := Obj_Id'Unrestricted_Access;
4642 -- When the transient object is initialized by an aggregate,
4643 -- the hook must capture the object after the last component
4644 -- assignment takes place. Only then is the object fully
4647 if Ekind
(Obj_Id
) = E_Variable
4648 and then Present
(Last_Aggregate_Assignment
(Obj_Id
))
4650 Temp_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
4652 -- Otherwise the hook seizes the related object immediately
4658 Insert_After_And_Analyze
(Temp_Ins
,
4659 Make_Assignment_Statement
(Loc
,
4660 Name
=> New_Reference_To
(Temp_Id
, Loc
),
4661 Expression
=> Expr
));
4666 -- The transient object is about to be finalized by the clean
4667 -- up code following the subprogram call. In order to avoid
4668 -- double finalization, clear the hook.
4675 Make_Assignment_Statement
(Loc
,
4676 Name
=> New_Reference_To
(Temp_Id
, Loc
),
4677 Expression
=> Make_Null
(Loc
)));
4681 -- [Deep_]Finalize (Obj_Ref);
4683 Obj_Ref
:= New_Reference_To
(Obj_Id
, Loc
);
4685 if Is_Access_Type
(Obj_Typ
) then
4686 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
4690 Make_Final_Call
(Obj_Ref
=> Obj_Ref
, Typ
=> Desig_Typ
));
4695 -- [Deep_]Finalize (Obj_Ref);
4699 -- if not Raised then
4702 -- (Enn, Get_Current_Excep.all.all);
4707 Make_Block_Statement
(Loc
,
4708 Handled_Statement_Sequence
=>
4709 Make_Handled_Sequence_Of_Statements
(Loc
,
4710 Statements
=> Stmts
,
4711 Exception_Handlers
=> New_List
(
4712 Build_Exception_Handler
(Fin_Data
))));
4714 -- The single raise statement must be inserted after all the
4715 -- finalization blocks, and we put everything into a wrapper
4716 -- block to clearly expose the construct to the back-end.
4718 if Present
(Prev_Fin
) then
4719 Insert_Before_And_Analyze
(Prev_Fin
, Fin_Block
);
4721 Insert_After_And_Analyze
(Fin_Insrt
,
4722 Make_Block_Statement
(Loc
,
4723 Declarations
=> Fin_Decls
,
4724 Handled_Statement_Sequence
=>
4725 Make_Handled_Sequence_Of_Statements
(Loc
,
4726 Statements
=> New_List
(Fin_Block
))));
4728 Last_Fin
:= Fin_Block
;
4731 Prev_Fin
:= Fin_Block
;
4734 -- Terminate the scan after the last object has been processed to
4735 -- avoid touching unrelated code.
4737 if Stmt
= Last_Object
then
4745 -- if Raised and then not Abort then
4746 -- Raise_From_Controlled_Operation (E);
4749 if Built
and then Present
(Last_Fin
) then
4750 Insert_After_And_Analyze
(Last_Fin
,
4751 Build_Raise_Statement
(Fin_Data
));
4753 end Process_Transient_Objects
;
4755 -- Start of processing for Insert_Actions_In_Scope_Around
4758 if No
(Before
) and then No
(After
) then
4763 Node_To_Wrap
: constant Node_Id
:= Node_To_Be_Wrapped
;
4764 First_Obj
: Node_Id
;
4769 -- If the node to be wrapped is the trigger of an asynchronous
4770 -- select, it is not part of a statement list. The actions must be
4771 -- inserted before the select itself, which is part of some list of
4772 -- statements. Note that the triggering alternative includes the
4773 -- triggering statement and an optional statement list. If the node
4774 -- to be wrapped is part of that list, the normal insertion applies.
4776 if Nkind
(Parent
(Node_To_Wrap
)) = N_Triggering_Alternative
4777 and then not Is_List_Member
(Node_To_Wrap
)
4779 Target
:= Parent
(Parent
(Node_To_Wrap
));
4784 First_Obj
:= Target
;
4787 -- Add all actions associated with a transient scope into the main
4788 -- tree. There are several scenarios here:
4790 -- +--- Before ----+ +----- After ---+
4791 -- 1) First_Obj ....... Target ........ Last_Obj
4793 -- 2) First_Obj ....... Target
4795 -- 3) Target ........ Last_Obj
4797 if Present
(Before
) then
4799 -- Flag declarations are inserted before the first object
4801 First_Obj
:= First
(Before
);
4803 Insert_List_Before
(Target
, Before
);
4806 if Present
(After
) then
4808 -- Finalization calls are inserted after the last object
4810 Last_Obj
:= Last
(After
);
4812 Insert_List_After
(Target
, After
);
4815 -- Check for transient controlled objects associated with Target and
4816 -- generate the appropriate finalization actions for them.
4818 Process_Transient_Objects
4819 (First_Object
=> First_Obj
,
4820 Last_Object
=> Last_Obj
,
4821 Related_Node
=> Target
);
4823 -- Reset the action lists
4825 if Present
(Before
) then
4826 Scope_Stack
.Table
(Scope_Stack
.Last
).
4827 Actions_To_Be_Wrapped_Before
:= No_List
;
4830 if Present
(After
) then
4831 Scope_Stack
.Table
(Scope_Stack
.Last
).
4832 Actions_To_Be_Wrapped_After
:= No_List
;
4835 end Insert_Actions_In_Scope_Around
;
4837 ------------------------------
4838 -- Is_Simple_Protected_Type --
4839 ------------------------------
4841 function Is_Simple_Protected_Type
(T
: Entity_Id
) return Boolean is
4844 Is_Protected_Type
(T
)
4845 and then not Uses_Lock_Free
(T
)
4846 and then not Has_Entries
(T
)
4847 and then Is_RTE
(Find_Protection_Type
(T
), RE_Protection
);
4848 end Is_Simple_Protected_Type
;
4850 -----------------------
4851 -- Make_Adjust_Call --
4852 -----------------------
4854 function Make_Adjust_Call
4857 For_Parent
: Boolean := False) return Node_Id
4859 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
4860 Adj_Id
: Entity_Id
:= Empty
;
4861 Ref
: Node_Id
:= Obj_Ref
;
4865 -- Recover the proper type which contains Deep_Adjust
4867 if Is_Class_Wide_Type
(Typ
) then
4868 Utyp
:= Root_Type
(Typ
);
4873 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
4874 Set_Assignment_OK
(Ref
);
4876 -- Deal with non-tagged derivation of private views
4878 if Is_Untagged_Derivation
(Typ
) then
4879 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
4880 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
4881 Set_Assignment_OK
(Ref
);
4884 -- When dealing with the completion of a private type, use the base
4887 if Utyp
/= Base_Type
(Utyp
) then
4888 pragma Assert
(Is_Private_Type
(Typ
));
4890 Utyp
:= Base_Type
(Utyp
);
4891 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
4894 -- Select the appropriate version of adjust
4897 if Has_Controlled_Component
(Utyp
) then
4898 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
4901 -- Class-wide types, interfaces and types with controlled components
4903 elsif Is_Class_Wide_Type
(Typ
)
4904 or else Is_Interface
(Typ
)
4905 or else Has_Controlled_Component
(Utyp
)
4907 if Is_Tagged_Type
(Utyp
) then
4908 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
4910 Adj_Id
:= TSS
(Utyp
, TSS_Deep_Adjust
);
4913 -- Derivations from [Limited_]Controlled
4915 elsif Is_Controlled
(Utyp
) then
4916 if Has_Controlled_Component
(Utyp
) then
4917 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
4919 Adj_Id
:= Find_Prim_Op
(Utyp
, Name_Of
(Adjust_Case
));
4924 elsif Is_Tagged_Type
(Utyp
) then
4925 Adj_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
4928 raise Program_Error
;
4931 if Present
(Adj_Id
) then
4933 -- If the object is unanalyzed, set its expected type for use in
4934 -- Convert_View in case an additional conversion is needed.
4937 and then Nkind
(Ref
) /= N_Unchecked_Type_Conversion
4939 Set_Etype
(Ref
, Typ
);
4942 -- The object reference may need another conversion depending on the
4943 -- type of the formal and that of the actual.
4945 if not Is_Class_Wide_Type
(Typ
) then
4946 Ref
:= Convert_View
(Adj_Id
, Ref
);
4949 return Make_Call
(Loc
, Adj_Id
, New_Copy_Tree
(Ref
), For_Parent
);
4953 end Make_Adjust_Call
;
4955 ----------------------
4956 -- Make_Attach_Call --
4957 ----------------------
4959 function Make_Attach_Call
4961 Ptr_Typ
: Entity_Id
) return Node_Id
4963 pragma Assert
(VM_Target
/= No_VM
);
4965 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
4968 Make_Procedure_Call_Statement
(Loc
,
4970 New_Reference_To
(RTE
(RE_Attach
), Loc
),
4971 Parameter_Associations
=> New_List
(
4972 New_Reference_To
(Finalization_Master
(Ptr_Typ
), Loc
),
4973 Unchecked_Convert_To
(RTE
(RE_Root_Controlled_Ptr
), Obj_Ref
)));
4974 end Make_Attach_Call
;
4976 ----------------------
4977 -- Make_Detach_Call --
4978 ----------------------
4980 function Make_Detach_Call
(Obj_Ref
: Node_Id
) return Node_Id
is
4981 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
4985 Make_Procedure_Call_Statement
(Loc
,
4987 New_Reference_To
(RTE
(RE_Detach
), Loc
),
4988 Parameter_Associations
=> New_List
(
4989 Unchecked_Convert_To
(RTE
(RE_Root_Controlled_Ptr
), Obj_Ref
)));
4990 end Make_Detach_Call
;
4998 Proc_Id
: Entity_Id
;
5000 For_Parent
: Boolean := False) return Node_Id
5002 Params
: constant List_Id
:= New_List
(Param
);
5005 -- When creating a call to Deep_Finalize for a _parent field of a
5006 -- derived type, disable the invocation of the nested Finalize by giving
5007 -- the corresponding flag a False value.
5010 Append_To
(Params
, New_Reference_To
(Standard_False
, Loc
));
5014 Make_Procedure_Call_Statement
(Loc
,
5015 Name
=> New_Reference_To
(Proc_Id
, Loc
),
5016 Parameter_Associations
=> Params
);
5019 --------------------------
5020 -- Make_Deep_Array_Body --
5021 --------------------------
5023 function Make_Deep_Array_Body
5024 (Prim
: Final_Primitives
;
5025 Typ
: Entity_Id
) return List_Id
5027 function Build_Adjust_Or_Finalize_Statements
5028 (Typ
: Entity_Id
) return List_Id
;
5029 -- Create the statements necessary to adjust or finalize an array of
5030 -- controlled elements. Generate:
5033 -- Abort : constant Boolean := Triggered_By_Abort;
5035 -- Abort : constant Boolean := False; -- no abort
5037 -- E : Exception_Occurrence;
5038 -- Raised : Boolean := False;
5041 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
5042 -- ^-- in the finalization case
5044 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
5046 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
5050 -- if not Raised then
5052 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5059 -- if Raised and then not Abort then
5060 -- Raise_From_Controlled_Operation (E);
5064 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
;
5065 -- Create the statements necessary to initialize an array of controlled
5066 -- elements. Include a mechanism to carry out partial finalization if an
5067 -- exception occurs. Generate:
5070 -- Counter : Integer := 0;
5073 -- for J1 in V'Range (1) loop
5075 -- for JN in V'Range (N) loop
5077 -- [Deep_]Initialize (V (J1, ..., JN));
5079 -- Counter := Counter + 1;
5084 -- Abort : constant Boolean := Triggered_By_Abort;
5086 -- Abort : constant Boolean := False; -- no abort
5087 -- E : Exception_Occurence;
5088 -- Raised : Boolean := False;
5095 -- V'Length (N) - Counter;
5097 -- for F1 in reverse V'Range (1) loop
5099 -- for FN in reverse V'Range (N) loop
5100 -- if Counter > 0 then
5101 -- Counter := Counter - 1;
5104 -- [Deep_]Finalize (V (F1, ..., FN));
5108 -- if not Raised then
5110 -- Save_Occurrence (E,
5111 -- Get_Current_Excep.all.all);
5120 -- if Raised and then not Abort then
5121 -- Raise_From_Controlled_Operation (E);
5130 function New_References_To
5132 Loc
: Source_Ptr
) return List_Id
;
5133 -- Given a list of defining identifiers, return a list of references to
5134 -- the original identifiers, in the same order as they appear.
5136 -----------------------------------------
5137 -- Build_Adjust_Or_Finalize_Statements --
5138 -----------------------------------------
5140 function Build_Adjust_Or_Finalize_Statements
5141 (Typ
: Entity_Id
) return List_Id
5143 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5144 Index_List
: constant List_Id
:= New_List
;
5145 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5146 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5147 Finalizer_Decls
: List_Id
:= No_List
;
5148 Finalizer_Data
: Finalization_Exception_Data
;
5151 Core_Loop
: Node_Id
;
5154 Loop_Id
: Entity_Id
;
5157 Exceptions_OK
: constant Boolean :=
5158 not Restriction_Active
(No_Exception_Propagation
);
5160 procedure Build_Indexes
;
5161 -- Generate the indexes used in the dimension loops
5167 procedure Build_Indexes
is
5169 -- Generate the following identifiers:
5170 -- Jnn - for initialization
5172 for Dim
in 1 .. Num_Dims
loop
5173 Append_To
(Index_List
,
5174 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5178 -- Start of processing for Build_Adjust_Or_Finalize_Statements
5181 Finalizer_Decls
:= New_List
;
5184 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
5187 Make_Indexed_Component
(Loc
,
5188 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5189 Expressions
=> New_References_To
(Index_List
, Loc
));
5190 Set_Etype
(Comp_Ref
, Comp_Typ
);
5193 -- [Deep_]Adjust (V (J1, ..., JN))
5195 if Prim
= Adjust_Case
then
5196 Call
:= Make_Adjust_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5199 -- [Deep_]Finalize (V (J1, ..., JN))
5201 else pragma Assert
(Prim
= Finalize_Case
);
5202 Call
:= Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5205 -- Generate the block which houses the adjust or finalize call:
5207 -- <adjust or finalize call>; -- No_Exception_Propagation
5209 -- begin -- Exception handlers allowed
5210 -- <adjust or finalize call>
5214 -- if not Raised then
5216 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5220 if Exceptions_OK
then
5222 Make_Block_Statement
(Loc
,
5223 Handled_Statement_Sequence
=>
5224 Make_Handled_Sequence_Of_Statements
(Loc
,
5225 Statements
=> New_List
(Call
),
5226 Exception_Handlers
=> New_List
(
5227 Build_Exception_Handler
(Finalizer_Data
))));
5232 -- Generate the dimension loops starting from the innermost one
5234 -- for Jnn in [reverse] V'Range (Dim) loop
5238 J
:= Last
(Index_List
);
5240 while Present
(J
) and then Dim
> 0 loop
5246 Make_Loop_Statement
(Loc
,
5248 Make_Iteration_Scheme
(Loc
,
5249 Loop_Parameter_Specification
=>
5250 Make_Loop_Parameter_Specification
(Loc
,
5251 Defining_Identifier
=> Loop_Id
,
5252 Discrete_Subtype_Definition
=>
5253 Make_Attribute_Reference
(Loc
,
5254 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5255 Attribute_Name
=> Name_Range
,
5256 Expressions
=> New_List
(
5257 Make_Integer_Literal
(Loc
, Dim
))),
5259 Reverse_Present
=> Prim
= Finalize_Case
)),
5261 Statements
=> New_List
(Core_Loop
),
5262 End_Label
=> Empty
);
5267 -- Generate the block which contains the core loop, the declarations
5268 -- of the abort flag, the exception occurrence, the raised flag and
5269 -- the conditional raise:
5272 -- Abort : constant Boolean := Triggered_By_Abort;
5274 -- Abort : constant Boolean := False; -- no abort
5276 -- E : Exception_Occurrence;
5277 -- Raised : Boolean := False;
5282 -- if Raised and then not Abort then -- Expection handlers OK
5283 -- Raise_From_Controlled_Operation (E);
5287 Stmts
:= New_List
(Core_Loop
);
5289 if Exceptions_OK
then
5291 Build_Raise_Statement
(Finalizer_Data
));
5296 Make_Block_Statement
(Loc
,
5299 Handled_Statement_Sequence
=>
5300 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
)));
5301 end Build_Adjust_Or_Finalize_Statements
;
5303 ---------------------------------
5304 -- Build_Initialize_Statements --
5305 ---------------------------------
5307 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
is
5308 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5309 Final_List
: constant List_Id
:= New_List
;
5310 Index_List
: constant List_Id
:= New_List
;
5311 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5312 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5313 Counter_Id
: Entity_Id
;
5317 Final_Block
: Node_Id
;
5318 Final_Loop
: Node_Id
;
5319 Finalizer_Data
: Finalization_Exception_Data
;
5320 Finalizer_Decls
: List_Id
:= No_List
;
5321 Init_Loop
: Node_Id
;
5326 Exceptions_OK
: constant Boolean :=
5327 not Restriction_Active
(No_Exception_Propagation
);
5329 function Build_Counter_Assignment
return Node_Id
;
5330 -- Generate the following assignment:
5331 -- Counter := V'Length (1) *
5333 -- V'Length (N) - Counter;
5335 function Build_Finalization_Call
return Node_Id
;
5336 -- Generate a deep finalization call for an array element
5338 procedure Build_Indexes
;
5339 -- Generate the initialization and finalization indexes used in the
5342 function Build_Initialization_Call
return Node_Id
;
5343 -- Generate a deep initialization call for an array element
5345 ------------------------------
5346 -- Build_Counter_Assignment --
5347 ------------------------------
5349 function Build_Counter_Assignment
return Node_Id
is
5354 -- Start from the first dimension and generate:
5359 Make_Attribute_Reference
(Loc
,
5360 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5361 Attribute_Name
=> Name_Length
,
5362 Expressions
=> New_List
(Make_Integer_Literal
(Loc
, Dim
)));
5364 -- Process the rest of the dimensions, generate:
5365 -- Expr * V'Length (N)
5368 while Dim
<= Num_Dims
loop
5370 Make_Op_Multiply
(Loc
,
5373 Make_Attribute_Reference
(Loc
,
5374 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5375 Attribute_Name
=> Name_Length
,
5376 Expressions
=> New_List
(
5377 Make_Integer_Literal
(Loc
, Dim
))));
5383 -- Counter := Expr - Counter;
5386 Make_Assignment_Statement
(Loc
,
5387 Name
=> New_Reference_To
(Counter_Id
, Loc
),
5389 Make_Op_Subtract
(Loc
,
5391 Right_Opnd
=> New_Reference_To
(Counter_Id
, Loc
)));
5392 end Build_Counter_Assignment
;
5394 -----------------------------
5395 -- Build_Finalization_Call --
5396 -----------------------------
5398 function Build_Finalization_Call
return Node_Id
is
5399 Comp_Ref
: constant Node_Id
:=
5400 Make_Indexed_Component
(Loc
,
5401 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5402 Expressions
=> New_References_To
(Final_List
, Loc
));
5405 Set_Etype
(Comp_Ref
, Comp_Typ
);
5408 -- [Deep_]Finalize (V);
5410 return Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5411 end Build_Finalization_Call
;
5417 procedure Build_Indexes
is
5419 -- Generate the following identifiers:
5420 -- Jnn - for initialization
5421 -- Fnn - for finalization
5423 for Dim
in 1 .. Num_Dims
loop
5424 Append_To
(Index_List
,
5425 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5427 Append_To
(Final_List
,
5428 Make_Defining_Identifier
(Loc
, New_External_Name
('F', Dim
)));
5432 -------------------------------
5433 -- Build_Initialization_Call --
5434 -------------------------------
5436 function Build_Initialization_Call
return Node_Id
is
5437 Comp_Ref
: constant Node_Id
:=
5438 Make_Indexed_Component
(Loc
,
5439 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5440 Expressions
=> New_References_To
(Index_List
, Loc
));
5443 Set_Etype
(Comp_Ref
, Comp_Typ
);
5446 -- [Deep_]Initialize (V (J1, ..., JN));
5448 return Make_Init_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5449 end Build_Initialization_Call
;
5451 -- Start of processing for Build_Initialize_Statements
5454 Counter_Id
:= Make_Temporary
(Loc
, 'C');
5455 Finalizer_Decls
:= New_List
;
5458 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
5460 -- Generate the block which houses the finalization call, the index
5461 -- guard and the handler which triggers Program_Error later on.
5463 -- if Counter > 0 then
5464 -- Counter := Counter - 1;
5466 -- [Deep_]Finalize (V (F1, ..., FN)); -- No_Except_Propagation
5468 -- begin -- Exceptions allowed
5469 -- [Deep_]Finalize (V (F1, ..., FN));
5472 -- if not Raised then
5474 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5479 if Exceptions_OK
then
5481 Make_Block_Statement
(Loc
,
5482 Handled_Statement_Sequence
=>
5483 Make_Handled_Sequence_Of_Statements
(Loc
,
5484 Statements
=> New_List
(Build_Finalization_Call
),
5485 Exception_Handlers
=> New_List
(
5486 Build_Exception_Handler
(Finalizer_Data
))));
5488 Fin_Stmt
:= Build_Finalization_Call
;
5491 -- This is the core of the loop, the dimension iterators are added
5492 -- one by one in reverse.
5495 Make_If_Statement
(Loc
,
5498 Left_Opnd
=> New_Reference_To
(Counter_Id
, Loc
),
5499 Right_Opnd
=> Make_Integer_Literal
(Loc
, 0)),
5501 Then_Statements
=> New_List
(
5502 Make_Assignment_Statement
(Loc
,
5503 Name
=> New_Reference_To
(Counter_Id
, Loc
),
5505 Make_Op_Subtract
(Loc
,
5506 Left_Opnd
=> New_Reference_To
(Counter_Id
, Loc
),
5507 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)))),
5509 Else_Statements
=> New_List
(Fin_Stmt
));
5511 -- Generate all finalization loops starting from the innermost
5514 -- for Fnn in reverse V'Range (Dim) loop
5518 F
:= Last
(Final_List
);
5520 while Present
(F
) and then Dim
> 0 loop
5526 Make_Loop_Statement
(Loc
,
5528 Make_Iteration_Scheme
(Loc
,
5529 Loop_Parameter_Specification
=>
5530 Make_Loop_Parameter_Specification
(Loc
,
5531 Defining_Identifier
=> Loop_Id
,
5532 Discrete_Subtype_Definition
=>
5533 Make_Attribute_Reference
(Loc
,
5534 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5535 Attribute_Name
=> Name_Range
,
5536 Expressions
=> New_List
(
5537 Make_Integer_Literal
(Loc
, Dim
))),
5539 Reverse_Present
=> True)),
5541 Statements
=> New_List
(Final_Loop
),
5542 End_Label
=> Empty
);
5547 -- Generate the block which contains the finalization loops, the
5548 -- declarations of the abort flag, the exception occurrence, the
5549 -- raised flag and the conditional raise.
5552 -- Abort : constant Boolean := Triggered_By_Abort;
5554 -- Abort : constant Boolean := False; -- no abort
5556 -- E : Exception_Occurrence;
5557 -- Raised : Boolean := False;
5563 -- V'Length (N) - Counter;
5567 -- if Raised and then not Abort then -- Exception handlers OK
5568 -- Raise_From_Controlled_Operation (E);
5571 -- raise; -- Exception handlers OK
5574 Stmts
:= New_List
(Build_Counter_Assignment
, Final_Loop
);
5576 if Exceptions_OK
then
5578 Build_Raise_Statement
(Finalizer_Data
));
5579 Append_To
(Stmts
, Make_Raise_Statement
(Loc
));
5583 Make_Block_Statement
(Loc
,
5586 Handled_Statement_Sequence
=>
5587 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
));
5589 -- Generate the block which contains the initialization call and
5590 -- the partial finalization code.
5593 -- [Deep_]Initialize (V (J1, ..., JN));
5595 -- Counter := Counter + 1;
5599 -- <finalization code>
5603 Make_Block_Statement
(Loc
,
5604 Handled_Statement_Sequence
=>
5605 Make_Handled_Sequence_Of_Statements
(Loc
,
5606 Statements
=> New_List
(Build_Initialization_Call
),
5607 Exception_Handlers
=> New_List
(
5608 Make_Exception_Handler
(Loc
,
5609 Exception_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
5610 Statements
=> New_List
(Final_Block
)))));
5612 Append_To
(Statements
(Handled_Statement_Sequence
(Init_Loop
)),
5613 Make_Assignment_Statement
(Loc
,
5614 Name
=> New_Reference_To
(Counter_Id
, Loc
),
5617 Left_Opnd
=> New_Reference_To
(Counter_Id
, Loc
),
5618 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1))));
5620 -- Generate all initialization loops starting from the innermost
5623 -- for Jnn in V'Range (Dim) loop
5627 J
:= Last
(Index_List
);
5629 while Present
(J
) and then Dim
> 0 loop
5635 Make_Loop_Statement
(Loc
,
5637 Make_Iteration_Scheme
(Loc
,
5638 Loop_Parameter_Specification
=>
5639 Make_Loop_Parameter_Specification
(Loc
,
5640 Defining_Identifier
=> Loop_Id
,
5641 Discrete_Subtype_Definition
=>
5642 Make_Attribute_Reference
(Loc
,
5643 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5644 Attribute_Name
=> Name_Range
,
5645 Expressions
=> New_List
(
5646 Make_Integer_Literal
(Loc
, Dim
))))),
5648 Statements
=> New_List
(Init_Loop
),
5649 End_Label
=> Empty
);
5654 -- Generate the block which contains the counter variable and the
5655 -- initialization loops.
5658 -- Counter : Integer := 0;
5665 Make_Block_Statement
(Loc
,
5666 Declarations
=> New_List
(
5667 Make_Object_Declaration
(Loc
,
5668 Defining_Identifier
=> Counter_Id
,
5669 Object_Definition
=>
5670 New_Reference_To
(Standard_Integer
, Loc
),
5671 Expression
=> Make_Integer_Literal
(Loc
, 0))),
5673 Handled_Statement_Sequence
=>
5674 Make_Handled_Sequence_Of_Statements
(Loc
,
5675 Statements
=> New_List
(Init_Loop
))));
5676 end Build_Initialize_Statements
;
5678 -----------------------
5679 -- New_References_To --
5680 -----------------------
5682 function New_References_To
5684 Loc
: Source_Ptr
) return List_Id
5686 Refs
: constant List_Id
:= New_List
;
5691 while Present
(Id
) loop
5692 Append_To
(Refs
, New_Reference_To
(Id
, Loc
));
5697 end New_References_To
;
5699 -- Start of processing for Make_Deep_Array_Body
5703 when Address_Case
=>
5704 return Make_Finalize_Address_Stmts
(Typ
);
5708 return Build_Adjust_Or_Finalize_Statements
(Typ
);
5710 when Initialize_Case
=>
5711 return Build_Initialize_Statements
(Typ
);
5713 end Make_Deep_Array_Body
;
5715 --------------------
5716 -- Make_Deep_Proc --
5717 --------------------
5719 function Make_Deep_Proc
5720 (Prim
: Final_Primitives
;
5722 Stmts
: List_Id
) return Entity_Id
5724 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5726 Proc_Id
: Entity_Id
;
5729 -- Create the object formal, generate:
5730 -- V : System.Address
5732 if Prim
= Address_Case
then
5733 Formals
:= New_List
(
5734 Make_Parameter_Specification
(Loc
,
5735 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
5736 Parameter_Type
=> New_Reference_To
(RTE
(RE_Address
), Loc
)));
5743 Formals
:= New_List
(
5744 Make_Parameter_Specification
(Loc
,
5745 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
5747 Out_Present
=> True,
5748 Parameter_Type
=> New_Reference_To
(Typ
, Loc
)));
5750 -- F : Boolean := True
5752 if Prim
= Adjust_Case
5753 or else Prim
= Finalize_Case
5756 Make_Parameter_Specification
(Loc
,
5757 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
5759 New_Reference_To
(Standard_Boolean
, Loc
),
5761 New_Reference_To
(Standard_True
, Loc
)));
5766 Make_Defining_Identifier
(Loc
,
5767 Chars
=> Make_TSS_Name
(Typ
, Deep_Name_Of
(Prim
)));
5770 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5773 -- exception -- Finalize and Adjust cases only
5774 -- raise Program_Error;
5775 -- end Deep_Initialize / Adjust / Finalize;
5779 -- procedure Finalize_Address (V : System.Address) is
5782 -- end Finalize_Address;
5785 Make_Subprogram_Body
(Loc
,
5787 Make_Procedure_Specification
(Loc
,
5788 Defining_Unit_Name
=> Proc_Id
,
5789 Parameter_Specifications
=> Formals
),
5791 Declarations
=> Empty_List
,
5793 Handled_Statement_Sequence
=>
5794 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
)));
5799 ---------------------------
5800 -- Make_Deep_Record_Body --
5801 ---------------------------
5803 function Make_Deep_Record_Body
5804 (Prim
: Final_Primitives
;
5806 Is_Local
: Boolean := False) return List_Id
5808 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
;
5809 -- Build the statements necessary to adjust a record type. The type may
5810 -- have discriminants and contain variant parts. Generate:
5814 -- [Deep_]Adjust (V.Comp_1);
5816 -- when Id : others =>
5817 -- if not Raised then
5819 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5824 -- [Deep_]Adjust (V.Comp_N);
5826 -- when Id : others =>
5827 -- if not Raised then
5829 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5834 -- Deep_Adjust (V._parent, False); -- If applicable
5836 -- when Id : others =>
5837 -- if not Raised then
5839 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5845 -- Adjust (V); -- If applicable
5848 -- if not Raised then
5850 -- Save_Occurence (E, Get_Current_Excep.all.all);
5855 -- if Raised and then not Abort then
5856 -- Raise_From_Controlled_Operation (E);
5860 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
;
5861 -- Build the statements necessary to finalize a record type. The type
5862 -- may have discriminants and contain variant parts. Generate:
5865 -- Abort : constant Boolean := Triggered_By_Abort;
5867 -- Abort : constant Boolean := False; -- no abort
5868 -- E : Exception_Occurence;
5869 -- Raised : Boolean := False;
5874 -- Finalize (V); -- If applicable
5877 -- if not Raised then
5879 -- Save_Occurence (E, Get_Current_Excep.all.all);
5884 -- case Variant_1 is
5886 -- case State_Counter_N => -- If Is_Local is enabled
5896 -- <<LN>> -- If Is_Local is enabled
5898 -- [Deep_]Finalize (V.Comp_N);
5901 -- if not Raised then
5903 -- Save_Occurence (E, Get_Current_Excep.all.all);
5909 -- [Deep_]Finalize (V.Comp_1);
5912 -- if not Raised then
5914 -- Save_Occurence (E, Get_Current_Excep.all.all);
5920 -- case State_Counter_1 => -- If Is_Local is enabled
5926 -- Deep_Finalize (V._parent, False); -- If applicable
5928 -- when Id : others =>
5929 -- if not Raised then
5931 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5935 -- if Raised and then not Abort then
5936 -- Raise_From_Controlled_Operation (E);
5940 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
;
5941 -- Given a derived tagged type Typ, traverse all components, find field
5942 -- _parent and return its type.
5944 procedure Preprocess_Components
5946 Num_Comps
: out Int
;
5947 Has_POC
: out Boolean);
5948 -- Examine all components in component list Comps, count all controlled
5949 -- components and determine whether at least one of them is per-object
5950 -- constrained. Component _parent is always skipped.
5952 -----------------------------
5953 -- Build_Adjust_Statements --
5954 -----------------------------
5956 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
is
5957 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5958 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
5959 Bod_Stmts
: List_Id
;
5960 Finalizer_Data
: Finalization_Exception_Data
;
5961 Finalizer_Decls
: List_Id
:= No_List
;
5965 Exceptions_OK
: constant Boolean :=
5966 not Restriction_Active
(No_Exception_Propagation
);
5968 function Process_Component_List_For_Adjust
5969 (Comps
: Node_Id
) return List_Id
;
5970 -- Build all necessary adjust statements for a single component list
5972 ---------------------------------------
5973 -- Process_Component_List_For_Adjust --
5974 ---------------------------------------
5976 function Process_Component_List_For_Adjust
5977 (Comps
: Node_Id
) return List_Id
5979 Stmts
: constant List_Id
:= New_List
;
5981 Decl_Id
: Entity_Id
;
5982 Decl_Typ
: Entity_Id
;
5986 procedure Process_Component_For_Adjust
(Decl
: Node_Id
);
5987 -- Process the declaration of a single controlled component
5989 ----------------------------------
5990 -- Process_Component_For_Adjust --
5991 ----------------------------------
5993 procedure Process_Component_For_Adjust
(Decl
: Node_Id
) is
5994 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
5995 Typ
: constant Entity_Id
:= Etype
(Id
);
6000 -- [Deep_]Adjust (V.Id); -- No_Exception_Propagation
6002 -- begin -- Exception handlers allowed
6003 -- [Deep_]Adjust (V.Id);
6006 -- if not Raised then
6008 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6015 Make_Selected_Component
(Loc
,
6016 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6017 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
6020 if Exceptions_OK
then
6022 Make_Block_Statement
(Loc
,
6023 Handled_Statement_Sequence
=>
6024 Make_Handled_Sequence_Of_Statements
(Loc
,
6025 Statements
=> New_List
(Adj_Stmt
),
6026 Exception_Handlers
=> New_List
(
6027 Build_Exception_Handler
(Finalizer_Data
))));
6030 Append_To
(Stmts
, Adj_Stmt
);
6031 end Process_Component_For_Adjust
;
6033 -- Start of processing for Process_Component_List_For_Adjust
6036 -- Perform an initial check, determine the number of controlled
6037 -- components in the current list and whether at least one of them
6038 -- is per-object constrained.
6040 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
6042 -- The processing in this routine is done in the following order:
6043 -- 1) Regular components
6044 -- 2) Per-object constrained components
6047 if Num_Comps
> 0 then
6049 -- Process all regular components in order of declarations
6051 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6052 while Present
(Decl
) loop
6053 Decl_Id
:= Defining_Identifier
(Decl
);
6054 Decl_Typ
:= Etype
(Decl_Id
);
6056 -- Skip _parent as well as per-object constrained components
6058 if Chars
(Decl_Id
) /= Name_uParent
6059 and then Needs_Finalization
(Decl_Typ
)
6061 if Has_Access_Constraint
(Decl_Id
)
6062 and then No
(Expression
(Decl
))
6066 Process_Component_For_Adjust
(Decl
);
6070 Next_Non_Pragma
(Decl
);
6073 -- Process all per-object constrained components in order of
6077 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6078 while Present
(Decl
) loop
6079 Decl_Id
:= Defining_Identifier
(Decl
);
6080 Decl_Typ
:= Etype
(Decl_Id
);
6084 if Chars
(Decl_Id
) /= Name_uParent
6085 and then Needs_Finalization
(Decl_Typ
)
6086 and then Has_Access_Constraint
(Decl_Id
)
6087 and then No
(Expression
(Decl
))
6089 Process_Component_For_Adjust
(Decl
);
6092 Next_Non_Pragma
(Decl
);
6097 -- Process all variants, if any
6100 if Present
(Variant_Part
(Comps
)) then
6102 Var_Alts
: constant List_Id
:= New_List
;
6106 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
6107 while Present
(Var
) loop
6110 -- when <discrete choices> =>
6111 -- <adjust statements>
6113 Append_To
(Var_Alts
,
6114 Make_Case_Statement_Alternative
(Loc
,
6116 New_Copy_List
(Discrete_Choices
(Var
)),
6118 Process_Component_List_For_Adjust
(
6119 Component_List
(Var
))));
6121 Next_Non_Pragma
(Var
);
6125 -- case V.<discriminant> is
6126 -- when <discrete choices 1> =>
6127 -- <adjust statements 1>
6129 -- when <discrete choices N> =>
6130 -- <adjust statements N>
6134 Make_Case_Statement
(Loc
,
6136 Make_Selected_Component
(Loc
,
6137 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6139 Make_Identifier
(Loc
,
6140 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
6141 Alternatives
=> Var_Alts
);
6145 -- Add the variant case statement to the list of statements
6147 if Present
(Var_Case
) then
6148 Append_To
(Stmts
, Var_Case
);
6151 -- If the component list did not have any controlled components
6152 -- nor variants, return null.
6154 if Is_Empty_List
(Stmts
) then
6155 Append_To
(Stmts
, Make_Null_Statement
(Loc
));
6159 end Process_Component_List_For_Adjust
;
6161 -- Start of processing for Build_Adjust_Statements
6164 Finalizer_Decls
:= New_List
;
6165 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
6167 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
6168 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
6173 -- Create an adjust sequence for all record components
6175 if Present
(Component_List
(Rec_Def
)) then
6177 Process_Component_List_For_Adjust
(Component_List
(Rec_Def
));
6180 -- A derived record type must adjust all inherited components. This
6181 -- action poses the following problem:
6183 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
6188 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
6190 -- Deep_Adjust (Obj._parent);
6195 -- Adjusting the derived type will invoke Adjust of the parent and
6196 -- then that of the derived type. This is undesirable because both
6197 -- routines may modify shared components. Only the Adjust of the
6198 -- derived type should be invoked.
6200 -- To prevent this double adjustment of shared components,
6201 -- Deep_Adjust uses a flag to control the invocation of Adjust:
6203 -- procedure Deep_Adjust
6204 -- (Obj : in out Some_Type;
6205 -- Flag : Boolean := True)
6213 -- When Deep_Adjust is invokes for field _parent, a value of False is
6214 -- provided for the flag:
6216 -- Deep_Adjust (Obj._parent, False);
6218 if Is_Tagged_Type
(Typ
) and then Is_Derived_Type
(Typ
) then
6220 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
6225 if Needs_Finalization
(Par_Typ
) then
6229 Make_Selected_Component
(Loc
,
6230 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6232 Make_Identifier
(Loc
, Name_uParent
)),
6234 For_Parent
=> True);
6237 -- Deep_Adjust (V._parent, False); -- No_Except_Propagat
6239 -- begin -- Exceptions OK
6240 -- Deep_Adjust (V._parent, False);
6242 -- when Id : others =>
6243 -- if not Raised then
6245 -- Save_Occurrence (E,
6246 -- Get_Current_Excep.all.all);
6250 if Present
(Call
) then
6253 if Exceptions_OK
then
6255 Make_Block_Statement
(Loc
,
6256 Handled_Statement_Sequence
=>
6257 Make_Handled_Sequence_Of_Statements
(Loc
,
6258 Statements
=> New_List
(Adj_Stmt
),
6259 Exception_Handlers
=> New_List
(
6260 Build_Exception_Handler
(Finalizer_Data
))));
6263 Prepend_To
(Bod_Stmts
, Adj_Stmt
);
6269 -- Adjust the object. This action must be performed last after all
6270 -- components have been adjusted.
6272 if Is_Controlled
(Typ
) then
6278 Proc
:= Find_Prim_Op
(Typ
, Name_Adjust
);
6282 -- Adjust (V); -- No_Exception_Propagation
6284 -- begin -- Exception handlers allowed
6288 -- if not Raised then
6290 -- Save_Occurrence (E,
6291 -- Get_Current_Excep.all.all);
6296 if Present
(Proc
) then
6298 Make_Procedure_Call_Statement
(Loc
,
6299 Name
=> New_Reference_To
(Proc
, Loc
),
6300 Parameter_Associations
=> New_List
(
6301 Make_Identifier
(Loc
, Name_V
)));
6303 if Exceptions_OK
then
6305 Make_Block_Statement
(Loc
,
6306 Handled_Statement_Sequence
=>
6307 Make_Handled_Sequence_Of_Statements
(Loc
,
6308 Statements
=> New_List
(Adj_Stmt
),
6309 Exception_Handlers
=> New_List
(
6310 Build_Exception_Handler
6311 (Finalizer_Data
))));
6314 Append_To
(Bod_Stmts
,
6315 Make_If_Statement
(Loc
,
6316 Condition
=> Make_Identifier
(Loc
, Name_F
),
6317 Then_Statements
=> New_List
(Adj_Stmt
)));
6322 -- At this point either all adjustment statements have been generated
6323 -- or the type is not controlled.
6325 if Is_Empty_List
(Bod_Stmts
) then
6326 Append_To
(Bod_Stmts
, Make_Null_Statement
(Loc
));
6332 -- Abort : constant Boolean := Triggered_By_Abort;
6334 -- Abort : constant Boolean := False; -- no abort
6336 -- E : Exception_Occurence;
6337 -- Raised : Boolean := False;
6340 -- <adjust statements>
6342 -- if Raised and then not Abort then
6343 -- Raise_From_Controlled_Operation (E);
6348 if Exceptions_OK
then
6349 Append_To
(Bod_Stmts
,
6350 Build_Raise_Statement
(Finalizer_Data
));
6355 Make_Block_Statement
(Loc
,
6358 Handled_Statement_Sequence
=>
6359 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
6361 end Build_Adjust_Statements
;
6363 -------------------------------
6364 -- Build_Finalize_Statements --
6365 -------------------------------
6367 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
is
6368 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6369 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
6370 Bod_Stmts
: List_Id
;
6372 Finalizer_Data
: Finalization_Exception_Data
;
6373 Finalizer_Decls
: List_Id
:= No_List
;
6377 Exceptions_OK
: constant Boolean :=
6378 not Restriction_Active
(No_Exception_Propagation
);
6380 function Process_Component_List_For_Finalize
6381 (Comps
: Node_Id
) return List_Id
;
6382 -- Build all necessary finalization statements for a single component
6383 -- list. The statements may include a jump circuitry if flag Is_Local
6386 -----------------------------------------
6387 -- Process_Component_List_For_Finalize --
6388 -----------------------------------------
6390 function Process_Component_List_For_Finalize
6391 (Comps
: Node_Id
) return List_Id
6394 Counter_Id
: Entity_Id
;
6396 Decl_Id
: Entity_Id
;
6397 Decl_Typ
: Entity_Id
;
6400 Jump_Block
: Node_Id
;
6402 Label_Id
: Entity_Id
;
6406 procedure Process_Component_For_Finalize
6411 -- Process the declaration of a single controlled component. If
6412 -- flag Is_Local is enabled, create the corresponding label and
6413 -- jump circuitry. Alts is the list of case alternatives, Decls
6414 -- is the top level declaration list where labels are declared
6415 -- and Stmts is the list of finalization actions.
6417 ------------------------------------
6418 -- Process_Component_For_Finalize --
6419 ------------------------------------
6421 procedure Process_Component_For_Finalize
6427 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
6428 Typ
: constant Entity_Id
:= Etype
(Id
);
6435 Label_Id
: Entity_Id
;
6442 Make_Identifier
(Loc
,
6443 Chars
=> New_External_Name
('L', Num_Comps
));
6444 Set_Entity
(Label_Id
,
6445 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
6446 Label
:= Make_Label
(Loc
, Label_Id
);
6449 Make_Implicit_Label_Declaration
(Loc
,
6450 Defining_Identifier
=> Entity
(Label_Id
),
6451 Label_Construct
=> Label
));
6458 Make_Case_Statement_Alternative
(Loc
,
6459 Discrete_Choices
=> New_List
(
6460 Make_Integer_Literal
(Loc
, Num_Comps
)),
6462 Statements
=> New_List
(
6463 Make_Goto_Statement
(Loc
,
6465 New_Reference_To
(Entity
(Label_Id
), Loc
)))));
6470 Append_To
(Stmts
, Label
);
6472 -- Decrease the number of components to be processed.
6473 -- This action yields a new Label_Id in future calls.
6475 Num_Comps
:= Num_Comps
- 1;
6480 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
6482 -- begin -- Exception handlers allowed
6483 -- [Deep_]Finalize (V.Id);
6486 -- if not Raised then
6488 -- Save_Occurrence (E,
6489 -- Get_Current_Excep.all.all);
6496 Make_Selected_Component
(Loc
,
6497 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6498 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
6501 if not Restriction_Active
(No_Exception_Propagation
) then
6503 Make_Block_Statement
(Loc
,
6504 Handled_Statement_Sequence
=>
6505 Make_Handled_Sequence_Of_Statements
(Loc
,
6506 Statements
=> New_List
(Fin_Stmt
),
6507 Exception_Handlers
=> New_List
(
6508 Build_Exception_Handler
(Finalizer_Data
))));
6511 Append_To
(Stmts
, Fin_Stmt
);
6512 end Process_Component_For_Finalize
;
6514 -- Start of processing for Process_Component_List_For_Finalize
6517 -- Perform an initial check, look for controlled and per-object
6518 -- constrained components.
6520 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
6522 -- Create a state counter to service the current component list.
6523 -- This step is performed before the variants are inspected in
6524 -- order to generate the same state counter names as those from
6525 -- Build_Initialize_Statements.
6530 Counter
:= Counter
+ 1;
6533 Make_Defining_Identifier
(Loc
,
6534 Chars
=> New_External_Name
('C', Counter
));
6537 -- Process the component in the following order:
6539 -- 2) Per-object constrained components
6540 -- 3) Regular components
6542 -- Start with the variant parts
6545 if Present
(Variant_Part
(Comps
)) then
6547 Var_Alts
: constant List_Id
:= New_List
;
6551 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
6552 while Present
(Var
) loop
6555 -- when <discrete choices> =>
6556 -- <finalize statements>
6558 Append_To
(Var_Alts
,
6559 Make_Case_Statement_Alternative
(Loc
,
6561 New_Copy_List
(Discrete_Choices
(Var
)),
6563 Process_Component_List_For_Finalize
(
6564 Component_List
(Var
))));
6566 Next_Non_Pragma
(Var
);
6570 -- case V.<discriminant> is
6571 -- when <discrete choices 1> =>
6572 -- <finalize statements 1>
6574 -- when <discrete choices N> =>
6575 -- <finalize statements N>
6579 Make_Case_Statement
(Loc
,
6581 Make_Selected_Component
(Loc
,
6582 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6584 Make_Identifier
(Loc
,
6585 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
6586 Alternatives
=> Var_Alts
);
6590 -- The current component list does not have a single controlled
6591 -- component, however it may contain variants. Return the case
6592 -- statement for the variants or nothing.
6594 if Num_Comps
= 0 then
6595 if Present
(Var_Case
) then
6596 return New_List
(Var_Case
);
6598 return New_List
(Make_Null_Statement
(Loc
));
6602 -- Prepare all lists
6608 -- Process all per-object constrained components in reverse order
6611 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
6612 while Present
(Decl
) loop
6613 Decl_Id
:= Defining_Identifier
(Decl
);
6614 Decl_Typ
:= Etype
(Decl_Id
);
6618 if Chars
(Decl_Id
) /= Name_uParent
6619 and then Needs_Finalization
(Decl_Typ
)
6620 and then Has_Access_Constraint
(Decl_Id
)
6621 and then No
(Expression
(Decl
))
6623 Process_Component_For_Finalize
(Decl
, Alts
, Decls
, Stmts
);
6626 Prev_Non_Pragma
(Decl
);
6630 -- Process the rest of the components in reverse order
6632 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
6633 while Present
(Decl
) loop
6634 Decl_Id
:= Defining_Identifier
(Decl
);
6635 Decl_Typ
:= Etype
(Decl_Id
);
6639 if Chars
(Decl_Id
) /= Name_uParent
6640 and then Needs_Finalization
(Decl_Typ
)
6642 -- Skip per-object constrained components since they were
6643 -- handled in the above step.
6645 if Has_Access_Constraint
(Decl_Id
)
6646 and then No
(Expression
(Decl
))
6650 Process_Component_For_Finalize
(Decl
, Alts
, Decls
, Stmts
);
6654 Prev_Non_Pragma
(Decl
);
6659 -- LN : label; -- If Is_Local is enabled
6664 -- case CounterX is .
6674 -- <<LN>> -- If Is_Local is enabled
6676 -- [Deep_]Finalize (V.CompY);
6678 -- when Id : others =>
6679 -- if not Raised then
6681 -- Save_Occurrence (E,
6682 -- Get_Current_Excep.all.all);
6686 -- <<L0>> -- If Is_Local is enabled
6691 -- Add the declaration of default jump location L0, its
6692 -- corresponding alternative and its place in the statements.
6694 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
6695 Set_Entity
(Label_Id
,
6696 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
6697 Label
:= Make_Label
(Loc
, Label_Id
);
6699 Append_To
(Decls
, -- declaration
6700 Make_Implicit_Label_Declaration
(Loc
,
6701 Defining_Identifier
=> Entity
(Label_Id
),
6702 Label_Construct
=> Label
));
6704 Append_To
(Alts
, -- alternative
6705 Make_Case_Statement_Alternative
(Loc
,
6706 Discrete_Choices
=> New_List
(
6707 Make_Others_Choice
(Loc
)),
6709 Statements
=> New_List
(
6710 Make_Goto_Statement
(Loc
,
6711 Name
=> New_Reference_To
(Entity
(Label_Id
), Loc
)))));
6713 Append_To
(Stmts
, Label
); -- statement
6715 -- Create the jump block
6718 Make_Case_Statement
(Loc
,
6719 Expression
=> Make_Identifier
(Loc
, Chars
(Counter_Id
)),
6720 Alternatives
=> Alts
));
6724 Make_Block_Statement
(Loc
,
6725 Declarations
=> Decls
,
6726 Handled_Statement_Sequence
=>
6727 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
));
6729 if Present
(Var_Case
) then
6730 return New_List
(Var_Case
, Jump_Block
);
6732 return New_List
(Jump_Block
);
6734 end Process_Component_List_For_Finalize
;
6736 -- Start of processing for Build_Finalize_Statements
6739 Finalizer_Decls
:= New_List
;
6740 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
6742 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
6743 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
6748 -- Create a finalization sequence for all record components
6750 if Present
(Component_List
(Rec_Def
)) then
6752 Process_Component_List_For_Finalize
(Component_List
(Rec_Def
));
6755 -- A derived record type must finalize all inherited components. This
6756 -- action poses the following problem:
6758 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
6763 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
6765 -- Deep_Finalize (Obj._parent);
6770 -- Finalizing the derived type will invoke Finalize of the parent and
6771 -- then that of the derived type. This is undesirable because both
6772 -- routines may modify shared components. Only the Finalize of the
6773 -- derived type should be invoked.
6775 -- To prevent this double adjustment of shared components,
6776 -- Deep_Finalize uses a flag to control the invocation of Finalize:
6778 -- procedure Deep_Finalize
6779 -- (Obj : in out Some_Type;
6780 -- Flag : Boolean := True)
6788 -- When Deep_Finalize is invokes for field _parent, a value of False
6789 -- is provided for the flag:
6791 -- Deep_Finalize (Obj._parent, False);
6793 if Is_Tagged_Type
(Typ
)
6794 and then Is_Derived_Type
(Typ
)
6797 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
6802 if Needs_Finalization
(Par_Typ
) then
6806 Make_Selected_Component
(Loc
,
6807 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6809 Make_Identifier
(Loc
, Name_uParent
)),
6811 For_Parent
=> True);
6814 -- Deep_Finalize (V._parent, False); -- No_Except_Propag
6816 -- begin -- Exceptions OK
6817 -- Deep_Finalize (V._parent, False);
6819 -- when Id : others =>
6820 -- if not Raised then
6822 -- Save_Occurrence (E,
6823 -- Get_Current_Excep.all.all);
6827 if Present
(Call
) then
6830 if Exceptions_OK
then
6832 Make_Block_Statement
(Loc
,
6833 Handled_Statement_Sequence
=>
6834 Make_Handled_Sequence_Of_Statements
(Loc
,
6835 Statements
=> New_List
(Fin_Stmt
),
6836 Exception_Handlers
=> New_List
(
6837 Build_Exception_Handler
6838 (Finalizer_Data
))));
6841 Append_To
(Bod_Stmts
, Fin_Stmt
);
6847 -- Finalize the object. This action must be performed first before
6848 -- all components have been finalized.
6850 if Is_Controlled
(Typ
)
6851 and then not Is_Local
6858 Proc
:= Find_Prim_Op
(Typ
, Name_Finalize
);
6862 -- Finalize (V); -- No_Exception_Propagation
6868 -- if not Raised then
6870 -- Save_Occurrence (E,
6871 -- Get_Current_Excep.all.all);
6876 if Present
(Proc
) then
6878 Make_Procedure_Call_Statement
(Loc
,
6879 Name
=> New_Reference_To
(Proc
, Loc
),
6880 Parameter_Associations
=> New_List
(
6881 Make_Identifier
(Loc
, Name_V
)));
6883 if Exceptions_OK
then
6885 Make_Block_Statement
(Loc
,
6886 Handled_Statement_Sequence
=>
6887 Make_Handled_Sequence_Of_Statements
(Loc
,
6888 Statements
=> New_List
(Fin_Stmt
),
6889 Exception_Handlers
=> New_List
(
6890 Build_Exception_Handler
6891 (Finalizer_Data
))));
6894 Prepend_To
(Bod_Stmts
,
6895 Make_If_Statement
(Loc
,
6896 Condition
=> Make_Identifier
(Loc
, Name_F
),
6897 Then_Statements
=> New_List
(Fin_Stmt
)));
6902 -- At this point either all finalization statements have been
6903 -- generated or the type is not controlled.
6905 if No
(Bod_Stmts
) then
6906 return New_List
(Make_Null_Statement
(Loc
));
6910 -- Abort : constant Boolean := Triggered_By_Abort;
6912 -- Abort : constant Boolean := False; -- no abort
6914 -- E : Exception_Occurence;
6915 -- Raised : Boolean := False;
6918 -- <finalize statements>
6920 -- if Raised and then not Abort then
6921 -- Raise_From_Controlled_Operation (E);
6926 if Exceptions_OK
then
6927 Append_To
(Bod_Stmts
,
6928 Build_Raise_Statement
(Finalizer_Data
));
6933 Make_Block_Statement
(Loc
,
6936 Handled_Statement_Sequence
=>
6937 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
6939 end Build_Finalize_Statements
;
6941 -----------------------
6942 -- Parent_Field_Type --
6943 -----------------------
6945 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
is
6949 Field
:= First_Entity
(Typ
);
6950 while Present
(Field
) loop
6951 if Chars
(Field
) = Name_uParent
then
6952 return Etype
(Field
);
6955 Next_Entity
(Field
);
6958 -- A derived tagged type should always have a parent field
6960 raise Program_Error
;
6961 end Parent_Field_Type
;
6963 ---------------------------
6964 -- Preprocess_Components --
6965 ---------------------------
6967 procedure Preprocess_Components
6969 Num_Comps
: out Int
;
6970 Has_POC
: out Boolean)
6980 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6981 while Present
(Decl
) loop
6982 Id
:= Defining_Identifier
(Decl
);
6985 -- Skip field _parent
6987 if Chars
(Id
) /= Name_uParent
6988 and then Needs_Finalization
(Typ
)
6990 Num_Comps
:= Num_Comps
+ 1;
6992 if Has_Access_Constraint
(Id
)
6993 and then No
(Expression
(Decl
))
6999 Next_Non_Pragma
(Decl
);
7001 end Preprocess_Components
;
7003 -- Start of processing for Make_Deep_Record_Body
7007 when Address_Case
=>
7008 return Make_Finalize_Address_Stmts
(Typ
);
7011 return Build_Adjust_Statements
(Typ
);
7013 when Finalize_Case
=>
7014 return Build_Finalize_Statements
(Typ
);
7016 when Initialize_Case
=>
7018 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7021 if Is_Controlled
(Typ
) then
7023 Make_Procedure_Call_Statement
(Loc
,
7026 (Find_Prim_Op
(Typ
, Name_Of
(Prim
)), Loc
),
7027 Parameter_Associations
=> New_List
(
7028 Make_Identifier
(Loc
, Name_V
))));
7034 end Make_Deep_Record_Body
;
7036 ----------------------
7037 -- Make_Final_Call --
7038 ----------------------
7040 function Make_Final_Call
7043 For_Parent
: Boolean := False) return Node_Id
7045 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
7047 Fin_Id
: Entity_Id
:= Empty
;
7052 -- Recover the proper type which contains [Deep_]Finalize
7054 if Is_Class_Wide_Type
(Typ
) then
7055 Utyp
:= Root_Type
(Typ
);
7059 elsif Is_Concurrent_Type
(Typ
) then
7060 Utyp
:= Corresponding_Record_Type
(Typ
);
7062 Ref
:= Convert_Concurrent
(Obj_Ref
, Typ
);
7064 elsif Is_Private_Type
(Typ
)
7065 and then Present
(Full_View
(Typ
))
7066 and then Is_Concurrent_Type
(Full_View
(Typ
))
7068 Utyp
:= Corresponding_Record_Type
(Full_View
(Typ
));
7070 Ref
:= Convert_Concurrent
(Obj_Ref
, Full_View
(Typ
));
7078 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7079 Set_Assignment_OK
(Ref
);
7081 -- Deal with non-tagged derivation of private views. If the parent type
7082 -- is a protected type, Deep_Finalize is found on the corresponding
7083 -- record of the ancestor.
7085 if Is_Untagged_Derivation
(Typ
) then
7086 if Is_Protected_Type
(Typ
) then
7087 Utyp
:= Corresponding_Record_Type
(Root_Type
(Base_Type
(Typ
)));
7089 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7091 if Is_Protected_Type
(Utyp
) then
7092 Utyp
:= Corresponding_Record_Type
(Utyp
);
7096 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7097 Set_Assignment_OK
(Ref
);
7100 -- Deal with derived private types which do not inherit primitives from
7101 -- their parents. In this case, [Deep_]Finalize can be found in the full
7102 -- view of the parent type.
7104 if Is_Tagged_Type
(Utyp
)
7105 and then Is_Derived_Type
(Utyp
)
7106 and then Is_Empty_Elmt_List
(Primitive_Operations
(Utyp
))
7107 and then Is_Private_Type
(Etype
(Utyp
))
7108 and then Present
(Full_View
(Etype
(Utyp
)))
7110 Utyp
:= Full_View
(Etype
(Utyp
));
7111 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7112 Set_Assignment_OK
(Ref
);
7115 -- When dealing with the completion of a private type, use the base type
7118 if Utyp
/= Base_Type
(Utyp
) then
7119 pragma Assert
(Present
(Atyp
) and then Is_Private_Type
(Atyp
));
7121 Utyp
:= Base_Type
(Utyp
);
7122 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7123 Set_Assignment_OK
(Ref
);
7126 -- Select the appropriate version of Finalize
7129 if Has_Controlled_Component
(Utyp
) then
7130 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7133 -- Class-wide types, interfaces and types with controlled components
7135 elsif Is_Class_Wide_Type
(Typ
)
7136 or else Is_Interface
(Typ
)
7137 or else Has_Controlled_Component
(Utyp
)
7139 if Is_Tagged_Type
(Utyp
) then
7140 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7142 Fin_Id
:= TSS
(Utyp
, TSS_Deep_Finalize
);
7145 -- Derivations from [Limited_]Controlled
7147 elsif Is_Controlled
(Utyp
) then
7148 if Has_Controlled_Component
(Utyp
) then
7149 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7151 Fin_Id
:= Find_Prim_Op
(Utyp
, Name_Of
(Finalize_Case
));
7156 elsif Is_Tagged_Type
(Utyp
) then
7157 Fin_Id
:= Find_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7160 raise Program_Error
;
7163 if Present
(Fin_Id
) then
7165 -- When finalizing a class-wide object, do not convert to the root
7166 -- type in order to produce a dispatching call.
7168 if Is_Class_Wide_Type
(Typ
) then
7171 -- Ensure that a finalization routine is at least decorated in order
7172 -- to inspect the object parameter.
7174 elsif Analyzed
(Fin_Id
)
7175 or else Ekind
(Fin_Id
) = E_Procedure
7177 -- In certain cases, such as the creation of Stream_Read, the
7178 -- visible entity of the type is its full view. Since Stream_Read
7179 -- will have to create an object of type Typ, the local object
7180 -- will be finalzed by the scope finalizer generated later on. The
7181 -- object parameter of Deep_Finalize will always use the private
7182 -- view of the type. To avoid such a clash between a private and a
7183 -- full view, perform an unchecked conversion of the object
7184 -- reference to the private view.
7187 Formal_Typ
: constant Entity_Id
:=
7188 Etype
(First_Formal
(Fin_Id
));
7190 if Is_Private_Type
(Formal_Typ
)
7191 and then Present
(Full_View
(Formal_Typ
))
7192 and then Full_View
(Formal_Typ
) = Utyp
7194 Ref
:= Unchecked_Convert_To
(Formal_Typ
, Ref
);
7198 Ref
:= Convert_View
(Fin_Id
, Ref
);
7201 return Make_Call
(Loc
, Fin_Id
, New_Copy_Tree
(Ref
), For_Parent
);
7205 end Make_Final_Call
;
7207 --------------------------------
7208 -- Make_Finalize_Address_Body --
7209 --------------------------------
7211 procedure Make_Finalize_Address_Body
(Typ
: Entity_Id
) is
7212 Is_Task
: constant Boolean :=
7213 Ekind
(Typ
) = E_Record_Type
7214 and then Is_Concurrent_Record_Type
(Typ
)
7215 and then Ekind
(Corresponding_Concurrent_Type
(Typ
)) =
7217 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7218 Proc_Id
: Entity_Id
;
7222 -- The corresponding records of task types are not controlled by design.
7223 -- For the sake of completeness, create an empty Finalize_Address to be
7224 -- used in task class-wide allocations.
7229 -- Nothing to do if the type is not controlled or it already has a
7230 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
7231 -- come from source. These are usually generated for completeness and
7232 -- do not need the Finalize_Address primitive.
7234 elsif not Needs_Finalization
(Typ
)
7235 or else Is_Abstract_Type
(Typ
)
7236 or else Present
(TSS
(Typ
, TSS_Finalize_Address
))
7238 (Is_Class_Wide_Type
(Typ
)
7239 and then Ekind
(Root_Type
(Typ
)) = E_Record_Subtype
7240 and then not Comes_From_Source
(Root_Type
(Typ
)))
7246 Make_Defining_Identifier
(Loc
,
7247 Make_TSS_Name
(Typ
, TSS_Finalize_Address
));
7251 -- procedure <Typ>FD (V : System.Address) is
7253 -- null; -- for tasks
7255 -- declare -- for all other types
7256 -- type Pnn is access all Typ;
7257 -- for Pnn'Storage_Size use 0;
7259 -- [Deep_]Finalize (Pnn (V).all);
7264 Stmts
:= New_List
(Make_Null_Statement
(Loc
));
7266 Stmts
:= Make_Finalize_Address_Stmts
(Typ
);
7270 Make_Subprogram_Body
(Loc
,
7272 Make_Procedure_Specification
(Loc
,
7273 Defining_Unit_Name
=> Proc_Id
,
7275 Parameter_Specifications
=> New_List
(
7276 Make_Parameter_Specification
(Loc
,
7277 Defining_Identifier
=>
7278 Make_Defining_Identifier
(Loc
, Name_V
),
7280 New_Reference_To
(RTE
(RE_Address
), Loc
)))),
7282 Declarations
=> No_List
,
7284 Handled_Statement_Sequence
=>
7285 Make_Handled_Sequence_Of_Statements
(Loc
,
7286 Statements
=> Stmts
)));
7288 Set_TSS
(Typ
, Proc_Id
);
7289 end Make_Finalize_Address_Body
;
7291 ---------------------------------
7292 -- Make_Finalize_Address_Stmts --
7293 ---------------------------------
7295 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
is
7296 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7297 Ptr_Typ
: constant Entity_Id
:= Make_Temporary
(Loc
, 'P');
7299 Desg_Typ
: Entity_Id
;
7303 if Is_Array_Type
(Typ
) then
7304 if Is_Constrained
(First_Subtype
(Typ
)) then
7305 Desg_Typ
:= First_Subtype
(Typ
);
7307 Desg_Typ
:= Base_Type
(Typ
);
7310 -- Class-wide types of constrained root types
7312 elsif Is_Class_Wide_Type
(Typ
)
7313 and then Has_Discriminants
(Root_Type
(Typ
))
7315 Is_Empty_Elmt_List
(Discriminant_Constraint
(Root_Type
(Typ
)))
7318 Parent_Typ
: Entity_Id
;
7321 -- Climb the parent type chain looking for a non-constrained type
7323 Parent_Typ
:= Root_Type
(Typ
);
7324 while Parent_Typ
/= Etype
(Parent_Typ
)
7325 and then Has_Discriminants
(Parent_Typ
)
7327 Is_Empty_Elmt_List
(Discriminant_Constraint
(Parent_Typ
))
7329 Parent_Typ
:= Etype
(Parent_Typ
);
7332 -- Handle views created for tagged types with unknown
7335 if Is_Underlying_Record_View
(Parent_Typ
) then
7336 Parent_Typ
:= Underlying_Record_View
(Parent_Typ
);
7339 Desg_Typ
:= Class_Wide_Type
(Underlying_Type
(Parent_Typ
));
7349 -- type Ptr_Typ is access all Typ;
7350 -- for Ptr_Typ'Storage_Size use 0;
7353 Make_Full_Type_Declaration
(Loc
,
7354 Defining_Identifier
=> Ptr_Typ
,
7356 Make_Access_To_Object_Definition
(Loc
,
7357 All_Present
=> True,
7358 Subtype_Indication
=> New_Reference_To
(Desg_Typ
, Loc
))),
7360 Make_Attribute_Definition_Clause
(Loc
,
7361 Name
=> New_Reference_To
(Ptr_Typ
, Loc
),
7362 Chars
=> Name_Storage_Size
,
7363 Expression
=> Make_Integer_Literal
(Loc
, 0)));
7365 Obj_Expr
:= Make_Identifier
(Loc
, Name_V
);
7367 -- Unconstrained arrays require special processing in order to retrieve
7368 -- the elements. To achieve this, we have to skip the dope vector which
7369 -- lays in front of the elements and then use a thin pointer to perform
7370 -- the address-to-access conversion.
7372 if Is_Array_Type
(Typ
)
7373 and then not Is_Constrained
(First_Subtype
(Typ
))
7376 Dope_Id
: Entity_Id
;
7379 -- Ensure that Ptr_Typ a thin pointer, generate:
7380 -- for Ptr_Typ'Size use System.Address'Size;
7383 Make_Attribute_Definition_Clause
(Loc
,
7384 Name
=> New_Reference_To
(Ptr_Typ
, Loc
),
7387 Make_Integer_Literal
(Loc
, System_Address_Size
)));
7390 -- Dnn : constant Storage_Offset :=
7391 -- Desg_Typ'Descriptor_Size / Storage_Unit;
7393 Dope_Id
:= Make_Temporary
(Loc
, 'D');
7396 Make_Object_Declaration
(Loc
,
7397 Defining_Identifier
=> Dope_Id
,
7398 Constant_Present
=> True,
7399 Object_Definition
=>
7400 New_Reference_To
(RTE
(RE_Storage_Offset
), Loc
),
7402 Make_Op_Divide
(Loc
,
7404 Make_Attribute_Reference
(Loc
,
7405 Prefix
=> New_Reference_To
(Desg_Typ
, Loc
),
7406 Attribute_Name
=> Name_Descriptor_Size
),
7408 Make_Integer_Literal
(Loc
, System_Storage_Unit
))));
7410 -- Shift the address from the start of the dope vector to the
7411 -- start of the elements:
7415 -- Note that this is done through a wrapper routine since RTSfind
7416 -- cannot retrieve operations with string names of the form "+".
7419 Make_Function_Call
(Loc
,
7421 New_Reference_To
(RTE
(RE_Add_Offset_To_Address
), Loc
),
7422 Parameter_Associations
=> New_List
(
7424 New_Reference_To
(Dope_Id
, Loc
)));
7428 -- Create the block and the finalization call
7431 Make_Block_Statement
(Loc
,
7432 Declarations
=> Decls
,
7434 Handled_Statement_Sequence
=>
7435 Make_Handled_Sequence_Of_Statements
(Loc
,
7436 Statements
=> New_List
(
7439 Make_Explicit_Dereference
(Loc
,
7440 Prefix
=> Unchecked_Convert_To
(Ptr_Typ
, Obj_Expr
)),
7441 Typ
=> Desg_Typ
)))));
7442 end Make_Finalize_Address_Stmts
;
7444 -------------------------------------
7445 -- Make_Handler_For_Ctrl_Operation --
7446 -------------------------------------
7450 -- when E : others =>
7451 -- Raise_From_Controlled_Operation (E);
7456 -- raise Program_Error [finalize raised exception];
7458 -- depending on whether Raise_From_Controlled_Operation is available
7460 function Make_Handler_For_Ctrl_Operation
7461 (Loc
: Source_Ptr
) return Node_Id
7464 -- Choice parameter (for the first case above)
7466 Raise_Node
: Node_Id
;
7467 -- Procedure call or raise statement
7470 -- Standard run-time, .NET/JVM targets: add choice parameter E and pass
7471 -- it to Raise_From_Controlled_Operation so that the original exception
7472 -- name and message can be recorded in the exception message for
7475 if RTE_Available
(RE_Raise_From_Controlled_Operation
) then
7476 E_Occ
:= Make_Defining_Identifier
(Loc
, Name_E
);
7478 Make_Procedure_Call_Statement
(Loc
,
7481 (RTE
(RE_Raise_From_Controlled_Operation
), Loc
),
7482 Parameter_Associations
=> New_List
(
7483 New_Reference_To
(E_Occ
, Loc
)));
7485 -- Restricted run-time: exception messages are not supported
7490 Make_Raise_Program_Error
(Loc
,
7491 Reason
=> PE_Finalize_Raised_Exception
);
7495 Make_Implicit_Exception_Handler
(Loc
,
7496 Exception_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
7497 Choice_Parameter
=> E_Occ
,
7498 Statements
=> New_List
(Raise_Node
));
7499 end Make_Handler_For_Ctrl_Operation
;
7501 --------------------
7502 -- Make_Init_Call --
7503 --------------------
7505 function Make_Init_Call
7507 Typ
: Entity_Id
) return Node_Id
7509 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
7516 -- Deal with the type and object reference. Depending on the context, an
7517 -- object reference may need several conversions.
7519 if Is_Concurrent_Type
(Typ
) then
7521 Utyp
:= Corresponding_Record_Type
(Typ
);
7522 Ref
:= Convert_Concurrent
(Obj_Ref
, Typ
);
7524 elsif Is_Private_Type
(Typ
)
7525 and then Present
(Full_View
(Typ
))
7526 and then Is_Concurrent_Type
(Underlying_Type
(Typ
))
7529 Utyp
:= Corresponding_Record_Type
(Underlying_Type
(Typ
));
7530 Ref
:= Convert_Concurrent
(Obj_Ref
, Underlying_Type
(Typ
));
7538 Set_Assignment_OK
(Ref
);
7540 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7542 -- Deal with non-tagged derivation of private views
7544 if Is_Untagged_Derivation
(Typ
)
7545 and then not Is_Conc
7547 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7548 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7550 -- The following is to prevent problems with UC see 1.156 RH ???
7552 Set_Assignment_OK
(Ref
);
7555 -- If the underlying_type is a subtype, then we are dealing with the
7556 -- completion of a private type. We need to access the base type and
7557 -- generate a conversion to it.
7559 if Utyp
/= Base_Type
(Utyp
) then
7560 pragma Assert
(Is_Private_Type
(Typ
));
7561 Utyp
:= Base_Type
(Utyp
);
7562 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7565 -- Select the appropriate version of initialize
7567 if Has_Controlled_Component
(Utyp
) then
7568 Proc
:= TSS
(Utyp
, Deep_Name_Of
(Initialize_Case
));
7570 Proc
:= Find_Prim_Op
(Utyp
, Name_Of
(Initialize_Case
));
7571 Check_Visibly_Controlled
(Initialize_Case
, Typ
, Proc
, Ref
);
7574 -- The object reference may need another conversion depending on the
7575 -- type of the formal and that of the actual.
7577 Ref
:= Convert_View
(Proc
, Ref
);
7580 -- [Deep_]Initialize (Ref);
7583 Make_Procedure_Call_Statement
(Loc
,
7585 New_Reference_To
(Proc
, Loc
),
7586 Parameter_Associations
=> New_List
(Ref
));
7589 ------------------------------
7590 -- Make_Local_Deep_Finalize --
7591 ------------------------------
7593 function Make_Local_Deep_Finalize
7595 Nam
: Entity_Id
) return Node_Id
7597 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7601 Formals
:= New_List
(
7605 Make_Parameter_Specification
(Loc
,
7606 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
7608 Out_Present
=> True,
7609 Parameter_Type
=> New_Reference_To
(Typ
, Loc
)),
7611 -- F : Boolean := True
7613 Make_Parameter_Specification
(Loc
,
7614 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
7615 Parameter_Type
=> New_Reference_To
(Standard_Boolean
, Loc
),
7616 Expression
=> New_Reference_To
(Standard_True
, Loc
)));
7618 -- Add the necessary number of counters to represent the initialization
7619 -- state of an object.
7622 Make_Subprogram_Body
(Loc
,
7624 Make_Procedure_Specification
(Loc
,
7625 Defining_Unit_Name
=> Nam
,
7626 Parameter_Specifications
=> Formals
),
7628 Declarations
=> No_List
,
7630 Handled_Statement_Sequence
=>
7631 Make_Handled_Sequence_Of_Statements
(Loc
,
7632 Statements
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
, True)));
7633 end Make_Local_Deep_Finalize
;
7635 ------------------------------------
7636 -- Make_Set_Finalize_Address_Call --
7637 ------------------------------------
7639 function Make_Set_Finalize_Address_Call
7642 Ptr_Typ
: Entity_Id
) return Node_Id
7644 Desig_Typ
: constant Entity_Id
:=
7645 Available_View
(Designated_Type
(Ptr_Typ
));
7646 Fin_Mas_Id
: constant Entity_Id
:= Finalization_Master
(Ptr_Typ
);
7647 Fin_Mas_Ref
: Node_Id
;
7651 -- If the context is a class-wide allocator, we use the class-wide type
7652 -- to obtain the proper Finalize_Address routine.
7654 if Is_Class_Wide_Type
(Desig_Typ
) then
7660 if Is_Private_Type
(Utyp
) and then Present
(Full_View
(Utyp
)) then
7661 Utyp
:= Full_View
(Utyp
);
7664 if Is_Concurrent_Type
(Utyp
) then
7665 Utyp
:= Corresponding_Record_Type
(Utyp
);
7669 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7671 -- Deal with non-tagged derivation of private views. If the parent is
7672 -- now known to be protected, the finalization routine is the one
7673 -- defined on the corresponding record of the ancestor (corresponding
7674 -- records do not automatically inherit operations, but maybe they
7677 if Is_Untagged_Derivation
(Typ
) then
7678 if Is_Protected_Type
(Typ
) then
7679 Utyp
:= Corresponding_Record_Type
(Root_Type
(Base_Type
(Typ
)));
7681 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7683 if Is_Protected_Type
(Utyp
) then
7684 Utyp
:= Corresponding_Record_Type
(Utyp
);
7689 -- If the underlying_type is a subtype, we are dealing with the
7690 -- completion of a private type. We need to access the base type and
7691 -- generate a conversion to it.
7693 if Utyp
/= Base_Type
(Utyp
) then
7694 pragma Assert
(Is_Private_Type
(Typ
));
7696 Utyp
:= Base_Type
(Utyp
);
7699 Fin_Mas_Ref
:= New_Occurrence_Of
(Fin_Mas_Id
, Loc
);
7701 -- If the call is from a build-in-place function, the Master parameter
7702 -- is actually a pointer. Dereference it for the call.
7704 if Is_Access_Type
(Etype
(Fin_Mas_Id
)) then
7705 Fin_Mas_Ref
:= Make_Explicit_Dereference
(Loc
, Fin_Mas_Ref
);
7709 -- Set_Finalize_Address (<Ptr_Typ>FM, <Utyp>FD'Unrestricted_Access);
7712 Make_Procedure_Call_Statement
(Loc
,
7714 New_Reference_To
(RTE
(RE_Set_Finalize_Address
), Loc
),
7715 Parameter_Associations
=> New_List
(
7717 Make_Attribute_Reference
(Loc
,
7719 New_Reference_To
(TSS
(Utyp
, TSS_Finalize_Address
), Loc
),
7720 Attribute_Name
=> Name_Unrestricted_Access
)));
7721 end Make_Set_Finalize_Address_Call
;
7723 --------------------------
7724 -- Make_Transient_Block --
7725 --------------------------
7727 function Make_Transient_Block
7730 Par
: Node_Id
) return Node_Id
7732 Decls
: constant List_Id
:= New_List
;
7733 Instrs
: constant List_Id
:= New_List
(Action
);
7738 -- Case where only secondary stack use is involved
7740 if VM_Target
= No_VM
7741 and then Uses_Sec_Stack
(Current_Scope
)
7742 and then Nkind
(Action
) /= N_Simple_Return_Statement
7743 and then Nkind
(Par
) /= N_Exception_Handler
7749 S
:= Scope
(Current_Scope
);
7751 -- At the outer level, no need to release the sec stack
7753 if S
= Standard_Standard
then
7754 Set_Uses_Sec_Stack
(Current_Scope
, False);
7757 -- In a function, only release the sec stack if the function
7758 -- does not return on the sec stack otherwise the result may
7759 -- be lost. The caller is responsible for releasing.
7761 elsif Ekind
(S
) = E_Function
then
7762 Set_Uses_Sec_Stack
(Current_Scope
, False);
7764 if not Requires_Transient_Scope
(Etype
(S
)) then
7765 Set_Uses_Sec_Stack
(S
, True);
7766 Check_Restriction
(No_Secondary_Stack
, Action
);
7771 -- In a loop or entry we should install a block encompassing
7772 -- all the construct. For now just release right away.
7774 elsif Ekind_In
(S
, E_Entry
, E_Loop
) then
7777 -- In a procedure or a block, we release on exit of the
7778 -- procedure or block. ??? memory leak can be created by
7781 elsif Ekind_In
(S
, E_Block
, E_Procedure
) then
7782 Set_Uses_Sec_Stack
(S
, True);
7783 Check_Restriction
(No_Secondary_Stack
, Action
);
7784 Set_Uses_Sec_Stack
(Current_Scope
, False);
7794 -- Create the transient block. Set the parent now since the block itself
7795 -- is not part of the tree.
7798 Make_Block_Statement
(Loc
,
7799 Identifier
=> New_Reference_To
(Current_Scope
, Loc
),
7800 Declarations
=> Decls
,
7801 Handled_Statement_Sequence
=>
7802 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Instrs
),
7803 Has_Created_Identifier
=> True);
7804 Set_Parent
(Block
, Par
);
7806 -- Insert actions stuck in the transient scopes as well as all freezing
7807 -- nodes needed by those actions.
7809 Insert_Actions_In_Scope_Around
(Action
);
7811 Insert
:= Prev
(Action
);
7812 if Present
(Insert
) then
7813 Freeze_All
(First_Entity
(Current_Scope
), Insert
);
7816 -- When the transient scope was established, we pushed the entry for the
7817 -- transient scope onto the scope stack, so that the scope was active
7818 -- for the installation of finalizable entities etc. Now we must remove
7819 -- this entry, since we have constructed a proper block.
7824 end Make_Transient_Block
;
7826 ------------------------
7827 -- Node_To_Be_Wrapped --
7828 ------------------------
7830 function Node_To_Be_Wrapped
return Node_Id
is
7832 return Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
;
7833 end Node_To_Be_Wrapped
;
7835 ----------------------------
7836 -- Set_Node_To_Be_Wrapped --
7837 ----------------------------
7839 procedure Set_Node_To_Be_Wrapped
(N
: Node_Id
) is
7841 Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
:= N
;
7842 end Set_Node_To_Be_Wrapped
;
7844 ----------------------------------
7845 -- Store_After_Actions_In_Scope --
7846 ----------------------------------
7848 procedure Store_After_Actions_In_Scope
(L
: List_Id
) is
7849 SE
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Scope_Stack
.Last
);
7852 if Present
(SE
.Actions_To_Be_Wrapped_After
) then
7853 Insert_List_Before_And_Analyze
(
7854 First
(SE
.Actions_To_Be_Wrapped_After
), L
);
7857 SE
.Actions_To_Be_Wrapped_After
:= L
;
7859 if Is_List_Member
(SE
.Node_To_Be_Wrapped
) then
7860 Set_Parent
(L
, Parent
(SE
.Node_To_Be_Wrapped
));
7862 Set_Parent
(L
, SE
.Node_To_Be_Wrapped
);
7867 end Store_After_Actions_In_Scope
;
7869 -----------------------------------
7870 -- Store_Before_Actions_In_Scope --
7871 -----------------------------------
7873 procedure Store_Before_Actions_In_Scope
(L
: List_Id
) is
7874 SE
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Scope_Stack
.Last
);
7877 if Present
(SE
.Actions_To_Be_Wrapped_Before
) then
7878 Insert_List_After_And_Analyze
(
7879 Last
(SE
.Actions_To_Be_Wrapped_Before
), L
);
7882 SE
.Actions_To_Be_Wrapped_Before
:= L
;
7884 if Is_List_Member
(SE
.Node_To_Be_Wrapped
) then
7885 Set_Parent
(L
, Parent
(SE
.Node_To_Be_Wrapped
));
7887 Set_Parent
(L
, SE
.Node_To_Be_Wrapped
);
7892 end Store_Before_Actions_In_Scope
;
7894 --------------------------------
7895 -- Wrap_Transient_Declaration --
7896 --------------------------------
7898 -- If a transient scope has been established during the processing of the
7899 -- Expression of an Object_Declaration, it is not possible to wrap the
7900 -- declaration into a transient block as usual case, otherwise the object
7901 -- would be itself declared in the wrong scope. Therefore, all entities (if
7902 -- any) defined in the transient block are moved to the proper enclosing
7903 -- scope, furthermore, if they are controlled variables they are finalized
7904 -- right after the declaration. The finalization list of the transient
7905 -- scope is defined as a renaming of the enclosing one so during their
7906 -- initialization they will be attached to the proper finalization list.
7907 -- For instance, the following declaration :
7909 -- X : Typ := F (G (A), G (B));
7911 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7912 -- is expanded into :
7914 -- X : Typ := [ complex Expression-Action ];
7915 -- [Deep_]Finalize (_v1);
7916 -- [Deep_]Finalize (_v2);
7918 procedure Wrap_Transient_Declaration
(N
: Node_Id
) is
7925 Encl_S
:= Scope
(S
);
7927 -- Insert Actions kept in the Scope stack
7929 Insert_Actions_In_Scope_Around
(N
);
7931 -- If the declaration is consuming some secondary stack, mark the
7932 -- enclosing scope appropriately.
7934 Uses_SS
:= Uses_Sec_Stack
(S
);
7937 -- Put the local entities back in the enclosing scope, and set the
7938 -- Is_Public flag appropriately.
7940 Transfer_Entities
(S
, Encl_S
);
7942 -- Mark the enclosing dynamic scope so that the sec stack will be
7943 -- released upon its exit unless this is a function that returns on
7944 -- the sec stack in which case this will be done by the caller.
7946 if VM_Target
= No_VM
and then Uses_SS
then
7947 S
:= Enclosing_Dynamic_Scope
(S
);
7949 if Ekind
(S
) = E_Function
7950 and then Requires_Transient_Scope
(Etype
(S
))
7954 Set_Uses_Sec_Stack
(S
);
7955 Check_Restriction
(No_Secondary_Stack
, N
);
7958 end Wrap_Transient_Declaration
;
7960 -------------------------------
7961 -- Wrap_Transient_Expression --
7962 -------------------------------
7964 procedure Wrap_Transient_Expression
(N
: Node_Id
) is
7965 Loc
: constant Source_Ptr
:= Sloc
(N
);
7966 Expr
: Node_Id
:= Relocate_Node
(N
);
7967 Temp
: constant Entity_Id
:= Make_Temporary
(Loc
, 'E', N
);
7968 Typ
: constant Entity_Id
:= Etype
(N
);
7975 -- M : constant Mark_Id := SS_Mark;
7976 -- procedure Finalizer is ... (See Build_Finalizer)
7979 -- Temp := <Expr>; -- general case
7980 -- Temp := (if <Expr> then True else False); -- boolean case
7986 -- A special case is made for Boolean expressions so that the back-end
7987 -- knows to generate a conditional branch instruction, if running with
7988 -- -fpreserve-control-flow. This ensures that a control flow change
7989 -- signalling the decision outcome occurs before the cleanup actions.
7991 if Opt
.Suppress_Control_Flow_Optimizations
7992 and then Is_Boolean_Type
(Typ
)
7995 Make_If_Expression
(Loc
,
7996 Expressions
=> New_List
(
7998 New_Occurrence_Of
(Standard_True
, Loc
),
7999 New_Occurrence_Of
(Standard_False
, Loc
)));
8002 Insert_Actions
(N
, New_List
(
8003 Make_Object_Declaration
(Loc
,
8004 Defining_Identifier
=> Temp
,
8005 Object_Definition
=> New_Reference_To
(Typ
, Loc
)),
8007 Make_Transient_Block
(Loc
,
8009 Make_Assignment_Statement
(Loc
,
8010 Name
=> New_Reference_To
(Temp
, Loc
),
8011 Expression
=> Expr
),
8012 Par
=> Parent
(N
))));
8014 Rewrite
(N
, New_Reference_To
(Temp
, Loc
));
8015 Analyze_And_Resolve
(N
, Typ
);
8016 end Wrap_Transient_Expression
;
8018 ------------------------------
8019 -- Wrap_Transient_Statement --
8020 ------------------------------
8022 procedure Wrap_Transient_Statement
(N
: Node_Id
) is
8023 Loc
: constant Source_Ptr
:= Sloc
(N
);
8024 New_Stmt
: constant Node_Id
:= Relocate_Node
(N
);
8029 -- M : constant Mark_Id := SS_Mark;
8030 -- procedure Finalizer is ... (See Build_Finalizer)
8040 Make_Transient_Block
(Loc
,
8042 Par
=> Parent
(N
)));
8044 -- With the scope stack back to normal, we can call analyze on the
8045 -- resulting block. At this point, the transient scope is being
8046 -- treated like a perfectly normal scope, so there is nothing
8047 -- special about it.
8049 -- Note: Wrap_Transient_Statement is called with the node already
8050 -- analyzed (i.e. Analyzed (N) is True). This is important, since
8051 -- otherwise we would get a recursive processing of the node when
8052 -- we do this Analyze call.
8055 end Wrap_Transient_Statement
;