1 ------------------------------------------------------------------------------
3 -- GNAT COMPILER COMPONENTS --
9 -- Copyright (C) 1992-2024, 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 Einfo
.Entities
; use Einfo
.Entities
;
34 with Einfo
.Utils
; use Einfo
.Utils
;
35 with Elists
; use Elists
;
36 with Errout
; use Errout
;
37 with Exp_Ch6
; use Exp_Ch6
;
38 with Exp_Ch9
; use Exp_Ch9
;
39 with Exp_Ch11
; use Exp_Ch11
;
40 with Exp_Dbug
; use Exp_Dbug
;
41 with Exp_Dist
; use Exp_Dist
;
42 with Exp_Disp
; use Exp_Disp
;
43 with Exp_Prag
; use Exp_Prag
;
44 with Exp_Tss
; use Exp_Tss
;
45 with Exp_Util
; use Exp_Util
;
46 with Freeze
; use Freeze
;
47 with GNAT_CUDA
; use GNAT_CUDA
;
49 with Nlists
; use Nlists
;
50 with Nmake
; use Nmake
;
52 with Output
; use Output
;
53 with Restrict
; use Restrict
;
54 with Rident
; use Rident
;
55 with Rtsfind
; use Rtsfind
;
56 with Sinfo
; use Sinfo
;
57 with Sinfo
.Nodes
; use Sinfo
.Nodes
;
58 with Sinfo
.Utils
; use Sinfo
.Utils
;
60 with Sem_Aux
; use Sem_Aux
;
61 with Sem_Ch7
; use Sem_Ch7
;
62 with Sem_Ch8
; use Sem_Ch8
;
63 with Sem_Res
; use Sem_Res
;
64 with Sem_Util
; use Sem_Util
;
65 with Snames
; use Snames
;
66 with Stand
; use Stand
;
67 with Tbuild
; use Tbuild
;
68 with Ttypes
; use Ttypes
;
69 with Uintp
; use Uintp
;
71 package body Exp_Ch7
is
73 -----------------------------
74 -- Finalization Management --
75 -----------------------------
77 -- This paragraph describes how Initialization/Adjustment/Finalization
78 -- procedures are generated and called. Two cases must be considered: types
79 -- that are controlled (Is_Controlled flag set) and composite types that
80 -- contain controlled components (Has_Controlled_Component flag set). In
81 -- the first case the procedures to call are the user-defined primitive
82 -- operations Initialize/Adjust/Finalize. In the second case, the compiler
83 -- generates Deep_Initialize, Deep_Adjust and Deep_Finalize that are in
84 -- charge of calling the former procedures on the controlled components.
86 -- Initialize calls: they are generated for either declarations or dynamic
87 -- allocations of controlled objects with no initial value. They are always
88 -- followed by an attachment to some finalization chain. For the dynamic
89 -- dynamic allocation case, this is the collection attached to the access
90 -- type definition; otherwise, this is the master of the current scope.
92 -- Adjust calls: they are generated on two occasions: (1) for declarations
93 -- or dynamic allocations of controlled objects with an initial value (with
94 -- the exception of function calls), (2) after an assignment. In the first
95 -- case they are followed by an attachment to the finalization chain, in
96 -- the second case they are not.
98 -- Finalization calls: they are generated on three occasions: (1) on scope
99 -- exit, (2) assignments, (3) unchecked deallocations. In case (3) objects
100 -- have to be detached from the finalization chain, in case (2) they must
101 -- not and in case (1) this is optional as we are exiting the scope anyway.
103 -- There are two kinds of finalization chain to which objects are attached,
104 -- depending on the way they are created. For objects (statically) declared
105 -- in a scope, the finalization chain is that of the master of the scope,
106 -- which is embodied in a Finalization_Master object. As per RM 7.6.1(11/3)
107 -- the finalization of the master (on scope exit) performs the finalization
108 -- of objects attached to its chain in the reverse order of their creation.
110 -- For dynamically allocated objects, the finalization chain is that of the
111 -- finalization collection of the access type through which the objects are
112 -- allocated, which is embodied in a Finalization_Collection object. As per
113 -- RM 7.6.1(11.1/3), the finalization of the collection performs the
114 -- finalization of objects attached to its chain in an arbitrary order.
116 -- A Finalization_Collection object is implemented as a controlled object
117 -- and its finalization is therefore driven by the finalization master of
118 -- the scope where it is declared. As per RM 7.6.1(11.2/3), for a named
119 -- access type, the Finalization_Collection object is declared in the list
120 -- of actions of its freeze node.
122 -- ??? For an anonymous access type, the implementation deviates from the
123 -- RM 7.6.1 clause as follows: all the anonymous access types with the same
124 -- designated type that are (implicitly) declared in a library unit share a
125 -- single Finalization_Collection object declared in the outermost scope of
126 -- the library unit, except if the designated type is declared in a dynamic
127 -- scope nested in the unit; in this case no Finalization_Collection object
128 -- is created. As a result, in the first case, objects allocated through
129 -- the anonymous access types are finalized when the library unit goes out
130 -- of scope, while in the second case, they are not finalized at all.
132 -- Here is a simple example of the expansion of a controlled block:
138 -- type Rec is record
153 -- Mnn : System.Finalization_Primitives.Finalization_Master;
155 -- XMN : aliased System.Finalization_Primitives.Master_Node;
160 -- System.Finalization_Primitives.Attach_To_Master
162 -- CtrlFD'unrestricted_access,
163 -- XMN'unrestricted_access,
169 -- YMN : aliased System.Finalization_Primitives.Master_Node;
171 -- System.Finalization_Primitives.Attach_To_Master
173 -- CtrlFD'unrestricted_access,
174 -- YMN'unrestricted_access,
177 -- type Rec is record
181 -- WMN : aliased System.Finalization_Primitives.Master_Node;
186 -- Deep_Initialize (W);
187 -- System.Finalization_Primitives.Attach_To_Master
189 -- Rec_FD'unrestricted_access,
190 -- WMN'unrestricted_access,
194 -- Deep_Finalize (W);
200 -- ZMN : aliaed System.Finalization_Primitives.Master_Node;
202 -- System.Finalization_Primitives.Attach_To_Master
204 -- Rec_FD'unrestricted_access,
205 -- ZMN'unrestricted_access,
208 -- procedure _Finalizer is
209 -- Ann : constant Boolean := Ada.Exceptions.Triggered_By_Abort;
210 -- Rnn : boolean := False;
214 -- System.Finalization_Primitives.Finalize_Master (Mnn);
220 -- if Rnn and then not Ann then
221 -- [program_error "finalize raised exception"]
227 -- Deep_Finalize (W);
234 -- In the case of a block containing a single controlled object, the master
235 -- degenerates into a single master node:
247 -- XMN : aliased System.Finalization_Primitives.Master_Node;
249 -- System.Finalization_Primitives.Attach_To_Node
251 -- CtrlFD'unrestricted_access,
252 -- XMN'unrestricted_access);
254 -- procedure _Finalizer is
255 -- Ann : constant Boolean := Ada.Exceptions.Triggered_By_Abort;
256 -- Rnn : boolean := False;
260 -- System.Finalization_Primitives.Finalize_Object (XMN);
266 -- if Rnn and then not Ann then
267 -- [program_error "finalize raised exception"]
277 -- Here is the version with a dynamically allocated object:
280 -- X : P_Ctrl := new Ctrl;
289 -- Cnn : System.Finalization_Primitives.Finalization_Collection_Ptr :=
290 -- P_CtrlFC'unrestricted_access;
292 -- Pnn : constant P_Ctrl := new Ctrl[...][...];
295 -- Initialize (Pnn.all);
296 -- System.Finalization_Primitives.Attach_To_Collection
298 -- CtrlFD'unrestricted_access,
303 -- X : P_Ctrl := Pnn;
305 -- The implementation uses two different strategies for the finalization
306 -- of (statically) declared objects and of dynamically allocated objects.
308 -- For (statically) declared objects, the attachment to the finalization
309 -- chain of the current scope and the call to the finalization procedure
310 -- are generated during a post-processing phase of the expansion. These
311 -- objects are first spotted in declarative parts and statement lists by
312 -- Requires_Cleanup_Actions; then Build_Finalizer is called on the parent
313 -- node to generate both the attachment and the finalization actions.
315 -- This post processing is fully transparent for the rest of the expansion
316 -- activities, in other words those have nothing to do or to care about.
317 -- However this default processing may not be sufficient in specific cases,
318 -- e.g. for the return object of an extended return statement in a function
319 -- whose result type is controlled: in this case, the return object must be
320 -- finalized only if the function returns abnormally. In order to deal with
321 -- these cases, it is possible to directly generate detachment actions (for
322 -- the return object case) or finalization actions (for transient objects)
323 -- during the rest of expansion activities.
325 -- These direct actions must be signalled to the post-processing machinery
326 -- and this is achieved through the handling of Master_Node objects, which
327 -- are the items actually chained in the finalization chains of masters.
328 -- With the default processing, they are created by Build_Finalizer for the
329 -- controlled objects spotted by Requires_Cleanup_Actions. But when direct
330 -- actions are carried out, they are generated by these actions and later
331 -- recognized by Requires_Cleanup_Actions and picked up by Build_Finalizer.
333 -- For dynamically allocated objects, there is no post-processing phase and
334 -- the attachment to the finalization chain of the access type, as well the
335 -- the detachment from this chain for unchecked deallocation, are generated
336 -- directly by the compiler during the expansion of allocators and calls to
337 -- instances of the Unchecked_Deallocation procedure.
339 type Final_Primitives
is
340 (Initialize_Case
, Adjust_Case
, Finalize_Case
, Address_Case
);
341 -- This enumeration type is defined in order to ease sharing code for
342 -- building finalization procedures for composite types.
344 Name_Of
: constant array (Final_Primitives
) of Name_Id
:=
345 (Initialize_Case
=> Name_Initialize
,
346 Adjust_Case
=> Name_Adjust
,
347 Finalize_Case
=> Name_Finalize
,
348 Address_Case
=> Name_Finalize_Address
);
349 Deep_Name_Of
: constant array (Final_Primitives
) of TSS_Name_Type
:=
350 (Initialize_Case
=> TSS_Deep_Initialize
,
351 Adjust_Case
=> TSS_Deep_Adjust
,
352 Finalize_Case
=> TSS_Deep_Finalize
,
353 Address_Case
=> TSS_Finalize_Address
);
355 function Allows_Finalization_Collection
(Typ
: Entity_Id
) return Boolean;
356 -- Determine whether access type Typ may have a finalization collection
358 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
);
359 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
360 -- Has_Controlled_Component set and store them using the TSS mechanism.
362 function Build_Cleanup_Statements
364 Additional_Cleanup
: List_Id
) return List_Id
;
365 -- Create the cleanup calls for an asynchronous call block, task master,
366 -- protected subprogram body, task allocation block or task body, or
367 -- additional cleanup actions parked on a transient block. If the context
368 -- does not contain the above constructs, the routine returns an empty
371 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
);
372 -- N is a construct that contains a handled sequence of statements, Fin_Id
373 -- is the entity of a finalizer. Create an At_End handler that covers the
374 -- statements of N and calls Fin_Id. If the handled statement sequence has
375 -- an exception handler, the statements will be wrapped in a block to avoid
376 -- unwanted interaction with the new At_End handler.
378 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
);
379 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
380 -- Has_Component_Component set and store them using the TSS mechanism.
382 --------------------------------
383 -- Transient Scope Management --
384 --------------------------------
386 -- A transient scope is needed when certain temporary objects are created
387 -- by the compiler. These temporary objects are allocated on the secondary
388 -- stack and/or need finalization, and the transient scope is responsible
389 -- for finalizing the objects and reclaiming the memory of the secondary
390 -- stack at the appropriate time. They are generally objects allocated to
391 -- store the result of a function returning an unconstrained or controlled
392 -- value. Expressions needing to be wrapped in a transient scope may appear
393 -- in three different contexts, which lead to different kinds of transient
396 -- 1. In a simple statement (procedure call, assignment, ...). In this
397 -- case the statement is wrapped into a transient block, which takes
398 -- care of the finalization actions as well as the secondary stack
399 -- deallocation, See Wrap_Transient_Statement for details.
401 -- 2. In an expression of a control structure (test in a If statement,
402 -- expression in a Case statement, ...). In this case the expression
403 -- is replaced by a temporary and the enclosing statement is wrapped
404 -- into a transient block, which takes care of the finalization actions
405 -- and the secondary stack deallocation. See Wrap_Transient_Expression
408 -- 3. In an expression of an object declaration. No wrapping is possible
409 -- here, so the finalization actions performed on the normal path, if
410 -- any, are done right after the declaration, and those performed on
411 -- the exceptional path, as well as the secondary stack deallocation,
412 -- are deferred to the enclosing scope. See Wrap_Transient_Declaration
415 -- A transient scope is created by calling Establish_Transient_Scope on the
416 -- node that needs to be serviced by it (the serviced node can subsequently
417 -- be retrieved by invoking Node_To_Be_Wrapped when the current scope is a
418 -- transient scope). Once this has been done, the normal processing of the
419 -- Insert_Actions procedures is blocked and the procedures are redirected
420 -- to the Store_xxx_Actions_In_Scope procedures and Store_Actions_In_Scope
421 -- is ultimately invoked to store the pending actions.
423 -- A transient scope is finalized by calling one of the Wrap_Transient_xxx
424 -- procedures depending on the context as explained above. They ultimately
425 -- invoke Insert_Actions_In_Scope_Around as per the following picture:
427 -- Wrap_Transient_Expression Wrap_Transient_Statement
430 -- Make_Transient_Block
432 -- Wrap_Transient_Declaration |
435 -- Insert_Actions_In_Scope_Around
437 procedure Insert_Actions_In_Scope_Around
440 Manage_SS
: Boolean);
441 -- Insert the before-actions kept in the scope stack before N, and the
442 -- after-actions after N, which must be a member of a list. If Clean is
443 -- true, insert any cleanup actions kept in the scope stack and generate
444 -- required finalization actions for the before-actions and after-actions.
445 -- If Manage_SS is true, insert calls to mark/release the secondary stack.
447 function Make_Transient_Block
450 Par
: Node_Id
) return Node_Id
;
451 -- Action is a single statement or object declaration. Par is the proper
452 -- parent of the generated block. Create a transient block whose name is
453 -- the current scope and the only handled statement is Action. If Action
454 -- involves controlled objects or secondary stack usage, the corresponding
455 -- cleanup actions are performed at the end of the block.
457 procedure Store_Actions_In_Scope
(AK
: Scope_Action_Kind
; L
: List_Id
);
458 -- Shared processing for Store_xxx_Actions_In_Scope
460 -------------------------------------------
461 -- Unnesting procedures for CCG and LLVM --
462 -------------------------------------------
464 -- Expansion generates subprograms for controlled types management that
465 -- may appear in declarative lists in package declarations and bodies.
466 -- These subprograms appear within generated blocks that contain local
467 -- declarations and a call to finalization procedures. To ensure that
468 -- such subprograms get activation records when needed, we transform the
469 -- block into a procedure body, followed by a call to it in the same
472 procedure Check_Unnesting_Elaboration_Code
(N
: Node_Id
);
473 -- The statement part of a package body that is a compilation unit may
474 -- contain blocks that declare local subprograms. In Subprogram_Unnesting_
475 -- Mode such subprograms must be handled as nested inside the (implicit)
476 -- elaboration procedure that executes that statement part. To handle
477 -- properly uplevel references we construct that subprogram explicitly,
478 -- to contain blocks and inner subprograms, the statement part becomes
479 -- a call to this subprogram. This is only done if blocks are present
480 -- in the statement list of the body. (It would be nice to unify this
481 -- procedure with Check_Unnesting_In_Decls_Or_Stmts, if possible, since
482 -- they're doing very similar work, but are structured differently. ???)
484 procedure Check_Unnesting_In_Decls_Or_Stmts
(Decls_Or_Stmts
: List_Id
);
485 -- Similarly, the declarations or statements in library-level packages may
486 -- have created blocks with nested subprograms. Such a block must be
487 -- transformed into a procedure followed by a call to it, so that unnesting
488 -- can handle uplevel references within these nested subprograms (typically
489 -- subprograms that handle finalization actions). This also applies to
490 -- nested packages, including instantiations, in which case it must
491 -- recursively process inner bodies.
493 procedure Check_Unnesting_In_Handlers
(N
: Node_Id
);
494 -- Similarly, check for blocks with nested subprograms occurring within
495 -- a set of exception handlers associated with a package body N.
497 procedure Unnest_Block
(Decl
: Node_Id
);
498 -- Blocks that contain nested subprograms with up-level references need to
499 -- create activation records for them. We do this by rewriting the block as
500 -- a procedure, followed by a call to it in the same declarative list, to
501 -- replicate the semantics of the original block.
503 -- A common source for such block is a transient block created for a
504 -- construct (declaration, assignment, etc.) that involves controlled
505 -- actions or secondary-stack management, in which case the nested
506 -- subprogram is a finalizer.
508 procedure Unnest_If_Statement
(If_Stmt
: Node_Id
);
509 -- The separate statement lists associated with an if-statement (then part,
510 -- elsif parts, else part) may require unnesting if they directly contain
511 -- a subprogram body that references up-level objects. Each statement list
512 -- is traversed to locate such subprogram bodies, and if a part's statement
513 -- list contains a body, then the list is replaced with a new procedure
514 -- containing the part's statements followed by a call to the procedure.
515 -- Furthermore, any nested blocks, loops, or if statements will also be
516 -- traversed to determine the need for further unnesting transformations.
518 procedure Unnest_Statement_List
(Stmts
: in out List_Id
);
519 -- A list of statements that directly contains a subprogram at its outer
520 -- level, that may reference objects declared in that same statement list,
521 -- is rewritten as a procedure containing the statement list Stmts (which
522 -- includes any such objects as well as the nested subprogram), followed by
523 -- a call to the new procedure, and Stmts becomes the list containing the
524 -- procedure and the call. This ensures that Unnest_Subprogram will later
525 -- properly handle up-level references from the nested subprogram to
526 -- objects declared earlier in statement list, by creating an activation
527 -- record and passing it to the nested subprogram. This procedure also
528 -- resets the Scope of objects declared in the statement list, as well as
529 -- the Scope of the nested subprogram, to refer to the new procedure.
530 -- Also, the new procedure is marked Has_Nested_Subprogram, so this should
531 -- only be called when known that the statement list contains a subprogram.
533 procedure Unnest_Loop
(Loop_Stmt
: Node_Id
);
534 -- Top-level Loops that contain nested subprograms with up-level references
535 -- need to have activation records. We do this by rewriting the loop as a
536 -- procedure containing the loop, followed by a call to the procedure in
537 -- the same library-level declarative list, to replicate the semantics of
538 -- the original loop. Such loops can occur due to aggregate expansions and
541 -----------------------
542 -- Local Subprograms --
543 -----------------------
545 procedure Check_Visibly_Controlled
546 (Prim
: Final_Primitives
;
548 E
: in out Entity_Id
;
549 Cref
: in out Node_Id
);
550 -- The controlled operation declared for a derived type may not be
551 -- overriding, if the controlled operations of the parent type are hidden,
552 -- for example when the parent is a private type whose full view is
553 -- controlled. For other primitive operations we modify the name of the
554 -- operation to indicate that it is not overriding, but this is not
555 -- possible for Initialize, etc. because they have to be retrievable by
556 -- name. Before generating the proper call to one of these operations we
557 -- check whether Typ is known to be controlled at the point of definition.
558 -- If it is not then we must retrieve the hidden operation of the parent
559 -- and use it instead. This is one case that might be solved more cleanly
560 -- once Overriding pragmas or declarations are in place.
562 function Contains_Subprogram
(Blk
: Entity_Id
) return Boolean;
563 -- Check recursively whether a loop or block contains a subprogram that
564 -- may need an activation record.
566 function Convert_View
(Proc
: Entity_Id
; Arg
: Node_Id
) return Node_Id
;
567 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
568 -- argument being passed to it. This function will, if necessary, generate
569 -- a conversion between the partial and full view of Arg to match the type
570 -- of the formal of Proc, or force a conversion to the class-wide type in
571 -- the case where the operation is abstract.
577 Skip_Self
: Boolean := False) return Node_Id
;
578 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
579 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
580 -- an adjust or finalization call. When flag Skip_Self is set, the related
581 -- action has an effect on the components only (if any).
583 function Make_Deep_Proc
584 (Prim
: Final_Primitives
;
586 Stmts
: List_Id
) return Entity_Id
;
587 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
588 -- Deep_Finalize procedures according to the first parameter. These
589 -- procedures operate on the type Typ. The Stmts parameter gives the
590 -- body of the procedure.
592 function Make_Deep_Array_Body
593 (Prim
: Final_Primitives
;
594 Typ
: Entity_Id
) return List_Id
;
595 -- This function generates the list of statements for implementing
596 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
597 -- the first parameter, these procedures operate on the array type Typ.
599 function Make_Deep_Record_Body
600 (Prim
: Final_Primitives
;
602 Is_Local
: Boolean := False) return List_Id
;
603 -- This function generates the list of statements for implementing
604 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
605 -- the first parameter, these procedures operate on the record type Typ.
606 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
607 -- whether the inner logic should be dictated by state counters.
609 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
;
610 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
611 -- Make_Deep_Record_Body. Generate the following statements:
614 -- type Acc_Typ is access all Typ;
615 -- for Acc_Typ'Storage_Size use 0;
617 -- [Deep_]Finalize (Acc_Typ (V).all);
620 ----------------------------------
621 -- Attach_Object_To_Master_Node --
622 ----------------------------------
624 procedure Attach_Object_To_Master_Node
626 Master_Node
: Entity_Id
)
628 Loc
: constant Source_Ptr
:= Sloc
(Obj_Decl
);
629 Obj_Id
: constant Entity_Id
:= Defining_Entity
(Obj_Decl
);
630 Func_Id
: constant Entity_Id
:=
631 (if Is_Return_Object
(Obj_Id
)
632 then Return_Applies_To
(Scope
(Obj_Id
))
635 function Build_BIP_Cleanup_Stmts
636 (Func_Id
: Entity_Id
;
637 Obj_Addr
: Node_Id
) return Node_Id
;
638 -- Func_Id denotes a build-in-place function. Generate the following
641 -- if BIPallocform > Secondary_Stack'Pos
642 -- and then BIPcollection /= null
645 -- type Ptr_Typ is access Fun_Typ;
646 -- for Ptr_Typ'Storage_Pool use BIPstoragepool.all;
649 -- Free (Ptr_Typ (Obj_Addr));
653 -- Fun_Typ is the return type of the Func_Id.
655 -----------------------------
656 -- Build_BIP_Cleanup_Stmts --
657 -----------------------------
659 function Build_BIP_Cleanup_Stmts
660 (Func_Id
: Entity_Id
;
661 Obj_Addr
: Node_Id
) return Node_Id
663 Alloc_Id
: constant Entity_Id
:=
664 Build_In_Place_Formal
(Func_Id
, BIP_Alloc_Form
);
665 Decls
: constant List_Id
:= New_List
;
666 Fin_Coll_Id
: constant Entity_Id
:=
667 Build_In_Place_Formal
(Func_Id
, BIP_Collection
);
668 Func_Typ
: constant Entity_Id
:= Etype
(Func_Id
);
678 -- Pool_Id renames BIPstoragepool.all;
680 -- This formal is not added on ZFP as those targets do not
683 if RTE_Available
(RE_Root_Storage_Pool_Ptr
) then
684 Pool_Id
:= Make_Temporary
(Loc
, 'P');
687 Make_Object_Renaming_Declaration
(Loc
,
688 Defining_Identifier
=> Pool_Id
,
690 New_Occurrence_Of
(RTE
(RE_Root_Storage_Pool
), Loc
),
692 Make_Explicit_Dereference
(Loc
,
694 (Build_In_Place_Formal
695 (Func_Id
, BIP_Storage_Pool
), Loc
))));
697 if Debug_Generated_Code
then
698 Set_Debug_Info_Needed
(Pool_Id
);
705 -- Create an access type which uses the storage pool of the caller
708 -- type Ptr_Typ is access Func_Typ;
710 Ptr_Typ
:= Make_Temporary
(Loc
, 'P');
713 Make_Full_Type_Declaration
(Loc
,
714 Defining_Identifier
=> Ptr_Typ
,
716 Make_Access_To_Object_Definition
(Loc
,
717 Subtype_Indication
=> New_Occurrence_Of
(Func_Typ
, Loc
))));
719 -- Perform minor decoration in order to set the collection and the
720 -- storage pool attributes.
722 Mutate_Ekind
(Ptr_Typ
, E_Access_Type
);
723 Set_Finalization_Collection
(Ptr_Typ
, Fin_Coll_Id
);
724 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
726 -- Create an explicit free statement. Note that the free uses the
727 -- caller's pool expressed as a renaming.
730 Make_Free_Statement
(Loc
,
732 Unchecked_Convert_To
(Ptr_Typ
, Obj_Addr
));
734 Set_Storage_Pool
(Free_Stmt
, Pool_Id
);
736 -- Create a block to house the dummy type and the instantiation as
737 -- well as to perform the cleanup the temporary.
743 -- Free (Ptr_Typ (Obj_Addr));
747 Make_Block_Statement
(Loc
,
748 Declarations
=> Decls
,
749 Handled_Statement_Sequence
=>
750 Make_Handled_Sequence_Of_Statements
(Loc
,
751 Statements
=> New_List
(Free_Stmt
)));
754 -- if BIPallocform > Secondary_Stack'Pos
755 -- and then BIPcollection /= null
762 Left_Opnd
=> New_Occurrence_Of
(Alloc_Id
, Loc
),
764 Make_Integer_Literal
(Loc
,
765 UI_From_Int
(BIP_Allocation_Form
'Pos (Secondary_Stack
)))),
768 Left_Opnd
=> New_Occurrence_Of
(Fin_Coll_Id
, Loc
),
769 Right_Opnd
=> Make_Null
(Loc
)));
777 Make_If_Statement
(Loc
,
779 Then_Statements
=> New_List
(Free_Blk
));
780 end Build_BIP_Cleanup_Stmts
;
785 Master_Node_Attach
: Node_Id
;
786 Master_Node_Ins
: Node_Id
;
790 -- Start of processing for Attach_Object_To_Master_Node
793 -- Finalize_Address is not generated in CodePeer mode because the
794 -- body contains address arithmetic. So we don't want to generate
795 -- the attach in this case.
797 if CodePeer_Mode
then
801 -- When the object is initialized by an aggregate, the attachment must
802 -- occur after the last aggregate assignment takes place; only then is
803 -- the object considered initialized. Likewise if it is initialized by
804 -- a build-in-place call: we must attach only after the call.
806 if Ekind
(Obj_Id
) in E_Constant | E_Variable
then
807 if Present
(Last_Aggregate_Assignment
(Obj_Id
)) then
808 Master_Node_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
809 elsif Present
(BIP_Initialization_Call
(Obj_Id
)) then
810 Master_Node_Ins
:= BIP_Initialization_Call
(Obj_Id
);
812 Master_Node_Ins
:= Obj_Decl
;
816 Master_Node_Ins
:= Obj_Decl
;
819 -- Handle the object type and the reference to the object
821 Obj_Ref
:= New_Occurrence_Of
(Obj_Id
, Loc
);
822 Obj_Typ
:= Etype
(Obj_Id
);
823 if not Is_Class_Wide_Type
(Obj_Typ
) then
824 Obj_Typ
:= Base_Type
(Obj_Typ
);
827 if Is_Access_Type
(Obj_Typ
) then
828 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
829 Obj_Typ
:= Available_View
(Designated_Type
(Obj_Typ
));
832 -- If we are dealing with a return object of a build-in-place function
833 -- and its allocation has been done in the function, we additionally
834 -- need to detach it from the caller's finalization collection in order
835 -- to prevent double finalization.
838 and then Is_Build_In_Place_Function
(Func_Id
)
839 and then Needs_BIP_Collection
(Func_Id
)
842 Ptr_Typ
: constant Node_Id
:= Make_Temporary
(Loc
, 'P');
843 Param
: constant Entity_Id
:=
844 Make_Defining_Identifier
(Loc
, Name_V
);
850 Fin_Stmts
:= Make_Finalize_Address_Stmts
(Obj_Typ
);
852 Append_To
(Fin_Stmts
,
853 Build_BIP_Cleanup_Stmts
854 (Func_Id
, New_Occurrence_Of
(Param
, Loc
)));
857 Make_Defining_Identifier
(Loc
,
859 (Obj_Typ
, TSS_Finalize_Address
));
862 Make_Subprogram_Body
(Loc
,
864 Make_Procedure_Specification
(Loc
,
865 Defining_Unit_Name
=> Fin_Id
,
867 Parameter_Specifications
=> New_List
(
868 Make_Parameter_Specification
(Loc
,
869 Defining_Identifier
=> Param
,
871 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)))),
873 Declarations
=> New_List
(
874 Make_Full_Type_Declaration
(Loc
,
875 Defining_Identifier
=> Ptr_Typ
,
877 Make_Access_To_Object_Definition
(Loc
,
879 Subtype_Indication
=>
880 New_Occurrence_Of
(Obj_Typ
, Loc
)))),
882 Handled_Statement_Sequence
=>
883 Make_Handled_Sequence_Of_Statements
(Loc
,
884 Statements
=> Fin_Stmts
));
886 Insert_After_And_Analyze
887 (Master_Node_Ins
, Fin_Body
, Suppress
=> All_Checks
);
889 Master_Node_Ins
:= Fin_Body
;
893 Fin_Id
:= Finalize_Address
(Obj_Typ
);
895 if No
(Fin_Id
) and then Ekind
(Obj_Typ
) = E_Class_Wide_Subtype
then
896 Fin_Id
:= TSS
(Obj_Typ
, TSS_Finalize_Address
);
900 -- Now build the attachment call that will initialize the object's
901 -- Master_Node using the object's address and finalization procedure.
903 Master_Node_Attach
:=
904 Make_Procedure_Call_Statement
(Loc
,
906 New_Occurrence_Of
(RTE
(RE_Attach_Object_To_Node
), Loc
),
907 Parameter_Associations
=> New_List
(
908 Make_Address_For_Finalize
(Loc
, Obj_Ref
, Obj_Typ
),
909 Make_Attribute_Reference
(Loc
,
911 New_Occurrence_Of
(Fin_Id
, Loc
),
912 Attribute_Name
=> Name_Unrestricted_Access
),
913 New_Occurrence_Of
(Master_Node
, Loc
)));
915 Insert_After_And_Analyze
916 (Master_Node_Ins
, Master_Node_Attach
, Suppress
=> All_Checks
);
917 end Attach_Object_To_Master_Node
;
919 ------------------------------------
920 -- Allows_Finalization_Collection --
921 ------------------------------------
923 function Allows_Finalization_Collection
(Typ
: Entity_Id
) return Boolean is
924 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean;
925 -- Determine whether entity E is inside a wrapper package created for
926 -- an instance of Ada.Unchecked_Deallocation.
928 ------------------------------
929 -- In_Deallocation_Instance --
930 ------------------------------
932 function In_Deallocation_Instance
(E
: Entity_Id
) return Boolean is
933 Pkg
: constant Entity_Id
:= Scope
(E
);
934 Par
: Node_Id
:= Empty
;
937 if Ekind
(Pkg
) = E_Package
938 and then Present
(Related_Instance
(Pkg
))
939 and then Ekind
(Related_Instance
(Pkg
)) = E_Procedure
941 Par
:= Generic_Parent
(Parent
(Related_Instance
(Pkg
)));
945 and then Chars
(Par
) = Name_Unchecked_Deallocation
946 and then Chars
(Scope
(Par
)) = Name_Ada
947 and then Scope
(Scope
(Par
)) = Standard_Standard
;
951 end In_Deallocation_Instance
;
955 Desig_Typ
: constant Entity_Id
:= Designated_Type
(Typ
);
956 Ptr_Typ
: constant Entity_Id
:=
957 Root_Type_Of_Full_View
(Base_Type
(Typ
));
959 -- Start of processing for Allows_Finalization_Collection
962 -- Certain run-time configurations and targets do not provide support
963 -- for controlled types and therefore do not need collections.
965 if Restriction_Active
(No_Finalization
) then
968 -- Do not consider C and C++ types since it is assumed that the non-Ada
969 -- side will handle their cleanup.
971 elsif Convention
(Desig_Typ
) = Convention_C
972 or else Convention
(Desig_Typ
) = Convention_CPP
976 -- Do not consider an access type that returns on the secondary stack
978 elsif Present
(Associated_Storage_Pool
(Ptr_Typ
))
979 and then Is_RTE
(Associated_Storage_Pool
(Ptr_Typ
), RE_SS_Pool
)
983 -- Do not consider an access type that can never allocate an object
985 elsif No_Pool_Assigned
(Ptr_Typ
) then
988 -- Do not consider an access type coming from an Unchecked_Deallocation
989 -- instance. Even though the designated type may be controlled, the
990 -- access type will never participate in any allocations.
992 elsif In_Deallocation_Instance
(Ptr_Typ
) then
995 -- Do not consider a non-library access type when No_Nested_Finalization
996 -- is in effect, because finalization collections are controlled objects
997 -- and, if created, will violate the restriction.
999 elsif Restriction_Active
(No_Nested_Finalization
)
1000 and then not Is_Library_Level_Entity
(Ptr_Typ
)
1004 -- Do not consider an access type subject to pragma No_Heap_Finalization
1005 -- because objects allocated through such a type are not to be finalized
1006 -- when the access type goes out of scope.
1008 elsif No_Heap_Finalization
(Ptr_Typ
) then
1011 -- Do not create finalization collections in GNATprove mode because this
1012 -- causes unwanted extra expansion. Compilation in this mode must always
1013 -- keep the tree as close as possible to the original sources.
1015 elsif GNATprove_Mode
then
1018 -- Otherwise the access type may use a finalization collection
1023 end Allows_Finalization_Collection
;
1025 --------------------------------
1026 -- Build_Anonymous_Collection --
1027 --------------------------------
1029 procedure Build_Anonymous_Collection
(Ptr_Typ
: Entity_Id
) is
1030 function Create_Anonymous_Collection
1031 (Desig_Typ
: Entity_Id
;
1032 Unit_Id
: Entity_Id
;
1033 Unit_Decl
: Node_Id
) return Entity_Id
;
1034 -- Create a new anonymous collection for access type Ptr_Typ with
1035 -- designated type Desig_Typ. The declaration of the collection and
1036 -- its initialization are inserted in the declarative part of unit
1037 -- Unit_Decl. Unit_Id is the entity of Unit_Decl.
1039 function Current_Anonymous_Collection
1040 (Desig_Typ
: Entity_Id
;
1041 Unit_Id
: Entity_Id
) return Entity_Id
;
1042 -- Find an anonymous collection declared in unit Unit_Id which services
1043 -- designated type Desig_Typ. If there is none, return Empty.
1045 ---------------------------------
1046 -- Create_Anonymous_Collection --
1047 ---------------------------------
1049 function Create_Anonymous_Collection
1050 (Desig_Typ
: Entity_Id
;
1051 Unit_Id
: Entity_Id
;
1052 Unit_Decl
: Node_Id
) return Entity_Id
1054 Loc
: constant Source_Ptr
:= Sloc
(Unit_Id
);
1060 Unit_Spec
: Node_Id
;
1064 -- <FC_Id> : Finalization_Collection;
1066 FC_Id
:= Make_Temporary
(Loc
, 'A');
1069 Make_Object_Declaration
(Loc
,
1070 Defining_Identifier
=> FC_Id
,
1071 Object_Definition
=>
1072 New_Occurrence_Of
(RTE
(RE_Finalization_Collection
), Loc
));
1074 -- Find the declarative list of the unit
1076 if Nkind
(Unit_Decl
) = N_Package_Declaration
then
1077 Unit_Spec
:= Specification
(Unit_Decl
);
1078 Decls
:= Visible_Declarations
(Unit_Spec
);
1082 Set_Visible_Declarations
(Unit_Spec
, Decls
);
1085 -- Package body or subprogram case
1087 -- ??? A subprogram spec or body that acts as a compilation unit may
1088 -- contain a formal parameter of an anonymous access-to-controlled
1089 -- type initialized by an allocator.
1091 -- procedure Comp_Unit_Proc (Param : access Ctrl := new Ctrl);
1093 -- There is no suitable place to create the collection because the
1094 -- subprogram is not in a declarative list.
1097 Decls
:= Declarations
(Unit_Decl
);
1101 Set_Declarations
(Unit_Decl
, Decls
);
1105 Prepend_To
(Decls
, FC_Decl
);
1107 -- Use the scope of the unit when analyzing the declaration of the
1108 -- collection and its initialization actions.
1110 Push_Scope
(Unit_Id
);
1114 -- Mark the collection as servicing this specific designated type
1116 Set_Anonymous_Designated_Type
(FC_Id
, Desig_Typ
);
1118 -- Include it in the list of existing anonymous collections which
1119 -- appear in this unit. This effectively creates a mapping between
1120 -- collections and designated types, which in turn allows for the
1121 -- reuse of collections on a per-unit basis.
1123 All_FCs
:= Anonymous_Collections
(Unit_Id
);
1125 if No
(All_FCs
) then
1126 All_FCs
:= New_Elmt_List
;
1127 Set_Anonymous_Collections
(Unit_Id
, All_FCs
);
1130 Prepend_Elmt
(FC_Id
, All_FCs
);
1133 end Create_Anonymous_Collection
;
1135 ----------------------------------
1136 -- Current_Anonymous_Collection --
1137 ----------------------------------
1139 function Current_Anonymous_Collection
1140 (Desig_Typ
: Entity_Id
;
1141 Unit_Id
: Entity_Id
) return Entity_Id
1143 All_FCs
: constant Elist_Id
:= Anonymous_Collections
(Unit_Id
);
1148 -- Inspect the list of anonymous collections declared within the unit
1149 -- looking for an existing collection which services the designated
1152 if Present
(All_FCs
) then
1153 FC_Elmt
:= First_Elmt
(All_FCs
);
1154 while Present
(FC_Elmt
) loop
1155 FC_Id
:= Node
(FC_Elmt
);
1157 -- The current collection services the same designated type.
1158 -- As a result, the collection can be reused and associated
1159 -- with another anonymous access-to-controlled type.
1161 if Anonymous_Designated_Type
(FC_Id
) = Desig_Typ
then
1165 Next_Elmt
(FC_Elmt
);
1170 end Current_Anonymous_Collection
;
1174 Desig_Typ
: Entity_Id
;
1176 Priv_View
: Entity_Id
;
1178 Unit_Decl
: Node_Id
;
1179 Unit_Id
: Entity_Id
;
1181 -- Start of processing for Build_Anonymous_Collection
1184 -- Nothing to do if the circumstances do not allow for a finalization
1187 if not Allows_Finalization_Collection
(Ptr_Typ
) then
1191 Unit_Decl
:= Unit
(Cunit
(Current_Sem_Unit
));
1192 Unit_Id
:= Unique_Defining_Entity
(Unit_Decl
);
1194 -- The compilation unit is a package instantiation. In this case the
1195 -- anonymous collection is associated with the package spec, as both
1196 -- the spec and body appear at the same level.
1198 if Nkind
(Unit_Decl
) = N_Package_Body
1199 and then Nkind
(Original_Node
(Unit_Decl
)) = N_Package_Instantiation
1201 Unit_Id
:= Corresponding_Spec
(Unit_Decl
);
1202 Unit_Decl
:= Unit_Declaration_Node
(Unit_Id
);
1205 -- Use the initial declaration of the designated type when it denotes
1206 -- the full view of an incomplete or private type. This ensures that
1207 -- types with one and two views are treated the same.
1209 Desig_Typ
:= Directly_Designated_Type
(Ptr_Typ
);
1210 Priv_View
:= Incomplete_Or_Partial_View
(Desig_Typ
);
1212 if Present
(Priv_View
) then
1213 Desig_Typ
:= Priv_View
;
1216 -- For a designated type not declared at library level, we cannot create
1217 -- a finalization collection attached to an outer unit since this would
1218 -- generate dangling references to the dynamic scope through access-to-
1219 -- procedure values designating the local Finalize_Address primitive.
1221 Scop
:= Enclosing_Dynamic_Scope
(Desig_Typ
);
1222 if Scop
/= Standard_Standard
1223 and then Scope_Depth
(Scop
) > Scope_Depth
(Unit_Id
)
1228 -- Determine whether the current semantic unit already has an anonymous
1229 -- collection which services the designated type.
1231 FC_Id
:= Current_Anonymous_Collection
(Desig_Typ
, Unit_Id
);
1233 -- If this is not the case, create a new collection
1236 FC_Id
:= Create_Anonymous_Collection
(Desig_Typ
, Unit_Id
, Unit_Decl
);
1239 Set_Finalization_Collection
(Ptr_Typ
, FC_Id
);
1240 end Build_Anonymous_Collection
;
1242 ----------------------------
1243 -- Build_Array_Deep_Procs --
1244 ----------------------------
1246 procedure Build_Array_Deep_Procs
(Typ
: Entity_Id
) is
1250 (Prim
=> Initialize_Case
,
1252 Stmts
=> Make_Deep_Array_Body
(Initialize_Case
, Typ
)));
1254 if not Is_Inherently_Limited_Type
(Typ
) then
1257 (Prim
=> Adjust_Case
,
1259 Stmts
=> Make_Deep_Array_Body
(Adjust_Case
, Typ
)));
1262 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
1263 -- suppressed since these routine will not be used.
1265 if not Restriction_Active
(No_Finalization
) then
1268 (Prim
=> Finalize_Case
,
1270 Stmts
=> Make_Deep_Array_Body
(Finalize_Case
, Typ
)));
1272 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
1274 if not CodePeer_Mode
then
1277 (Prim
=> Address_Case
,
1279 Stmts
=> Make_Deep_Array_Body
(Address_Case
, Typ
)));
1282 end Build_Array_Deep_Procs
;
1284 ------------------------------
1285 -- Build_Cleanup_Statements --
1286 ------------------------------
1288 function Build_Cleanup_Statements
1290 Additional_Cleanup
: List_Id
) return List_Id
1292 Is_Asynchronous_Call
: constant Boolean :=
1293 Nkind
(N
) = N_Block_Statement
and then Is_Asynchronous_Call_Block
(N
);
1294 Is_Master
: constant Boolean :=
1295 Nkind
(N
) /= N_Entry_Body
and then Is_Task_Master
(N
);
1296 Is_Protected_Subp_Body
: constant Boolean :=
1297 Nkind
(N
) = N_Subprogram_Body
1298 and then Is_Protected_Subprogram_Body
(N
);
1299 Is_Task_Allocation
: constant Boolean :=
1300 Nkind
(N
) = N_Block_Statement
and then Is_Task_Allocation_Block
(N
);
1301 Is_Task_Body
: constant Boolean :=
1302 Nkind
(Original_Node
(N
)) = N_Task_Body
;
1304 Loc
: constant Source_Ptr
:= Sloc
(N
);
1305 Stmts
: constant List_Id
:= New_List
;
1308 if Is_Task_Body
then
1309 if Restricted_Profile
then
1311 Build_Runtime_Call
(Loc
, RE_Complete_Restricted_Task
));
1313 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Task
));
1316 elsif Is_Master
then
1317 if Restriction_Active
(No_Task_Hierarchy
) = False then
1318 Append_To
(Stmts
, Build_Runtime_Call
(Loc
, RE_Complete_Master
));
1321 -- Add statements to unlock the protected object parameter and to
1322 -- undefer abort. If the context is a protected procedure and the object
1323 -- has entries, call the entry service routine.
1325 -- NOTE: The generated code references _object, a parameter to the
1328 elsif Is_Protected_Subp_Body
then
1330 Spec
: constant Node_Id
:= Parent
(Corresponding_Spec
(N
));
1331 Conc_Typ
: Entity_Id
:= Empty
;
1333 Param_Typ
: Entity_Id
;
1336 -- Find the _object parameter representing the protected object
1338 Param
:= First
(Parameter_Specifications
(Spec
));
1340 Param_Typ
:= Etype
(Parameter_Type
(Param
));
1342 if Ekind
(Param_Typ
) = E_Record_Type
then
1343 Conc_Typ
:= Corresponding_Concurrent_Type
(Param_Typ
);
1346 exit when No
(Param
) or else Present
(Conc_Typ
);
1350 pragma Assert
(Present
(Param
));
1351 pragma Assert
(Present
(Conc_Typ
));
1353 Build_Protected_Subprogram_Call_Cleanup
1354 (Specification
(N
), Conc_Typ
, Loc
, Stmts
);
1357 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
1358 -- tasks. Other unactivated tasks are completed by Complete_Task or
1361 -- NOTE: The generated code references _chain, a local object
1363 elsif Is_Task_Allocation
then
1366 -- Expunge_Unactivated_Tasks (_chain);
1368 -- where _chain is the list of tasks created by the allocator but not
1369 -- yet activated. This list will be empty unless the block completes
1373 Make_Procedure_Call_Statement
(Loc
,
1376 (RTE
(RE_Expunge_Unactivated_Tasks
), Loc
),
1377 Parameter_Associations
=> New_List
(
1378 New_Occurrence_Of
(Activation_Chain_Entity
(N
), Loc
))));
1380 -- Attempt to cancel an asynchronous entry call whenever the block which
1381 -- contains the abortable part is exited.
1383 -- NOTE: The generated code references Cnn, a local object
1385 elsif Is_Asynchronous_Call
then
1387 Cancel_Param
: constant Entity_Id
:=
1388 Entry_Cancel_Parameter
(Entity
(Identifier
(N
)));
1391 -- If it is of type Communication_Block, this must be a protected
1392 -- entry call. Generate:
1394 -- if Enqueued (Cancel_Param) then
1395 -- Cancel_Protected_Entry_Call (Cancel_Param);
1398 if Is_RTE
(Etype
(Cancel_Param
), RE_Communication_Block
) then
1400 Make_If_Statement
(Loc
,
1402 Make_Function_Call
(Loc
,
1404 New_Occurrence_Of
(RTE
(RE_Enqueued
), Loc
),
1405 Parameter_Associations
=> New_List
(
1406 New_Occurrence_Of
(Cancel_Param
, Loc
))),
1408 Then_Statements
=> New_List
(
1409 Make_Procedure_Call_Statement
(Loc
,
1412 (RTE
(RE_Cancel_Protected_Entry_Call
), Loc
),
1413 Parameter_Associations
=> New_List
(
1414 New_Occurrence_Of
(Cancel_Param
, Loc
))))));
1416 -- Asynchronous delay, generate:
1417 -- Cancel_Async_Delay (Cancel_Param);
1419 elsif Is_RTE
(Etype
(Cancel_Param
), RE_Delay_Block
) then
1421 Make_Procedure_Call_Statement
(Loc
,
1423 New_Occurrence_Of
(RTE
(RE_Cancel_Async_Delay
), Loc
),
1424 Parameter_Associations
=> New_List
(
1425 Make_Attribute_Reference
(Loc
,
1427 New_Occurrence_Of
(Cancel_Param
, Loc
),
1428 Attribute_Name
=> Name_Unchecked_Access
))));
1430 -- Task entry call, generate:
1431 -- Cancel_Task_Entry_Call (Cancel_Param);
1435 Make_Procedure_Call_Statement
(Loc
,
1437 New_Occurrence_Of
(RTE
(RE_Cancel_Task_Entry_Call
), Loc
),
1438 Parameter_Associations
=> New_List
(
1439 New_Occurrence_Of
(Cancel_Param
, Loc
))));
1444 Append_List_To
(Stmts
, Additional_Cleanup
);
1446 end Build_Cleanup_Statements
;
1448 -----------------------------
1449 -- Build_Controlling_Procs --
1450 -----------------------------
1452 procedure Build_Controlling_Procs
(Typ
: Entity_Id
) is
1454 if Is_Array_Type
(Typ
) then
1455 Build_Array_Deep_Procs
(Typ
);
1456 else pragma Assert
(Is_Record_Type
(Typ
));
1457 Build_Record_Deep_Procs
(Typ
);
1459 end Build_Controlling_Procs
;
1461 -----------------------------
1462 -- Build_Exception_Handler --
1463 -----------------------------
1465 function Build_Exception_Handler
1466 (Data
: Finalization_Exception_Data
;
1467 For_Library
: Boolean := False) return Node_Id
1470 Proc_To_Call
: Entity_Id
;
1475 pragma Assert
(Present
(Data
.Raised_Id
));
1477 if Exception_Extra_Info
1478 or else (For_Library
and not Restricted_Profile
)
1480 if Exception_Extra_Info
then
1484 -- Get_Current_Excep.all
1487 Make_Function_Call
(Data
.Loc
,
1489 Make_Explicit_Dereference
(Data
.Loc
,
1492 (RTE
(RE_Get_Current_Excep
), Data
.Loc
)));
1499 Except
:= Make_Null
(Data
.Loc
);
1502 if For_Library
and then not Restricted_Profile
then
1503 Proc_To_Call
:= RTE
(RE_Save_Library_Occurrence
);
1504 Actuals
:= New_List
(Except
);
1507 Proc_To_Call
:= RTE
(RE_Save_Occurrence
);
1509 -- The dereference occurs only when Exception_Extra_Info is true,
1510 -- and therefore Except is not null.
1514 New_Occurrence_Of
(Data
.E_Id
, Data
.Loc
),
1515 Make_Explicit_Dereference
(Data
.Loc
, Except
));
1521 -- if not Raised_Id then
1522 -- Raised_Id := True;
1524 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
1526 -- Save_Library_Occurrence (Get_Current_Excep.all);
1531 Make_If_Statement
(Data
.Loc
,
1533 Make_Op_Not
(Data
.Loc
,
1534 Right_Opnd
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
)),
1536 Then_Statements
=> New_List
(
1537 Make_Assignment_Statement
(Data
.Loc
,
1538 Name
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
),
1539 Expression
=> New_Occurrence_Of
(Standard_True
, Data
.Loc
)),
1541 Make_Procedure_Call_Statement
(Data
.Loc
,
1543 New_Occurrence_Of
(Proc_To_Call
, Data
.Loc
),
1544 Parameter_Associations
=> Actuals
))));
1549 -- Raised_Id := True;
1552 Make_Assignment_Statement
(Data
.Loc
,
1553 Name
=> New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
),
1554 Expression
=> New_Occurrence_Of
(Standard_True
, Data
.Loc
)));
1562 Make_Exception_Handler
(Data
.Loc
,
1563 Exception_Choices
=> New_List
(Make_Others_Choice
(Data
.Loc
)),
1564 Statements
=> Stmts
);
1565 end Build_Exception_Handler
;
1567 -----------------------------------
1568 -- Build_Finalization_Collection --
1569 -----------------------------------
1571 procedure Build_Finalization_Collection
1573 For_Lib_Level
: Boolean := False;
1574 For_Private
: Boolean := False;
1575 Context_Scope
: Entity_Id
:= Empty
;
1576 Insertion_Node
: Node_Id
:= Empty
)
1578 Ptr_Typ
: constant Entity_Id
:= Root_Type_Of_Full_View
(Base_Type
(Typ
));
1579 -- Finalization collections built for named access types are associated
1580 -- with the full view (if applicable) as a consequence of freezing. The
1581 -- full view criteria does not apply to anonymous access types because
1582 -- those cannot have a private and a full view.
1584 -- Start of processing for Build_Finalization_Collection
1587 -- Nothing to do if the circumstances do not allow for a finalization
1590 if not Allows_Finalization_Collection
(Typ
) then
1593 -- Various machinery such as freezing may have already created a
1594 -- finalization collection.
1596 elsif Present
(Finalization_Collection
(Ptr_Typ
)) then
1601 Actions
: constant List_Id
:= New_List
;
1602 Loc
: constant Source_Ptr
:= Sloc
(Ptr_Typ
);
1604 Fin_Coll_Id
: Entity_Id
;
1605 Pool_Id
: Entity_Id
;
1608 -- Source access types use fixed names since the collection will be
1609 -- inserted in the same source unit only once. The only exception to
1610 -- this are instances using the same access type as generic actual.
1612 if Comes_From_Source
(Ptr_Typ
) and then not Inside_A_Generic
then
1614 Make_Defining_Identifier
(Loc
,
1615 Chars
=> New_External_Name
(Chars
(Ptr_Typ
), "FC"));
1617 -- Internally generated access types use temporaries as their names
1618 -- due to possible collision with identical names coming from other
1622 Fin_Coll_Id
:= Make_Temporary
(Loc
, 'F');
1625 Set_Finalization_Collection
(Ptr_Typ
, Fin_Coll_Id
);
1628 -- <Ptr_Typ>FC : aliased Finalization_Collection;
1631 Make_Object_Declaration
(Loc
,
1632 Defining_Identifier
=> Fin_Coll_Id
,
1633 Aliased_Present
=> True,
1634 Object_Definition
=>
1635 New_Occurrence_Of
(RTE
(RE_Finalization_Collection
), Loc
)));
1637 if Debug_Generated_Code
then
1638 Set_Debug_Info_Needed
(Fin_Coll_Id
);
1641 -- Set the associated pool and primitive Finalize_Address of the new
1642 -- finalization collection.
1644 -- The access type has a user-defined storage pool, use it
1646 if Present
(Associated_Storage_Pool
(Ptr_Typ
)) then
1647 Pool_Id
:= Associated_Storage_Pool
(Ptr_Typ
);
1649 -- Otherwise the default choice is the global storage pool
1652 Pool_Id
:= RTE
(RE_Global_Pool_Object
);
1653 Set_Associated_Storage_Pool
(Ptr_Typ
, Pool_Id
);
1656 -- A finalization collection created for an access designating a type
1657 -- with private components is inserted before a context-dependent
1662 -- At this point both the scope of the context and the insertion
1663 -- mode must be known.
1665 pragma Assert
(Present
(Context_Scope
));
1666 pragma Assert
(Present
(Insertion_Node
));
1668 Push_Scope
(Context_Scope
);
1670 -- Treat use clauses as declarations and insert directly in front
1673 if Nkind
(Insertion_Node
) in
1674 N_Use_Package_Clause | N_Use_Type_Clause
1676 Insert_List_Before_And_Analyze
(Insertion_Node
, Actions
);
1678 Insert_Actions
(Insertion_Node
, Actions
);
1683 -- The finalization collection belongs to an access type related
1684 -- to a build-in-place function call used to initialize a library
1685 -- level object. The collection must be inserted in front of the
1686 -- access type declaration denoted by Insertion_Node.
1688 elsif For_Lib_Level
then
1689 pragma Assert
(Present
(Insertion_Node
));
1690 Insert_Actions
(Insertion_Node
, Actions
);
1692 -- Otherwise the finalization collection and its initialization
1693 -- become a part of the freeze node.
1696 Append_Freeze_Actions
(Ptr_Typ
, Actions
);
1699 Analyze_List
(Actions
);
1701 -- When the type the finalization collection is being generated for
1702 -- was created to store a 'Old object, then mark it as such so its
1703 -- finalization can be delayed until after postconditions have been
1706 if Stores_Attribute_Old_Prefix
(Ptr_Typ
) then
1707 Set_Stores_Attribute_Old_Prefix
(Fin_Coll_Id
);
1710 end Build_Finalization_Collection
;
1712 ---------------------
1713 -- Build_Finalizer --
1714 ---------------------
1716 procedure Build_Finalizer
1718 Clean_Stmts
: List_Id
;
1719 Mark_Id
: Entity_Id
;
1720 Top_Decls
: List_Id
;
1721 Defer_Abort
: Boolean;
1722 Fin_Id
: out Entity_Id
)
1724 Acts_As_Clean
: constant Boolean :=
1727 (Present
(Clean_Stmts
)
1728 and then Is_Non_Empty_List
(Clean_Stmts
));
1730 For_Package_Body
: constant Boolean := Nkind
(N
) = N_Package_Body
;
1731 For_Package_Spec
: constant Boolean := Nkind
(N
) = N_Package_Declaration
;
1732 For_Package
: constant Boolean :=
1733 For_Package_Body
or else For_Package_Spec
;
1734 Loc
: constant Source_Ptr
:= Sloc
(N
);
1736 -- NOTE: Local variable declarations are conservative and do not create
1737 -- structures right from the start. Entities and lists are created once
1738 -- it has been established that N has at least one controlled object.
1740 Counter_Val
: Nat
:= 0;
1741 -- Holds the number of controlled objects encountered so far
1743 Decls
: List_Id
:= No_List
;
1744 -- Declarative region of N (if available). If N is a package declaration
1745 -- Decls denotes the visible declarations.
1747 Finalizer_Data
: Finalization_Exception_Data
;
1748 -- Data for the exception
1750 Finalizer_Decls
: List_Id
:= No_List
;
1751 -- Local variable declarations
1753 Finalization_Master
: Entity_Id
;
1754 -- The Finalization Master object
1756 Finalizer_Stmts
: List_Id
:= No_List
;
1757 -- The statement list of the finalizer body
1759 Has_Ctrl_Objs
: Boolean := False;
1760 -- A general flag which denotes whether N has at least one controlled
1763 Has_Tagged_Types
: Boolean := False;
1764 -- A general flag which indicates whether N has at least one library-
1765 -- level tagged type declaration.
1767 HSS
: Node_Id
:= Empty
;
1768 -- The sequence of statements of N (if available)
1770 Prev_At_End
: Entity_Id
:= Empty
;
1771 -- The previous at end procedure of the handled statements block of N
1773 Priv_Decls
: List_Id
:= No_List
;
1774 -- The private declarations of N if N is a package declaration
1776 Spec_Id
: Entity_Id
:= Empty
;
1777 Spec_Decls
: List_Id
:= Top_Decls
;
1778 Stmts
: List_Id
:= No_List
;
1780 Tagged_Type_Stmts
: List_Id
:= No_List
;
1781 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1782 -- tagged types found in N.
1784 -----------------------
1785 -- Local subprograms --
1786 -----------------------
1788 procedure Build_Components
;
1789 -- Create all entites and initialize all lists used in the creation of
1792 procedure Create_Finalizer
;
1793 -- Create the spec and body of the finalizer and insert them in the
1794 -- proper place in the tree depending on the context.
1796 function New_Finalizer_Name
1797 (Spec_Id
: Node_Id
; For_Spec
: Boolean) return Name_Id
;
1798 -- Create a fully qualified name of a package spec or body finalizer.
1799 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1801 procedure Process_Declarations
1803 Preprocess
: Boolean := False);
1804 -- Inspect a list of declarations or statements which may contain
1805 -- objects that need finalization. When flag Preprocess is set, the
1806 -- routine will simply count the total number of controlled objects in
1807 -- Decls and set Counter_Val accordingly.
1809 procedure Process_Object_Declaration
1811 Is_Protected
: Boolean := False);
1812 -- Generate all the machinery associated with the finalization of a
1813 -- single object. Flag Is_Protected is set when Decl denotes a simple
1814 -- protected object.
1816 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
);
1817 -- Generate all the code necessary to unregister the external tag of a
1820 ----------------------
1821 -- Build_Components --
1822 ----------------------
1824 procedure Build_Components
is
1825 Constraints
: List_Id
;
1826 Master_Decl
: Node_Id
;
1827 Master_Name
: Name_Id
;
1830 pragma Assert
(Present
(Decls
));
1832 -- If the context contains controlled objects, then we create the
1833 -- finalization master, unless there is a single such object: in
1834 -- this common case, we'll directly finalize the object.
1836 if Has_Ctrl_Objs
then
1837 if Counter_Val
> 1 then
1838 if For_Package_Spec
then
1840 New_External_Name
(Name_uMaster
, Suffix
=> "_spec");
1841 elsif For_Package_Body
then
1843 New_External_Name
(Name_uMaster
, Suffix
=> "_body");
1845 Master_Name
:= New_Internal_Name
('M');
1848 Finalization_Master
:=
1849 Make_Defining_Identifier
(Loc
, Master_Name
);
1851 -- The master is statically parameterized by the context
1853 Constraints
:= New_List
;
1854 Append_To
(Constraints
,
1855 New_Occurrence_Of
(Boolean_Literals
(Exceptions_OK
), Loc
));
1856 Append_To
(Constraints
,
1858 (Boolean_Literals
(Exception_Extra_Info
), Loc
));
1859 Append_To
(Constraints
,
1860 New_Occurrence_Of
(Boolean_Literals
(For_Package
), Loc
));
1863 Make_Object_Declaration
(Loc
,
1864 Defining_Identifier
=> Finalization_Master
,
1865 Object_Definition
=>
1866 Make_Subtype_Indication
(Loc
,
1869 (RTE
(RE_Finalization_Master
), Loc
),
1871 Make_Index_Or_Discriminant_Constraint
(Loc
,
1872 Constraints
=> Constraints
)));
1874 Prepend_To
(Decls
, Master_Decl
);
1875 Analyze
(Master_Decl
, Suppress
=> All_Checks
);
1878 if Exceptions_OK
then
1879 Finalizer_Decls
:= New_List
;
1881 Build_Object_Declarations
1882 (Finalizer_Data
, Finalizer_Decls
, Loc
, For_Package
);
1885 Finalizer_Decls
:= No_List
;
1889 -- If the context requires additional cleanup, the finalization
1890 -- machinery is added after the cleanup code.
1892 if Acts_As_Clean
then
1893 Finalizer_Stmts
:= Clean_Stmts
;
1895 Finalizer_Stmts
:= New_List
;
1898 if Has_Tagged_Types
then
1899 Tagged_Type_Stmts
:= New_List
;
1901 end Build_Components
;
1903 ----------------------
1904 -- Create_Finalizer --
1905 ----------------------
1907 procedure Create_Finalizer
is
1908 Body_Id
: Entity_Id
;
1914 -- Step 1: Creation of the finalizer name
1916 -- Packages must use a distinct name for their finalizers since the
1917 -- binder will have to generate calls to them by name. The name is
1918 -- of the following form:
1920 -- xx__yy__finalize_[spec|body]
1923 Fin_Id
:= Make_Defining_Identifier
1924 (Loc
, New_Finalizer_Name
(Spec_Id
, For_Package_Spec
));
1925 Set_Has_Qualified_Name
(Fin_Id
);
1926 Set_Has_Fully_Qualified_Name
(Fin_Id
);
1928 -- The default name is _finalizer
1931 -- Generation of a finalization procedure exclusively for 'Old
1932 -- interally generated constants requires different name since
1933 -- there will need to be multiple finalization routines in the
1934 -- same scope. See Build_Finalizer for details.
1937 Make_Defining_Identifier
(Loc
,
1938 Chars
=> New_External_Name
(Name_uFinalizer
));
1940 -- Inlining the finalizer produces a substantial speedup at -O2.
1941 -- It is inlined by default at -O3. Either way, it is called
1942 -- exactly twice (once on the normal path, and once for
1943 -- exceptions/abort), so this won't bloat the code too much.
1945 Set_Is_Inlined
(Fin_Id
);
1948 if Debug_Generated_Code
then
1949 Set_Debug_Info_Needed
(Fin_Id
);
1952 -- Step 2: Creation of the finalizer specification
1955 -- procedure Fin_Id;
1958 Make_Subprogram_Declaration
(Loc
,
1960 Make_Procedure_Specification
(Loc
,
1961 Defining_Unit_Name
=> Fin_Id
));
1964 Set_Is_Exported
(Fin_Id
);
1965 Set_Interface_Name
(Fin_Id
,
1966 Make_String_Literal
(Loc
,
1967 Strval
=> Get_Name_String
(Chars
(Fin_Id
))));
1970 -- Step 3: Creation of the finalizer body
1972 -- Add the library-level tagged type unregistration machinery before
1973 -- the finalization circuitry. This ensures that external tags will
1974 -- be removed even if a finalization exception occurs at some point.
1976 if Has_Tagged_Types
then
1977 Prepend_List_To
(Finalizer_Stmts
, Tagged_Type_Stmts
);
1980 -- Add a call to the previous At_End handler if it exists. The call
1981 -- must always precede the finalization circuitry.
1983 if Present
(Prev_At_End
) then
1984 Prepend_To
(Finalizer_Stmts
,
1985 Make_Procedure_Call_Statement
(Loc
, Prev_At_End
));
1987 -- Clear the At_End handler since we have already generated the
1988 -- proper replacement call for it.
1990 Set_At_End_Proc
(HSS
, Empty
);
1993 -- If there are no controlled objects to be finalized, generate;
1995 -- procedure Fin_Id is
1997 -- Abort_Defer; -- Added if abort is allowed
1998 -- <call to Prev_At_End> -- Added if exists
1999 -- <tag unregistration> -- Added if Has_Tagged_Types
2000 -- <cleanup statements> -- Added if Acts_As_Clean
2001 -- <stack release> -- Added if Mark_Id exists
2002 -- Abort_Undefer; -- Added if abort is allowed
2005 -- If there are controlled objects to be finalized, generate:
2007 -- procedure Fin_Id is
2008 -- Abort : constant Boolean := Triggered_By_Abort;
2009 -- E : Exception_Occurrence;
2010 -- Raised : Boolean := False;
2012 -- Abort_Defer; -- Added if abort is allowed
2013 -- <call to Prev_At_End> -- Added if exists
2014 -- <tag unregistration> -- Added if Has_Tagged_Types
2015 -- <cleanup statements> -- Added if Acts_As_Clean
2016 -- <finalization statements>
2017 -- <stack release> -- Added if Mark_Id exists
2018 -- Abort_Undefer; -- Added if abort is allowed
2021 if Has_Ctrl_Objs
and then Counter_Val
> 1 then
2023 Make_Procedure_Call_Statement
(Loc
,
2025 New_Occurrence_Of
(RTE
(RE_Finalize_Master
), Loc
),
2026 Parameter_Associations
=>
2027 New_List
(New_Occurrence_Of
(Finalization_Master
, Loc
)));
2029 -- For CodePeer, the exception handlers normally generated here
2030 -- generate complex flowgraphs which result in capacity problems.
2031 -- Omitting these handlers for CodePeer is justified as follows:
2033 -- If a handler is dead, then omitting it is surely ok
2035 -- If a handler is live, then CodePeer should flag the
2036 -- potentially-exception-raising construct that causes it
2037 -- to be live. That is what we are interested in, not what
2038 -- happens after the exception is raised.
2040 if Exceptions_OK
and not CodePeer_Mode
then
2042 Make_Block_Statement
(Loc
,
2043 Handled_Statement_Sequence
=>
2044 Make_Handled_Sequence_Of_Statements
(Loc
,
2045 Statements
=> New_List
(Fin_Call
),
2047 Exception_Handlers
=> New_List
(
2048 Build_Exception_Handler
2049 (Finalizer_Data
, For_Package
))));
2052 Append_To
(Finalizer_Stmts
, Fin_Call
);
2055 -- Release the secondary stack
2057 if Present
(Mark_Id
) then
2059 Release
: Node_Id
:= Build_SS_Release_Call
(Loc
, Mark_Id
);
2062 -- If the context is a build-in-place function, the secondary
2063 -- stack must be released, unless the build-in-place function
2064 -- itself is returning on the secondary stack. Generate:
2066 -- if BIP_Alloc_Form /= Secondary_Stack then
2067 -- SS_Release (Mark_Id);
2070 -- Note that if the function returns on the secondary stack,
2071 -- then the responsibility of reclaiming the space is always
2072 -- left to the caller (recursively if needed).
2074 if Nkind
(N
) = N_Subprogram_Body
then
2076 Spec_Id
: constant Entity_Id
:=
2077 Unique_Defining_Entity
(N
);
2078 BIP_SS
: constant Boolean :=
2079 Is_Build_In_Place_Function
(Spec_Id
)
2080 and then Needs_BIP_Alloc_Form
(Spec_Id
);
2084 Make_If_Statement
(Loc
,
2089 (Build_In_Place_Formal
2090 (Spec_Id
, BIP_Alloc_Form
), Loc
),
2092 Make_Integer_Literal
(Loc
,
2094 (BIP_Allocation_Form
'Pos
2095 (Secondary_Stack
)))),
2097 Then_Statements
=> New_List
(Release
));
2102 Append_To
(Finalizer_Stmts
, Release
);
2106 -- Protect the statements with abort defer/undefer. This is only when
2107 -- aborts are allowed and the cleanup statements require deferral or
2108 -- there are controlled objects to be finalized. Note that the abort
2109 -- defer/undefer pair does not require an extra block because the
2110 -- finalization exception is caught in its corresponding finalization
2111 -- block. As a result, the call to Abort_Defer always takes place.
2113 if Abort_Allowed
and then (Defer_Abort
or Has_Ctrl_Objs
) then
2114 Prepend_To
(Finalizer_Stmts
,
2115 Build_Runtime_Call
(Loc
, RE_Abort_Defer
));
2117 Append_To
(Finalizer_Stmts
,
2118 Build_Runtime_Call
(Loc
, RE_Abort_Undefer
));
2121 -- The local exception does not need to be reraised for library-level
2122 -- finalizers. Note that this action must be carried out after object
2123 -- cleanup, secondary stack release, and abort undeferral. Generate:
2125 -- if Raised and then not Abort then
2126 -- Raise_From_Controlled_Operation (E);
2129 if Has_Ctrl_Objs
and Exceptions_OK
and not For_Package
then
2130 Append_To
(Finalizer_Stmts
,
2131 Build_Raise_Statement
(Finalizer_Data
));
2134 -- Create the body of the finalizer
2136 Body_Id
:= Make_Defining_Identifier
(Loc
, Chars
(Fin_Id
));
2138 if Debug_Generated_Code
then
2139 Set_Debug_Info_Needed
(Body_Id
);
2143 Set_Has_Qualified_Name
(Body_Id
);
2144 Set_Has_Fully_Qualified_Name
(Body_Id
);
2148 Make_Subprogram_Body
(Loc
,
2150 Make_Procedure_Specification
(Loc
,
2151 Defining_Unit_Name
=> Body_Id
),
2152 Declarations
=> Finalizer_Decls
,
2153 Handled_Statement_Sequence
=>
2154 Make_Handled_Sequence_Of_Statements
(Loc
,
2155 Statements
=> Finalizer_Stmts
));
2157 -- Step 4: Spec and body insertion, analysis
2161 -- If a package spec has private declarations, both the finalizer
2162 -- spec and body are inserted at the end of this list.
2164 if For_Package_Spec
and then Present
(Priv_Decls
) then
2165 Append_To
(Priv_Decls
, Fin_Spec
);
2166 Append_To
(Priv_Decls
, Fin_Body
);
2168 -- Otherwise, and for a package body, both the finalizer spec and
2169 -- body are inserted at the end of the package declarations.
2172 Append_To
(Decls
, Fin_Spec
);
2173 Append_To
(Decls
, Fin_Body
);
2179 pragma Assert
(Present
(Spec_Decls
));
2181 Append_To
(Spec_Decls
, Fin_Spec
);
2182 Append_To
(Spec_Decls
, Fin_Body
);
2185 Analyze
(Fin_Spec
, Suppress
=> All_Checks
);
2186 Analyze
(Fin_Body
, Suppress
=> All_Checks
);
2188 -- Never consider that the finalizer procedure is enabled Ghost, even
2189 -- when the corresponding unit is Ghost, as this would lead to an
2190 -- an external name with a ___ghost_ prefix that the binder cannot
2191 -- generate, as it has no knowledge of the Ghost status of units.
2193 Set_Is_Checked_Ghost_Entity
(Fin_Id
, False);
2194 end Create_Finalizer
;
2196 ------------------------
2197 -- New_Finalizer_Name --
2198 ------------------------
2200 function New_Finalizer_Name
2201 (Spec_Id
: Node_Id
; For_Spec
: Boolean) return Name_Id
2203 procedure New_Finalizer_Name
(Id
: Entity_Id
);
2204 -- Place "__<name-of-Id>" in the name buffer. If the identifier
2205 -- has a non-standard scope, process the scope first.
2207 ------------------------
2208 -- New_Finalizer_Name --
2209 ------------------------
2211 procedure New_Finalizer_Name
(Id
: Entity_Id
) is
2213 if Scope
(Id
) = Standard_Standard
then
2214 Get_Name_String
(Chars
(Id
));
2217 New_Finalizer_Name
(Scope
(Id
));
2218 Add_Str_To_Name_Buffer
("__");
2219 Get_Name_String_And_Append
(Chars
(Id
));
2221 end New_Finalizer_Name
;
2223 -- Start of processing for New_Finalizer_Name
2226 -- Create the fully qualified name of the enclosing scope
2228 New_Finalizer_Name
(Spec_Id
);
2231 -- __finalize_[spec|body]
2233 Add_Str_To_Name_Buffer
("__finalize_");
2236 Add_Str_To_Name_Buffer
("spec");
2238 Add_Str_To_Name_Buffer
("body");
2242 end New_Finalizer_Name
;
2244 --------------------------
2245 -- Process_Declarations --
2246 --------------------------
2248 procedure Process_Declarations
2250 Preprocess
: Boolean := False)
2252 procedure Process_Package_Body
(Decl
: Node_Id
);
2253 -- Process an N_Package_Body node
2255 procedure Processing_Actions
2257 Is_Protected
: Boolean := False);
2258 -- Depending on the mode of operation of Process_Declarations, either
2259 -- increment the controlled object counter, set the controlled object
2260 -- flag and store the last top level construct or process the current
2261 -- declaration. Flag Is_Protected is set when the current declaration
2262 -- denotes a simple protected object.
2264 --------------------------
2265 -- Process_Package_Body --
2266 --------------------------
2268 procedure Process_Package_Body
(Decl
: Node_Id
) is
2270 -- Do not inspect an ignored Ghost package body because all
2271 -- code found within will not appear in the final tree.
2273 if Is_Ignored_Ghost_Entity
(Defining_Entity
(Decl
)) then
2276 elsif Ekind
(Corresponding_Spec
(Decl
)) /= E_Generic_Package
then
2277 Process_Declarations
(Declarations
(Decl
), Preprocess
);
2279 end Process_Package_Body
;
2281 ------------------------
2282 -- Processing_Actions --
2283 ------------------------
2285 procedure Processing_Actions
2287 Is_Protected
: Boolean := False)
2290 -- Library-level tagged type
2292 if Nkind
(Decl
) = N_Full_Type_Declaration
then
2294 Has_Tagged_Types
:= True;
2296 -- Unregister tagged type, unless No_Tagged_Type_Registration
2299 elsif not Restriction_Active
(No_Tagged_Type_Registration
) then
2300 Process_Tagged_Type_Declaration
(Decl
);
2303 -- Controlled object declaration
2307 Counter_Val
:= Counter_Val
+ 1;
2308 Has_Ctrl_Objs
:= True;
2311 Process_Object_Declaration
(Decl
, Is_Protected
);
2314 end Processing_Actions
;
2321 Obj_Typ
: Entity_Id
;
2322 Pack_Id
: Entity_Id
;
2326 -- Start of processing for Process_Declarations
2329 if Is_Empty_List
(Decls
) then
2333 -- Process all declarations in reverse order
2335 Decl
:= Last_Non_Pragma
(Decls
);
2336 while Present
(Decl
) loop
2337 -- Library-level tagged types
2339 if Nkind
(Decl
) = N_Full_Type_Declaration
then
2340 Typ
:= Defining_Identifier
(Decl
);
2342 -- Ignored Ghost types do not need any cleanup actions because
2343 -- they will not appear in the final tree.
2345 if Is_Ignored_Ghost_Entity
(Typ
) then
2348 elsif Is_Tagged_Type
(Typ
)
2349 and then Is_Library_Level_Entity
(Typ
)
2350 and then Convention
(Typ
) = Convention_Ada
2351 and then Present
(Access_Disp_Table
(Typ
))
2352 and then not Is_Abstract_Type
(Typ
)
2353 and then not No_Run_Time_Mode
2354 and then not Restriction_Active
(No_Tagged_Type_Registration
)
2355 and then RTE_Available
(RE_Register_Tag
)
2357 Processing_Actions
(Decl
);
2360 -- Regular object declarations
2362 elsif Nkind
(Decl
) = N_Object_Declaration
then
2363 Obj_Id
:= Defining_Identifier
(Decl
);
2364 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
2365 Expr
:= Expression
(Decl
);
2367 -- Bypass any form of processing for objects which have their
2368 -- finalization disabled. This applies only to objects at the
2371 if For_Package
and then Finalize_Storage_Only
(Obj_Typ
) then
2374 -- Finalization of transient objects is treated separately in
2375 -- order to handle sensitive cases. These include:
2377 -- * Conditional expressions
2378 -- * Expressions with actions
2379 -- * Transient scopes
2381 elsif Is_Finalized_Transient
(Obj_Id
) then
2384 -- Finalization of specific objects is also treated separately
2386 elsif Is_Ignored_For_Finalization
(Obj_Id
) then
2389 -- Conversely, if one of the above cases created a Master_Node,
2390 -- finalization actions are required for the associated object.
2392 elsif Ekind
(Obj_Id
) = E_Variable
2393 and then Is_RTE
(Obj_Typ
, RE_Master_Node
)
2395 Processing_Actions
(Decl
);
2397 -- Ignored Ghost objects do not need any cleanup actions
2398 -- because they will not appear in the final tree.
2400 elsif Is_Ignored_Ghost_Entity
(Obj_Id
) then
2403 -- The object is of the form:
2404 -- Obj : [constant] Typ [:= Expr];
2406 -- Do not process the incomplete view of a deferred constant.
2407 -- Note that an object initialized by means of a BIP function
2408 -- call may appear as a deferred constant after expansion
2409 -- activities. These kinds of objects must be finalized.
2411 elsif not Is_Imported
(Obj_Id
)
2412 and then Needs_Finalization
(Obj_Typ
)
2413 and then not (Ekind
(Obj_Id
) = E_Constant
2414 and then not Has_Completion
(Obj_Id
)
2415 and then No
(BIP_Initialization_Call
(Obj_Id
)))
2417 Processing_Actions
(Decl
);
2419 -- The object is of the form:
2420 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
2422 -- Obj : Access_Typ :=
2423 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
2425 elsif Is_Access_Type
(Obj_Typ
)
2426 and then Needs_Finalization
2427 (Available_View
(Designated_Type
(Obj_Typ
)))
2428 and then Present
(Expr
)
2430 (Is_Secondary_Stack_BIP_Func_Call
(Expr
)
2432 (Is_Non_BIP_Func_Call
(Expr
)
2433 and then not Is_Related_To_Func_Return
(Obj_Id
)))
2435 Processing_Actions
(Decl
);
2437 -- Simple protected objects which use the type System.Tasking.
2438 -- Protected_Objects.Protection to manage their locks should
2439 -- be treated as controlled since they require manual cleanup.
2440 -- but not for restricted run-time libraries (Ravenscar), see
2441 -- also Cleanup_Protected_Object.
2443 -- The only exception is illustrated in the following example:
2446 -- type Ctrl is new Controlled ...
2447 -- procedure Finalize (Obj : in out Ctrl);
2451 -- package body Pkg is
2452 -- protected Prot is
2453 -- procedure Do_Something (Obj : in out Ctrl);
2456 -- protected body Prot is
2457 -- procedure Do_Something (Obj : in out Ctrl) is ...
2460 -- procedure Finalize (Obj : in out Ctrl) is
2462 -- Prot.Do_Something (Obj);
2466 -- Since for the most part entities in package bodies depend on
2467 -- those in package specs, Prot's lock should be cleaned up
2468 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
2469 -- This act however attempts to invoke Do_Something and fails
2470 -- because the lock has disappeared.
2472 elsif Ekind
(Obj_Id
) = E_Variable
2473 and then not In_Library_Level_Package_Body
(Obj_Id
)
2474 and then Has_Simple_Protected_Object
(Obj_Typ
)
2475 and then not Restricted_Profile
2477 Processing_Actions
(Decl
, Is_Protected
=> True);
2480 -- Specific cases of object renamings
2482 elsif Nkind
(Decl
) = N_Object_Renaming_Declaration
then
2483 Obj_Id
:= Defining_Identifier
(Decl
);
2484 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
2486 -- Bypass any form of processing for objects which have their
2487 -- finalization disabled. This applies only to objects at the
2490 if For_Package
and then Finalize_Storage_Only
(Obj_Typ
) then
2493 -- Ignored Ghost object renamings do not need any cleanup
2494 -- actions because they will not appear in the final tree.
2496 elsif Is_Ignored_Ghost_Entity
(Obj_Id
) then
2500 -- Inspect the freeze node of an access-to-controlled type and
2501 -- look for a delayed finalization collection. This case arises
2502 -- when the freeze actions are inserted at a later time than the
2503 -- expansion of the context. Since Build_Finalizer is never called
2504 -- on a single construct twice, the collection would be ultimately
2505 -- left out and never finalized. This is also needed for freeze
2506 -- actions of designated types themselves, since in some cases the
2507 -- finalization collection is associated with a designated type's
2508 -- freeze node rather than that of the access type (see handling
2509 -- for freeze actions in Build_Finalization_Collection).
2511 elsif Nkind
(Decl
) = N_Freeze_Entity
2512 and then Present
(Actions
(Decl
))
2514 Typ
:= Entity
(Decl
);
2516 -- Freeze nodes for ignored Ghost types do not need cleanup
2517 -- actions because they will never appear in the final tree.
2519 if Is_Ignored_Ghost_Entity
(Typ
) then
2522 elsif (Is_Access_Object_Type
(Typ
)
2523 and then Needs_Finalization
2524 (Available_View
(Designated_Type
(Typ
))))
2525 or else (Is_Type
(Typ
) and then Needs_Finalization
(Typ
))
2527 -- Freeze nodes are considered to be identical to packages
2528 -- and blocks in terms of nesting. The difference is that
2529 -- a finalization collection created inside the freeze node
2530 -- is at the same nesting level as the node itself.
2532 Process_Declarations
(Actions
(Decl
), Preprocess
);
2535 -- Nested package declarations, avoid generics
2537 elsif Nkind
(Decl
) = N_Package_Declaration
then
2538 Pack_Id
:= Defining_Entity
(Decl
);
2539 Spec
:= Specification
(Decl
);
2541 -- Do not inspect an ignored Ghost package because all code
2542 -- found within will not appear in the final tree.
2544 if Is_Ignored_Ghost_Entity
(Pack_Id
) then
2547 elsif Ekind
(Pack_Id
) /= E_Generic_Package
then
2548 Process_Declarations
2549 (Private_Declarations
(Spec
), Preprocess
);
2550 Process_Declarations
2551 (Visible_Declarations
(Spec
), Preprocess
);
2554 -- Nested package bodies, avoid generics
2556 elsif Nkind
(Decl
) = N_Package_Body
then
2557 Process_Package_Body
(Decl
);
2559 elsif Nkind
(Decl
) = N_Package_Body_Stub
2560 and then Present
(Library_Unit
(Decl
))
2562 Process_Package_Body
(Proper_Body
(Unit
(Library_Unit
(Decl
))));
2565 Prev_Non_Pragma
(Decl
);
2567 end Process_Declarations
;
2569 --------------------------------
2570 -- Process_Object_Declaration --
2571 --------------------------------
2573 procedure Process_Object_Declaration
2575 Is_Protected
: Boolean := False)
2577 Obj_Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2578 Loc
: constant Source_Ptr
:= Sloc
(Decl
);
2582 Master_Node_Attach
: Node_Id
;
2583 Master_Node_Decl
: Node_Id
;
2584 Master_Node_Id
: Entity_Id
;
2585 Master_Node_Ins
: Node_Id
;
2586 Master_Node_Loc
: Source_Ptr
;
2588 Obj_Typ
: Entity_Id
;
2590 -- Start of processing for Process_Object_Declaration
2593 -- Handle the object type and the reference to the object. Note
2594 -- that objects having simple protected components or of a CW type
2595 -- must retain their original type for the processing below to work.
2597 Obj_Ref
:= New_Occurrence_Of
(Obj_Id
, Loc
);
2598 Obj_Typ
:= Etype
(Obj_Id
);
2599 if not Is_Protected
and then not Is_Class_Wide_Type
(Obj_Typ
) then
2600 Obj_Typ
:= Base_Type
(Obj_Typ
);
2603 if Is_Access_Type
(Obj_Typ
) then
2604 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
2605 Obj_Typ
:= Available_View
(Designated_Type
(Obj_Typ
));
2608 -- If the object is a Master_Node, then nothing to do, except if it
2609 -- is the only object, in which case we move its declaration, call
2610 -- marker (if any) and initialization call, as well as mark it to
2611 -- avoid double processing.
2613 if Is_RTE
(Obj_Typ
, RE_Master_Node
) then
2614 Master_Node_Id
:= Obj_Id
;
2616 if Counter_Val
= 1 then
2617 if Nkind
(Next
(Decl
)) = N_Call_Marker
then
2618 Prepend_To
(Decls
, Remove_Next
(Next
(Decl
)));
2620 Prepend_To
(Decls
, Remove_Next
(Decl
));
2622 Prepend_To
(Decls
, Decl
);
2623 Set_Is_Ignored_For_Finalization
(Obj_Id
);
2626 -- Create the declaration of the Master_Node for the object and
2627 -- insert it before the declaration of the object itself, except
2628 -- for the case where it is the only object because it will play
2629 -- the role of a degenerated master and therefore needs to be
2630 -- inserted at the same place the master would have been.
2632 else pragma Assert
(No
(Finalization_Master_Node
(Obj_Id
)));
2633 -- For one object, use the Sloc the master would have had
2635 if Counter_Val
= 1 then
2636 Master_Node_Loc
:= Sloc
(N
);
2638 Master_Node_Loc
:= Loc
;
2642 Make_Defining_Identifier
(Master_Node_Loc
,
2643 Chars
=> New_External_Name
(Chars
(Obj_Id
), Suffix
=> "MN"));
2645 Make_Master_Node_Declaration
(Master_Node_Loc
,
2646 Master_Node_Id
, Obj_Id
);
2648 Push_Scope
(Scope
(Obj_Id
));
2649 if Counter_Val
= 1 then
2650 Prepend_To
(Decls
, Master_Node_Decl
);
2652 Insert_Before
(Decl
, Master_Node_Decl
);
2654 Analyze
(Master_Node_Decl
);
2657 -- Mark the Master_Node to avoid double processing
2659 Set_Is_Ignored_For_Finalization
(Master_Node_Id
);
2662 -- Attach the Master_Node after all initialization has been done. The
2663 -- place of insertion depends on the context.
2665 if Ekind
(Obj_Id
) in E_Constant | E_Variable
then
2667 -- The object is initialized by a build-in-place function call.
2668 -- The Master_Node insertion point is after the function call.
2670 if Present
(BIP_Initialization_Call
(Obj_Id
)) then
2671 Master_Node_Ins
:= BIP_Initialization_Call
(Obj_Id
);
2673 -- The object is initialized by an aggregate. The Master_Node
2674 -- insertion point is after the last aggregate assignment.
2676 elsif Present
(Last_Aggregate_Assignment
(Obj_Id
)) then
2677 Master_Node_Ins
:= Last_Aggregate_Assignment
(Obj_Id
);
2679 -- In other cases the Master_Node is inserted after the last call
2680 -- to either [Deep_]Initialize or the type-specific init proc.
2683 Master_Node_Ins
:= Find_Last_Init
(Decl
);
2686 -- In all other cases the Master_Node is inserted after the last call
2687 -- to either [Deep_]Initialize or the type-specific init proc.
2690 Master_Node_Ins
:= Find_Last_Init
(Decl
);
2693 -- If the Initialize function is null or trivial, the call will have
2694 -- been replaced with a null statement and we place the attachment
2695 -- of the Master_Node after the declaration of the object itself.
2697 if No
(Master_Node_Ins
) then
2698 Master_Node_Ins
:= Decl
;
2701 -- Processing for simple protected objects. Such objects require
2702 -- manual finalization of their lock managers. Generate:
2704 -- procedure obj_type_nnFD (v :system__address) is
2705 -- type Ptr_Typ is access all Obj_Typ;
2706 -- Rnn : Obj_Typ renames Ptr_Typ!(v).all;
2708 -- $system__tasking__protected_objects__finalize_protection
2709 -- (Obj_TypV!(Rnn)._object);
2713 -- end obj_type_nnFD;
2716 or else (Has_Simple_Protected_Object
(Obj_Typ
)
2717 and then No
(Finalize_Address
(Obj_Typ
)))
2720 Param
: constant Entity_Id
:=
2721 Make_Defining_Identifier
(Loc
, Name_V
);
2722 Ptr_Typ
: constant Entity_Id
:= Make_Temporary
(Loc
, 'P');
2723 Ren_Id
: constant Entity_Id
:= Make_Temporary
(Loc
, 'R');
2724 Ren_Ref
: constant Node_Id
:= New_Occurrence_Of
(Ren_Id
, Loc
);
2728 Fin_Stmts
: List_Id
:= No_List
;
2732 Set_Etype
(Ren_Ref
, Obj_Typ
);
2734 if Is_Simple_Protected_Type
(Obj_Typ
) then
2735 Fin_Call
:= Cleanup_Protected_Object
(Decl
, Ren_Ref
);
2737 if Present
(Fin_Call
) then
2738 Fin_Stmts
:= New_List
(Fin_Call
);
2741 elsif Is_Array_Type
(Obj_Typ
) then
2742 Fin_Stmts
:= Cleanup_Array
(Decl
, Ren_Ref
, Obj_Typ
);
2745 Fin_Stmts
:= Cleanup_Record
(Decl
, Ren_Ref
, Obj_Typ
);
2748 if No
(Fin_Stmts
) then
2753 Make_Handled_Sequence_Of_Statements
(Loc
,
2754 Statements
=> Fin_Stmts
);
2756 if Exceptions_OK
then
2757 Set_Exception_Handlers
(HSS
, New_List
(
2758 Make_Exception_Handler
(Loc
,
2759 Exception_Choices
=> New_List
(
2760 Make_Others_Choice
(Loc
)),
2761 Statements
=> New_List
(
2762 Make_Null_Statement
(Loc
)))));
2766 Make_Defining_Identifier
(Loc
,
2767 Make_TSS_Name_Local
(Obj_Typ
, TSS_Finalize_Address
));
2770 Make_Subprogram_Body
(Loc
,
2772 Make_Procedure_Specification
(Loc
,
2773 Defining_Unit_Name
=> Fin_Id
,
2775 Parameter_Specifications
=> New_List
(
2776 Make_Parameter_Specification
(Loc
,
2777 Defining_Identifier
=> Param
,
2779 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)))),
2781 Declarations
=> New_List
(
2782 Make_Full_Type_Declaration
(Loc
,
2783 Defining_Identifier
=> Ptr_Typ
,
2785 Make_Access_To_Object_Definition
(Loc
,
2786 All_Present
=> True,
2787 Subtype_Indication
=>
2788 New_Occurrence_Of
(Obj_Typ
, Loc
))),
2790 Make_Object_Renaming_Declaration
(Loc
,
2791 Defining_Identifier
=> Ren_Id
,
2793 New_Occurrence_Of
(Obj_Typ
, Loc
),
2795 Make_Explicit_Dereference
(Loc
,
2797 Unchecked_Convert_To
2798 (Ptr_Typ
, New_Occurrence_Of
(Param
, Loc
))))),
2800 Handled_Statement_Sequence
=> HSS
);
2802 Push_Scope
(Scope
(Obj_Id
));
2803 Insert_After_And_Analyze
2804 (Master_Node_Ins
, Fin_Body
, Suppress
=> All_Checks
);
2807 Master_Node_Ins
:= Fin_Body
;
2811 Fin_Id
:= Finalize_Address
(Obj_Typ
);
2813 if No
(Fin_Id
) and then Ekind
(Obj_Typ
) = E_Class_Wide_Subtype
then
2814 Fin_Id
:= TSS
(Obj_Typ
, TSS_Finalize_Address
);
2818 -- Now build the attachment call that will initialize the object's
2819 -- Master_Node using the object's address and type's finalization
2820 -- procedure and then attach the Master_Node to the master, unless
2821 -- there is a single controlled object.
2823 if Counter_Val
= 1 then
2824 -- Finalize_Address is not generated in CodePeer mode because the
2825 -- body contains address arithmetic. So we don't want to generate
2826 -- the attach in this case. Ditto if the object is a Master_Node.
2828 if CodePeer_Mode
or else Obj_Id
= Master_Node_Id
then
2829 Master_Node_Attach
:= Make_Null_Statement
(Loc
);
2832 Master_Node_Attach
:=
2833 Make_Procedure_Call_Statement
(Loc
,
2835 New_Occurrence_Of
(RTE
(RE_Attach_Object_To_Node
), Loc
),
2836 Parameter_Associations
=> New_List
(
2837 Make_Address_For_Finalize
(Loc
, Obj_Ref
, Obj_Typ
),
2838 Make_Attribute_Reference
(Loc
,
2839 Prefix
=> New_Occurrence_Of
(Fin_Id
, Loc
),
2840 Attribute_Name
=> Name_Unrestricted_Access
),
2841 New_Occurrence_Of
(Master_Node_Id
, Loc
)));
2844 -- We also generate the direct finalization call here
2847 Make_Procedure_Call_Statement
(Loc
,
2849 New_Occurrence_Of
(RTE
(RE_Finalize_Object
), Loc
),
2850 Parameter_Associations
=> New_List
(
2851 New_Occurrence_Of
(Master_Node_Id
, Loc
)));
2853 -- For CodePeer, the exception handlers normally generated here
2854 -- generate complex flowgraphs which result in capacity problems.
2855 -- Omitting these handlers for CodePeer is justified as follows:
2857 -- If a handler is dead, then omitting it is surely ok
2859 -- If a handler is live, then CodePeer should flag the
2860 -- potentially-exception-raising construct that causes it
2861 -- to be live. That is what we are interested in, not what
2862 -- happens after the exception is raised.
2864 if Exceptions_OK
and not CodePeer_Mode
then
2866 Make_Block_Statement
(Loc
,
2867 Handled_Statement_Sequence
=>
2868 Make_Handled_Sequence_Of_Statements
(Loc
,
2869 Statements
=> New_List
(Fin_Call
),
2871 Exception_Handlers
=> New_List
(
2872 Build_Exception_Handler
2873 (Finalizer_Data
, For_Package
))));
2876 Append_To
(Finalizer_Stmts
, Fin_Call
);
2879 -- If the object is a Master_Node, we just need to chain it
2881 if Obj_Id
= Master_Node_Id
then
2882 Master_Node_Attach
:=
2883 Make_Procedure_Call_Statement
(Loc
,
2885 New_Occurrence_Of
(RTE
(RE_Chain_Node_To_Master
), Loc
),
2886 Parameter_Associations
=> New_List
(
2887 Make_Attribute_Reference
(Loc
,
2888 Prefix
=> New_Occurrence_Of
(Obj_Id
, Loc
),
2889 Attribute_Name
=> Name_Unrestricted_Access
),
2890 New_Occurrence_Of
(Finalization_Master
, Loc
)));
2892 -- Finalize_Address is not generated in CodePeer mode because the
2893 -- body contains address arithmetic. So we don't want to generate
2894 -- the attach in this case.
2896 elsif CodePeer_Mode
then
2897 Master_Node_Attach
:= Make_Null_Statement
(Loc
);
2900 Master_Node_Attach
:=
2901 Make_Procedure_Call_Statement
(Loc
,
2903 New_Occurrence_Of
(RTE
(RE_Attach_Object_To_Master
), Loc
),
2904 Parameter_Associations
=> New_List
(
2905 Make_Address_For_Finalize
(Loc
, Obj_Ref
, Obj_Typ
),
2906 Make_Attribute_Reference
(Loc
,
2907 Prefix
=> New_Occurrence_Of
(Fin_Id
, Loc
),
2908 Attribute_Name
=> Name_Unrestricted_Access
),
2909 Make_Attribute_Reference
(Loc
,
2911 New_Occurrence_Of
(Master_Node_Id
, Loc
),
2912 Attribute_Name
=> Name_Unrestricted_Access
),
2913 New_Occurrence_Of
(Finalization_Master
, Loc
)));
2917 Insert_After_And_Analyze
2918 (Master_Node_Ins
, Master_Node_Attach
, Suppress
=> All_Checks
);
2919 end Process_Object_Declaration
;
2921 -------------------------------------
2922 -- Process_Tagged_Type_Declaration --
2923 -------------------------------------
2925 procedure Process_Tagged_Type_Declaration
(Decl
: Node_Id
) is
2926 Typ
: constant Entity_Id
:= Defining_Identifier
(Decl
);
2927 DT_Ptr
: constant Entity_Id
:=
2928 Node
(First_Elmt
(Access_Disp_Table
(Typ
)));
2931 -- Ada.Tags.Unregister_Tag (<Typ>P);
2933 Append_To
(Tagged_Type_Stmts
,
2934 Make_Procedure_Call_Statement
(Loc
,
2936 New_Occurrence_Of
(RTE
(RE_Unregister_Tag
), Loc
),
2937 Parameter_Associations
=> New_List
(
2938 New_Occurrence_Of
(DT_Ptr
, Loc
))));
2939 end Process_Tagged_Type_Declaration
;
2941 -- Start of processing for Build_Finalizer
2946 -- Do not perform this expansion in SPARK mode because it is not
2949 if GNATprove_Mode
then
2953 -- Step 1: Extract all lists which may contain controlled objects or
2954 -- library-level tagged types.
2956 if For_Package_Spec
then
2957 Decls
:= Visible_Declarations
(Specification
(N
));
2958 Priv_Decls
:= Private_Declarations
(Specification
(N
));
2960 -- Retrieve the package spec id
2962 Spec_Id
:= Defining_Unit_Name
(Specification
(N
));
2964 if Nkind
(Spec_Id
) = N_Defining_Program_Unit_Name
then
2965 Spec_Id
:= Defining_Identifier
(Spec_Id
);
2968 -- Accept statement, block, entry body, package body, protected body,
2969 -- subprogram body or task body.
2972 Decls
:= Declarations
(N
);
2973 HSS
:= Handled_Statement_Sequence
(N
);
2975 if Present
(HSS
) then
2976 if Present
(Statements
(HSS
)) then
2977 Stmts
:= Statements
(HSS
);
2980 if Present
(At_End_Proc
(HSS
)) then
2981 Prev_At_End
:= At_End_Proc
(HSS
);
2985 -- Retrieve the package spec id for package bodies
2987 if For_Package_Body
then
2988 Spec_Id
:= Corresponding_Spec
(N
);
2992 -- We do not need to process nested packages since they are handled by
2993 -- the finalizer of the enclosing scope, including at library level.
2994 -- And we do not build two finalizers for an instance without body that
2995 -- is a library unit (see Analyze_Package_Instantiation).
2998 and then (not Is_Compilation_Unit
(Spec_Id
)
2999 or else (Is_Generic_Instance
(Spec_Id
)
3000 and then Package_Instantiation
(Spec_Id
) = N
))
3005 -- Step 2: Object [pre]processing
3008 -- For package specs and bodies, we are invoked from the Standard
3009 -- scope, so we need to push the specs onto the scope stack first.
3011 Push_Scope
(Spec_Id
);
3013 -- Preprocess the visible declarations now in order to obtain the
3014 -- correct number of controlled object by the time the private
3015 -- declarations are processed.
3017 Process_Declarations
(Decls
, Preprocess
=> True);
3019 -- From all the possible contexts, only package specifications may
3020 -- have private declarations.
3022 if For_Package_Spec
then
3023 Process_Declarations
(Priv_Decls
, Preprocess
=> True);
3026 -- The current context may lack controlled objects, but require some
3027 -- other form of completion (task termination for instance). In such
3028 -- cases, the finalizer must be created and carry the additional
3031 if Acts_As_Clean
or else Has_Ctrl_Objs
or else Has_Tagged_Types
then
3035 -- The preprocessing has determined that the context has controlled
3036 -- objects or library-level tagged types.
3038 if Has_Ctrl_Objs
or else Has_Tagged_Types
then
3040 -- Private declarations are processed first in order to preserve
3041 -- possible dependencies between public and private objects.
3043 if For_Package_Spec
then
3044 Process_Declarations
(Priv_Decls
);
3047 Process_Declarations
(Decls
);
3053 -- Preprocess both declarations and statements
3055 Process_Declarations
(Decls
, Preprocess
=> True);
3056 Process_Declarations
(Stmts
, Preprocess
=> True);
3058 -- At this point it is known that N has controlled objects. Ensure
3059 -- that N has a declarative list since the finalizer spec will be
3062 if Has_Ctrl_Objs
and then No
(Decls
) then
3063 Set_Declarations
(N
, New_List
);
3064 Decls
:= Declarations
(N
);
3065 Spec_Decls
:= Decls
;
3068 -- The current context may lack controlled objects, but require some
3069 -- other form of completion (task termination for instance). In such
3070 -- cases, the finalizer must be created and carry the additional
3073 if Acts_As_Clean
or else Has_Ctrl_Objs
or else Has_Tagged_Types
then
3077 if Has_Ctrl_Objs
or else Has_Tagged_Types
then
3078 Process_Declarations
(Stmts
);
3079 Process_Declarations
(Decls
);
3083 -- Step 3: Finalizer creation
3085 if Acts_As_Clean
or else Has_Ctrl_Objs
or else Has_Tagged_Types
then
3089 -- Pop the scope that was pushed above for package specs and bodies
3094 end Build_Finalizer
;
3096 --------------------------
3097 -- Build_Finalizer_Call --
3098 --------------------------
3100 procedure Build_Finalizer_Call
(N
: Node_Id
; Fin_Id
: Entity_Id
) is
3102 -- Do not perform this expansion in SPARK mode because we do not create
3103 -- finalizers in the first place.
3105 if GNATprove_Mode
then
3109 -- If the construct to be cleaned up is a protected subprogram body, the
3110 -- finalizer call needs to be associated with the block that wraps the
3111 -- unprotected version of the subprogram. The following illustrates this
3114 -- procedure Prot_SubpP is
3115 -- procedure finalizer is
3117 -- Service_Entries (Prot_Obj);
3124 -- Prot_SubpN (Prot_Obj);
3131 Loc
: constant Source_Ptr
:= Sloc
(N
);
3133 Is_Protected_Subp_Body
: constant Boolean :=
3134 Nkind
(N
) = N_Subprogram_Body
3135 and then Is_Protected_Subprogram_Body
(N
);
3136 -- True if N is the protected version of a subprogram that belongs to
3137 -- a protected type.
3139 HSS
: constant Node_Id
:=
3140 (if Is_Protected_Subp_Body
3141 then Handled_Statement_Sequence
3142 (Last
(Statements
(Handled_Statement_Sequence
(N
))))
3143 else Handled_Statement_Sequence
(N
));
3145 -- We attach the At_End_Proc to the HSS if this is an accept
3146 -- statement or extended return statement. Also in the case of
3147 -- a protected subprogram, because if Service_Entries raises an
3148 -- exception, we do not lock the PO, so we also do not want to
3151 Use_HSS
: constant Boolean :=
3152 Nkind
(N
) in N_Accept_Statement | N_Extended_Return_Statement
3153 or else Is_Protected_Subp_Body
;
3155 At_End_Proc_Bearer
: constant Node_Id
:= (if Use_HSS
then HSS
else N
);
3157 pragma Assert
(No
(At_End_Proc
(At_End_Proc_Bearer
)));
3158 Set_At_End_Proc
(At_End_Proc_Bearer
, New_Occurrence_Of
(Fin_Id
, Loc
));
3159 -- Attach reference to finalizer to tree, for LLVM use
3160 Set_Parent
(At_End_Proc
(At_End_Proc_Bearer
), At_End_Proc_Bearer
);
3161 Analyze
(At_End_Proc
(At_End_Proc_Bearer
));
3162 Expand_At_End_Handler
(At_End_Proc_Bearer
, Empty
);
3164 end Build_Finalizer_Call
;
3166 ---------------------
3167 -- Build_Late_Proc --
3168 ---------------------
3170 procedure Build_Late_Proc
(Typ
: Entity_Id
; Nam
: Name_Id
) is
3172 for Final_Prim
in Name_Of
'Range loop
3173 if Name_Of
(Final_Prim
) = Nam
then
3176 (Prim
=> Final_Prim
,
3178 Stmts
=> Make_Deep_Record_Body
(Final_Prim
, Typ
)));
3181 end Build_Late_Proc
;
3183 -------------------------------
3184 -- Build_Object_Declarations --
3185 -------------------------------
3187 procedure Build_Object_Declarations
3188 (Data
: out Finalization_Exception_Data
;
3191 For_Package
: Boolean := False)
3196 -- This variable captures an unused dummy internal entity, see the
3197 -- comment associated with its use.
3200 pragma Assert
(Decls
/= No_List
);
3202 -- Always set the proper location as it may be needed even when
3203 -- exception propagation is forbidden.
3207 if Restriction_Active
(No_Exception_Propagation
) then
3208 Data
.Abort_Id
:= Empty
;
3210 Data
.Raised_Id
:= Empty
;
3214 Data
.Raised_Id
:= Make_Temporary
(Loc
, 'R');
3216 -- In certain scenarios, finalization can be triggered by an abort. If
3217 -- the finalization itself fails and raises an exception, the resulting
3218 -- Program_Error must be supressed and replaced by an abort signal. In
3219 -- order to detect this scenario, save the state of entry into the
3220 -- finalization code.
3222 -- This is not needed for library-level finalizers as they are called by
3223 -- the environment task and cannot be aborted.
3225 if not For_Package
then
3226 if Abort_Allowed
then
3227 Data
.Abort_Id
:= Make_Temporary
(Loc
, 'A');
3230 -- Abort_Id : constant Boolean := <A_Expr>;
3233 Make_Object_Declaration
(Loc
,
3234 Defining_Identifier
=> Data
.Abort_Id
,
3235 Constant_Present
=> True,
3236 Object_Definition
=>
3237 New_Occurrence_Of
(Standard_Boolean
, Loc
),
3239 New_Occurrence_Of
(RTE
(RE_Triggered_By_Abort
), Loc
)));
3241 -- Abort is not required
3244 -- Generate a dummy entity to ensure that the internal symbols are
3245 -- in sync when a unit is compiled with and without aborts.
3247 Dummy
:= Make_Temporary
(Loc
, 'A');
3248 Data
.Abort_Id
:= Empty
;
3251 -- Library-level finalizers
3254 Data
.Abort_Id
:= Empty
;
3257 if Exception_Extra_Info
then
3258 Data
.E_Id
:= Make_Temporary
(Loc
, 'E');
3261 -- E_Id : Exception_Occurrence;
3264 Make_Object_Declaration
(Loc
,
3265 Defining_Identifier
=> Data
.E_Id
,
3266 Object_Definition
=>
3267 New_Occurrence_Of
(RTE
(RE_Exception_Occurrence
), Loc
));
3268 Set_No_Initialization
(Decl
);
3270 Append_To
(Decls
, Decl
);
3277 -- Raised_Id : Boolean := False;
3280 Make_Object_Declaration
(Loc
,
3281 Defining_Identifier
=> Data
.Raised_Id
,
3282 Object_Definition
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
3283 Expression
=> New_Occurrence_Of
(Standard_False
, Loc
)));
3285 if Debug_Generated_Code
then
3286 Set_Debug_Info_Needed
(Data
.Raised_Id
);
3288 end Build_Object_Declarations
;
3290 ---------------------------
3291 -- Build_Raise_Statement --
3292 ---------------------------
3294 function Build_Raise_Statement
3295 (Data
: Finalization_Exception_Data
) return Node_Id
3301 -- Standard run-time use the specialized routine
3302 -- Raise_From_Controlled_Operation.
3304 if Exception_Extra_Info
3305 and then RTE_Available
(RE_Raise_From_Controlled_Operation
)
3308 Make_Procedure_Call_Statement
(Data
.Loc
,
3311 (RTE
(RE_Raise_From_Controlled_Operation
), Data
.Loc
),
3312 Parameter_Associations
=>
3313 New_List
(New_Occurrence_Of
(Data
.E_Id
, Data
.Loc
)));
3315 -- Restricted run-time: exception messages are not supported and hence
3316 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3321 Make_Raise_Program_Error
(Data
.Loc
,
3322 Reason
=> PE_Finalize_Raised_Exception
);
3327 -- Raised_Id and then not Abort_Id
3331 Expr
:= New_Occurrence_Of
(Data
.Raised_Id
, Data
.Loc
);
3333 if Present
(Data
.Abort_Id
) then
3334 Expr
:= Make_And_Then
(Data
.Loc
,
3337 Make_Op_Not
(Data
.Loc
,
3338 Right_Opnd
=> New_Occurrence_Of
(Data
.Abort_Id
, Data
.Loc
)));
3343 -- if Raised_Id and then not Abort_Id then
3344 -- Raise_From_Controlled_Operation (E_Id);
3346 -- raise Program_Error; -- restricted runtime
3350 Make_If_Statement
(Data
.Loc
,
3352 Then_Statements
=> New_List
(Stmt
));
3353 end Build_Raise_Statement
;
3355 -----------------------------
3356 -- Build_Record_Deep_Procs --
3357 -----------------------------
3359 procedure Build_Record_Deep_Procs
(Typ
: Entity_Id
) is
3363 (Prim
=> Initialize_Case
,
3365 Stmts
=> Make_Deep_Record_Body
(Initialize_Case
, Typ
)));
3367 if not Is_Inherently_Limited_Type
(Typ
) then
3370 (Prim
=> Adjust_Case
,
3372 Stmts
=> Make_Deep_Record_Body
(Adjust_Case
, Typ
)));
3375 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3376 -- suppressed since these routine will not be used.
3378 if not Restriction_Active
(No_Finalization
) then
3381 (Prim
=> Finalize_Case
,
3383 Stmts
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
)));
3385 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
3387 if not CodePeer_Mode
then
3390 (Prim
=> Address_Case
,
3392 Stmts
=> Make_Deep_Record_Body
(Address_Case
, Typ
)));
3395 end Build_Record_Deep_Procs
;
3401 function Cleanup_Array
3404 Typ
: Entity_Id
) return List_Id
3406 Loc
: constant Source_Ptr
:= Sloc
(N
);
3407 Index_List
: constant List_Id
:= New_List
;
3409 function Free_Component
return List_Id
;
3410 -- Generate the code to finalize the task or protected subcomponents
3411 -- of a single component of the array.
3413 function Free_One_Dimension
(Dim
: Int
) return List_Id
;
3414 -- Generate a loop over one dimension of the array
3416 --------------------
3417 -- Free_Component --
3418 --------------------
3420 function Free_Component
return List_Id
is
3421 Stmts
: List_Id
:= New_List
;
3423 C_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
3426 -- Component type is known to contain tasks or protected objects
3429 Make_Indexed_Component
(Loc
,
3430 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3431 Expressions
=> Index_List
);
3433 Set_Etype
(Tsk
, C_Typ
);
3435 if Is_Task_Type
(C_Typ
) then
3436 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3438 elsif Is_Simple_Protected_Type
(C_Typ
) then
3439 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3441 elsif Is_Record_Type
(C_Typ
) then
3442 Stmts
:= Cleanup_Record
(N
, Tsk
, C_Typ
);
3444 elsif Is_Array_Type
(C_Typ
) then
3445 Stmts
:= Cleanup_Array
(N
, Tsk
, C_Typ
);
3451 ------------------------
3452 -- Free_One_Dimension --
3453 ------------------------
3455 function Free_One_Dimension
(Dim
: Int
) return List_Id
is
3459 if Dim
> Number_Dimensions
(Typ
) then
3460 return Free_Component
;
3462 -- Here we generate the required loop
3465 Index
:= Make_Temporary
(Loc
, 'J');
3466 Append
(New_Occurrence_Of
(Index
, Loc
), Index_List
);
3469 Make_Implicit_Loop_Statement
(N
,
3470 Identifier
=> Empty
,
3472 Make_Iteration_Scheme
(Loc
,
3473 Loop_Parameter_Specification
=>
3474 Make_Loop_Parameter_Specification
(Loc
,
3475 Defining_Identifier
=> Index
,
3476 Discrete_Subtype_Definition
=>
3477 Make_Attribute_Reference
(Loc
,
3478 Prefix
=> Duplicate_Subexpr
(Obj
),
3479 Attribute_Name
=> Name_Range
,
3480 Expressions
=> New_List
(
3481 Make_Integer_Literal
(Loc
, Dim
))))),
3482 Statements
=> Free_One_Dimension
(Dim
+ 1)));
3484 end Free_One_Dimension
;
3486 -- Start of processing for Cleanup_Array
3489 return Free_One_Dimension
(1);
3492 --------------------
3493 -- Cleanup_Record --
3494 --------------------
3496 function Cleanup_Record
3499 Typ
: Entity_Id
) return List_Id
3501 Loc
: constant Source_Ptr
:= Sloc
(N
);
3502 Stmts
: constant List_Id
:= New_List
;
3503 U_Typ
: constant Entity_Id
:= Underlying_Type
(Typ
);
3509 if Has_Discriminants
(U_Typ
)
3510 and then Nkind
(Parent
(U_Typ
)) = N_Full_Type_Declaration
3511 and then Nkind
(Type_Definition
(Parent
(U_Typ
))) = N_Record_Definition
3514 (Variant_Part
(Component_List
(Type_Definition
(Parent
(U_Typ
)))))
3516 -- For now, do not attempt to free a component that may appear in a
3517 -- variant, and instead issue a warning. Doing this "properly" would
3518 -- require building a case statement and would be quite a mess. Note
3519 -- that the RM only requires that free "work" for the case of a task
3520 -- access value, so already we go way beyond this in that we deal
3521 -- with the array case and non-discriminated record cases.
3524 ("task/protected object in variant record will not be freed??", N
);
3525 return New_List
(Make_Null_Statement
(Loc
));
3528 Comp
:= First_Component
(U_Typ
);
3529 while Present
(Comp
) loop
3530 if Chars
(Comp
) /= Name_uParent
3531 and then (Has_Task
(Etype
(Comp
))
3532 or else Has_Simple_Protected_Object
(Etype
(Comp
)))
3535 Make_Selected_Component
(Loc
,
3536 Prefix
=> Duplicate_Subexpr_No_Checks
(Obj
),
3537 Selector_Name
=> New_Occurrence_Of
(Comp
, Loc
));
3538 Set_Etype
(Tsk
, Etype
(Comp
));
3540 if Is_Task_Type
(Etype
(Comp
)) then
3541 Append_To
(Stmts
, Cleanup_Task
(N
, Tsk
));
3543 elsif Is_Simple_Protected_Type
(Etype
(Comp
)) then
3544 Append_To
(Stmts
, Cleanup_Protected_Object
(N
, Tsk
));
3546 elsif Is_Record_Type
(Etype
(Comp
)) then
3548 -- Recurse, by generating the prefix of the argument to the
3549 -- eventual cleanup call.
3551 Append_List_To
(Stmts
, Cleanup_Record
(N
, Tsk
, Etype
(Comp
)));
3553 elsif Is_Array_Type
(Etype
(Comp
)) then
3554 Append_List_To
(Stmts
, Cleanup_Array
(N
, Tsk
, Etype
(Comp
)));
3558 Next_Component
(Comp
);
3564 ------------------------------
3565 -- Cleanup_Protected_Object --
3566 ------------------------------
3568 function Cleanup_Protected_Object
3570 Ref
: Node_Id
) return Node_Id
3572 Loc
: constant Source_Ptr
:= Sloc
(N
);
3575 -- For restricted run-time libraries (Ravenscar), tasks are
3576 -- non-terminating, and protected objects can only appear at library
3577 -- level, so we do not want finalization of protected objects.
3579 if Restricted_Profile
then
3584 Make_Procedure_Call_Statement
(Loc
,
3586 New_Occurrence_Of
(RTE
(RE_Finalize_Protection
), Loc
),
3587 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3589 end Cleanup_Protected_Object
;
3595 function Cleanup_Task
3597 Ref
: Node_Id
) return Node_Id
3599 Loc
: constant Source_Ptr
:= Sloc
(N
);
3602 -- For restricted run-time libraries (Ravenscar), tasks are
3603 -- non-terminating and they can only appear at library level,
3604 -- so we do not want finalization of task objects.
3606 if Restricted_Profile
then
3611 Make_Procedure_Call_Statement
(Loc
,
3613 New_Occurrence_Of
(RTE
(RE_Free_Task
), Loc
),
3614 Parameter_Associations
=> New_List
(Concurrent_Ref
(Ref
)));
3618 --------------------------------------
3619 -- Check_Unnesting_Elaboration_Code --
3620 --------------------------------------
3622 procedure Check_Unnesting_Elaboration_Code
(N
: Node_Id
) is
3623 Loc
: constant Source_Ptr
:= Sloc
(N
);
3624 Block_Elab_Proc
: Entity_Id
:= Empty
;
3626 procedure Set_Block_Elab_Proc
;
3627 -- Create a defining identifier for a procedure that will replace
3628 -- a block with nested subprograms (unless it has already been created,
3629 -- in which case this is a no-op).
3631 procedure Set_Block_Elab_Proc
is
3633 if No
(Block_Elab_Proc
) then
3634 Block_Elab_Proc
:= Make_Temporary
(Loc
, 'I');
3636 end Set_Block_Elab_Proc
;
3638 procedure Reset_Scopes_To_Block_Elab_Proc
(L
: List_Id
);
3639 -- Find entities in the elaboration code of a library package body that
3640 -- contain or represent a subprogram body. A body can appear within a
3641 -- block or a loop or can appear by itself if generated for an object
3642 -- declaration that involves controlled actions. The first such entity
3643 -- forces creation of a new procedure entity (via Set_Block_Elab_Proc)
3644 -- that will be used to reset the scopes of all entities that become
3645 -- local to the new elaboration procedure. This is needed for subsequent
3646 -- unnesting actions, which depend on proper setting of the Scope links
3647 -- to determine the nesting level of each subprogram.
3649 --------------------------------------
3650 -- Reset_Scopes_To_Block_Elab_Proc --
3651 --------------------------------------
3652 Maybe_Reset_Scopes_For_Decl
: constant Elist_Id
:= New_Elmt_List
;
3654 procedure Reset_Scopes_To_Block_Elab_Proc
(L
: List_Id
) is
3661 while Present
(Stat
) loop
3662 case Nkind
(Stat
) is
3663 when N_Block_Statement
=>
3664 if Present
(Identifier
(Stat
)) then
3665 Id
:= Entity
(Identifier
(Stat
));
3667 -- The Scope of this block needs to be reset to the new
3668 -- procedure if the block contains nested subprograms.
3670 if Present
(Id
) and then Contains_Subprogram
(Id
) then
3671 Set_Block_Elab_Proc
;
3672 Set_Scope
(Id
, Block_Elab_Proc
);
3676 when N_Loop_Statement
=>
3677 Id
:= Entity
(Identifier
(Stat
));
3679 if Present
(Id
) and then Contains_Subprogram
(Id
) then
3680 if Scope
(Id
) = Current_Scope
then
3681 Set_Block_Elab_Proc
;
3682 Set_Scope
(Id
, Block_Elab_Proc
);
3686 -- We traverse the loop's statements as well, which may
3687 -- include other block (etc.) statements that need to have
3688 -- their Scope set to Block_Elab_Proc. (Is this really the
3689 -- case, or do such nested blocks refer to the loop scope
3690 -- rather than the loop's enclosing scope???.)
3692 Reset_Scopes_To_Block_Elab_Proc
(Statements
(Stat
));
3694 when N_If_Statement
=>
3695 Reset_Scopes_To_Block_Elab_Proc
(Then_Statements
(Stat
));
3696 Reset_Scopes_To_Block_Elab_Proc
(Else_Statements
(Stat
));
3698 Node
:= First
(Elsif_Parts
(Stat
));
3699 while Present
(Node
) loop
3700 Reset_Scopes_To_Block_Elab_Proc
(Then_Statements
(Node
));
3704 when N_Case_Statement
=>
3705 Node
:= First
(Alternatives
(Stat
));
3706 while Present
(Node
) loop
3707 Reset_Scopes_To_Block_Elab_Proc
(Statements
(Node
));
3711 -- Reset the Scope of a subprogram and object declaration
3712 -- occurring at the top level
3714 when N_Subprogram_Body
=>
3715 Id
:= Defining_Entity
(Stat
);
3717 Set_Block_Elab_Proc
;
3718 Set_Scope
(Id
, Block_Elab_Proc
);
3720 when N_Object_Declaration
3721 | N_Object_Renaming_Declaration
=>
3722 Id
:= Defining_Entity
(Stat
);
3723 if No
(Block_Elab_Proc
) then
3724 Append_Elmt
(Id
, Maybe_Reset_Scopes_For_Decl
);
3726 Set_Scope
(Id
, Block_Elab_Proc
);
3736 -- If we are creating an Elab procedure, move all the gathered
3737 -- declarations in its scope.
3739 if Present
(Block_Elab_Proc
) then
3740 while not Is_Empty_Elmt_List
(Maybe_Reset_Scopes_For_Decl
) loop
3743 (Last_Elmt
(Maybe_Reset_Scopes_For_Decl
)), Block_Elab_Proc
);
3744 Remove_Last_Elmt
(Maybe_Reset_Scopes_For_Decl
);
3747 end Reset_Scopes_To_Block_Elab_Proc
;
3751 H_Seq
: constant Node_Id
:= Handled_Statement_Sequence
(N
);
3752 Elab_Body
: Node_Id
;
3753 Elab_Call
: Node_Id
;
3755 -- Start of processing for Check_Unnesting_Elaboration_Code
3758 if Present
(H_Seq
) then
3759 Reset_Scopes_To_Block_Elab_Proc
(Statements
(H_Seq
));
3761 -- There may be subprograms declared in the exception handlers
3762 -- of the current body.
3764 if Present
(Exception_Handlers
(H_Seq
)) then
3766 Handler
: Node_Id
:= First
(Exception_Handlers
(H_Seq
));
3768 while Present
(Handler
) loop
3769 Reset_Scopes_To_Block_Elab_Proc
(Statements
(Handler
));
3776 if Present
(Block_Elab_Proc
) then
3778 Make_Subprogram_Body
(Loc
,
3780 Make_Procedure_Specification
(Loc
,
3781 Defining_Unit_Name
=> Block_Elab_Proc
),
3782 Declarations
=> New_List
,
3783 Handled_Statement_Sequence
=>
3784 Relocate_Node
(Handled_Statement_Sequence
(N
)));
3787 Make_Procedure_Call_Statement
(Loc
,
3788 Name
=> New_Occurrence_Of
(Block_Elab_Proc
, Loc
));
3790 Append_To
(Declarations
(N
), Elab_Body
);
3791 Analyze
(Elab_Body
);
3792 Set_Has_Nested_Subprogram
(Block_Elab_Proc
);
3794 Set_Handled_Statement_Sequence
(N
,
3795 Make_Handled_Sequence_Of_Statements
(Loc
,
3796 Statements
=> New_List
(Elab_Call
)));
3798 Analyze
(Elab_Call
);
3800 -- Could we reset the scopes of entities associated with the new
3801 -- procedure here via a loop over entities rather than doing it in
3802 -- the recursive Reset_Scopes_To_Elab_Proc procedure???
3805 end Check_Unnesting_Elaboration_Code
;
3807 ---------------------------------------
3808 -- Check_Unnesting_In_Decls_Or_Stmts --
3809 ---------------------------------------
3811 procedure Check_Unnesting_In_Decls_Or_Stmts
(Decls_Or_Stmts
: List_Id
) is
3812 Decl_Or_Stmt
: Node_Id
;
3815 if Unnest_Subprogram_Mode
3816 and then Present
(Decls_Or_Stmts
)
3818 Decl_Or_Stmt
:= First
(Decls_Or_Stmts
);
3819 while Present
(Decl_Or_Stmt
) loop
3820 if Nkind
(Decl_Or_Stmt
) = N_Block_Statement
3821 and then Contains_Subprogram
(Entity
(Identifier
(Decl_Or_Stmt
)))
3823 Unnest_Block
(Decl_Or_Stmt
);
3825 -- If-statements may contain subprogram bodies at the outer level
3826 -- of their statement lists, and the subprograms may make up-level
3827 -- references (such as to objects declared in the same statement
3828 -- list). Unlike block and loop cases, however, we don't have an
3829 -- entity on which to test the Contains_Subprogram flag, so
3830 -- Unnest_If_Statement must traverse the statement lists to
3831 -- determine whether there are nested subprograms present.
3833 elsif Nkind
(Decl_Or_Stmt
) = N_If_Statement
then
3834 Unnest_If_Statement
(Decl_Or_Stmt
);
3836 elsif Nkind
(Decl_Or_Stmt
) = N_Loop_Statement
then
3838 Id
: constant Entity_Id
:=
3839 Entity
(Identifier
(Decl_Or_Stmt
));
3842 -- When a top-level loop within declarations of a library
3843 -- package spec or body contains nested subprograms, we wrap
3844 -- it in a procedure to handle possible up-level references
3845 -- to entities associated with the loop (such as loop
3848 if Present
(Id
) and then Contains_Subprogram
(Id
) then
3849 Unnest_Loop
(Decl_Or_Stmt
);
3853 elsif Nkind
(Decl_Or_Stmt
) = N_Package_Declaration
3854 and then not Modify_Tree_For_C
3856 Check_Unnesting_In_Decls_Or_Stmts
3857 (Visible_Declarations
(Specification
(Decl_Or_Stmt
)));
3858 Check_Unnesting_In_Decls_Or_Stmts
3859 (Private_Declarations
(Specification
(Decl_Or_Stmt
)));
3861 elsif Nkind
(Decl_Or_Stmt
) = N_Package_Body
3862 and then not Modify_Tree_For_C
3864 Check_Unnesting_In_Decls_Or_Stmts
(Declarations
(Decl_Or_Stmt
));
3865 if Present
(Statements
3866 (Handled_Statement_Sequence
(Decl_Or_Stmt
)))
3868 Check_Unnesting_In_Decls_Or_Stmts
(Statements
3869 (Handled_Statement_Sequence
(Decl_Or_Stmt
)));
3870 Check_Unnesting_In_Handlers
(Decl_Or_Stmt
);
3874 Next
(Decl_Or_Stmt
);
3877 end Check_Unnesting_In_Decls_Or_Stmts
;
3879 ---------------------------------
3880 -- Check_Unnesting_In_Handlers --
3881 ---------------------------------
3883 procedure Check_Unnesting_In_Handlers
(N
: Node_Id
) is
3884 Stmt_Seq
: constant Node_Id
:= Handled_Statement_Sequence
(N
);
3887 if Present
(Stmt_Seq
)
3888 and then Present
(Exception_Handlers
(Stmt_Seq
))
3891 Handler
: Node_Id
:= First
(Exception_Handlers
(Stmt_Seq
));
3893 while Present
(Handler
) loop
3894 if Present
(Statements
(Handler
)) then
3895 Check_Unnesting_In_Decls_Or_Stmts
(Statements
(Handler
));
3902 end Check_Unnesting_In_Handlers
;
3904 ------------------------------
3905 -- Check_Visibly_Controlled --
3906 ------------------------------
3908 procedure Check_Visibly_Controlled
3909 (Prim
: Final_Primitives
;
3911 E
: in out Entity_Id
;
3912 Cref
: in out Node_Id
)
3914 Parent_Type
: Entity_Id
;
3918 if Is_Derived_Type
(Typ
)
3919 and then Comes_From_Source
(E
)
3920 and then No
(Overridden_Operation
(E
))
3922 -- We know that the explicit operation on the type does not override
3923 -- the inherited operation of the parent, and that the derivation
3924 -- is from a private type that is not visibly controlled.
3926 Parent_Type
:= Etype
(Typ
);
3927 Op
:= Find_Optional_Prim_Op
(Parent_Type
, Name_Of
(Prim
));
3929 if Present
(Op
) then
3932 -- Wrap the object to be initialized into the proper
3933 -- unchecked conversion, to be compatible with the operation
3936 if Nkind
(Cref
) = N_Unchecked_Type_Conversion
then
3937 Cref
:= Unchecked_Convert_To
(Parent_Type
, Expression
(Cref
));
3939 Cref
:= Unchecked_Convert_To
(Parent_Type
, Cref
);
3943 end Check_Visibly_Controlled
;
3945 --------------------------
3946 -- Contains_Subprogram --
3947 --------------------------
3949 function Contains_Subprogram
(Blk
: Entity_Id
) return Boolean is
3953 E
:= First_Entity
(Blk
);
3955 -- The compiler may generate loops with a declare block containing
3956 -- nested procedures used for finalization. Recursively search for
3957 -- subprograms in such constructs.
3959 if Ekind
(Blk
) = E_Loop
3960 and then Parent_Kind
(Blk
) = N_Loop_Statement
3963 Stmt
: Node_Id
:= First
(Statements
(Parent
(Blk
)));
3965 while Present
(Stmt
) loop
3966 if Nkind
(Stmt
) = N_Block_Statement
then
3968 Id
: constant Entity_Id
:=
3969 Entity
(Identifier
(Stmt
));
3971 if Contains_Subprogram
(Id
) then
3981 while Present
(E
) loop
3982 if Is_Subprogram
(E
) then
3985 elsif Ekind
(E
) in E_Block | E_Loop
3986 and then Contains_Subprogram
(E
)
3995 end Contains_Subprogram
;
4001 function Convert_View
(Proc
: Entity_Id
; Arg
: Node_Id
) return Node_Id
is
4002 Ftyp
: constant Entity_Id
:= Etype
(First_Formal
(Proc
));
4007 if Nkind
(Arg
) in N_Type_Conversion | N_Unchecked_Type_Conversion
then
4008 Atyp
:= Entity
(Subtype_Mark
(Arg
));
4010 Atyp
:= Etype
(Arg
);
4013 if Is_Abstract_Subprogram
(Proc
) and then Is_Tagged_Type
(Ftyp
) then
4014 return Unchecked_Convert_To
(Class_Wide_Type
(Ftyp
), Arg
);
4016 elsif Present
(Atyp
)
4017 and then Atyp
/= Ftyp
4018 and then (Is_Private_Type
(Ftyp
)
4019 or else Is_Private_Type
(Atyp
)
4020 or else Is_Private_Type
(Base_Type
(Atyp
)))
4021 and then Implementation_Base_Type
(Atyp
) =
4022 Implementation_Base_Type
(Ftyp
)
4024 return Unchecked_Convert_To
(Ftyp
, Arg
);
4026 -- If the argument is already a conversion, as generated by
4027 -- Make_Init_Call, set the target type to the type of the formal
4028 -- directly, to avoid spurious typing problems.
4030 elsif Nkind
(Arg
) in N_Unchecked_Type_Conversion | N_Type_Conversion
4031 and then not Is_Class_Wide_Type
(Atyp
)
4033 Set_Subtype_Mark
(Arg
, New_Occurrence_Of
(Ftyp
, Sloc
(Arg
)));
4034 Set_Etype
(Arg
, Ftyp
);
4037 -- Otherwise, introduce a conversion when the designated object
4038 -- has a type derived from the formal of the controlled routine.
4040 elsif Is_Private_Type
(Ftyp
)
4041 and then Present
(Atyp
)
4042 and then Is_Derived_Type
(Underlying_Type
(Base_Type
(Atyp
)))
4044 return Unchecked_Convert_To
(Ftyp
, Arg
);
4051 -------------------------------
4052 -- Establish_Transient_Scope --
4053 -------------------------------
4055 -- This procedure is called each time a transient block has to be inserted
4056 -- that is to say for each call to a function with unconstrained or tagged
4057 -- result. It creates a new scope on the scope stack in order to enclose
4058 -- all transient variables generated.
4060 procedure Establish_Transient_Scope
4062 Manage_Sec_Stack
: Boolean)
4064 function Is_Package_Or_Subprogram
(Id
: Entity_Id
) return Boolean;
4065 -- Determine whether arbitrary Id denotes a package or subprogram [body]
4067 function Find_Enclosing_Transient_Scope
return Int
;
4068 -- Examine the scope stack looking for the nearest enclosing transient
4069 -- scope within the innermost enclosing package or subprogram. Return
4070 -- its index in the table or else -1 if no such scope exists.
4072 function Find_Transient_Context
(N
: Node_Id
) return Node_Id
;
4073 -- Locate a suitable context for arbitrary node N which may need to be
4074 -- serviced by a transient scope. Return Empty if no suitable context
4077 procedure Delegate_Sec_Stack_Management
;
4078 -- Move the management of the secondary stack to the nearest enclosing
4081 procedure Create_Transient_Scope
(Context
: Node_Id
);
4082 -- Place a new scope on the scope stack in order to service construct
4083 -- Context. Context is the node found by Find_Transient_Context. The
4084 -- new scope may also manage the secondary stack.
4086 ----------------------------
4087 -- Create_Transient_Scope --
4088 ----------------------------
4090 procedure Create_Transient_Scope
(Context
: Node_Id
) is
4091 Loc
: constant Source_Ptr
:= Sloc
(N
);
4093 Iter_Loop
: Entity_Id
;
4094 Trans_Scop
: constant Entity_Id
:=
4095 New_Internal_Entity
(E_Block
, Current_Scope
, Loc
, 'B');
4098 Set_Etype
(Trans_Scop
, Standard_Void_Type
);
4100 -- Push a new scope, and set its Node_To_Be_Wrapped and Is_Transient
4103 Push_Scope
(Trans_Scop
);
4104 Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
:= Context
;
4105 Scope_Stack
.Table
(Scope_Stack
.Last
).Is_Transient
:= True;
4107 -- The transient scope must also manage the secondary stack
4109 if Manage_Sec_Stack
then
4110 Set_Uses_Sec_Stack
(Trans_Scop
);
4111 Check_Restriction
(No_Secondary_Stack
, N
);
4113 -- The expansion of iterator loops generates references to objects
4114 -- in order to extract elements from a container:
4116 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
4117 -- Obj : <object type> renames Ref.all.Element.all;
4119 -- These references are controlled and returned on the secondary
4120 -- stack. A new reference is created at each iteration of the loop
4121 -- and as a result it must be finalized and the space occupied by
4122 -- it on the secondary stack reclaimed at the end of the current
4125 -- When the context that requires a transient scope is a call to
4126 -- routine Reference, the node to be wrapped is the source object:
4128 -- for Obj of Container loop
4130 -- Routine Wrap_Transient_Declaration however does not generate
4131 -- a physical block as wrapping a declaration will kill it too
4132 -- early. To handle this peculiar case, mark the related iterator
4133 -- loop as requiring the secondary stack. This signals the
4134 -- finalization machinery to manage the secondary stack (see
4135 -- routine Process_Statements_For_Controlled_Objects).
4137 Iter_Loop
:= Find_Enclosing_Iterator_Loop
(Trans_Scop
);
4139 if Present
(Iter_Loop
) then
4140 Set_Uses_Sec_Stack
(Iter_Loop
);
4144 if Debug_Flag_W
then
4145 Write_Str
(" <Transient>");
4148 end Create_Transient_Scope
;
4150 -----------------------------------
4151 -- Delegate_Sec_Stack_Management --
4152 -----------------------------------
4154 procedure Delegate_Sec_Stack_Management
is
4156 for Index
in reverse Scope_Stack
.First
.. Scope_Stack
.Last
loop
4158 Scope
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Index
);
4160 -- Prevent the search from going too far or within the scope
4161 -- space of another unit.
4163 if Scope
.Entity
= Standard_Standard
then
4166 -- No transient scope should be encountered during the
4167 -- traversal because Establish_Transient_Scope should have
4168 -- already handled this case.
4170 elsif Scope
.Is_Transient
then
4171 raise Program_Error
;
4173 -- The construct that requires secondary stack management is
4174 -- always enclosed by a package or subprogram scope.
4176 elsif Is_Package_Or_Subprogram
(Scope
.Entity
) then
4177 Set_Uses_Sec_Stack
(Scope
.Entity
);
4178 Check_Restriction
(No_Secondary_Stack
, N
);
4185 -- At this point no suitable scope was found. This should never occur
4186 -- because a construct is always enclosed by a compilation unit which
4189 pragma Assert
(False);
4190 end Delegate_Sec_Stack_Management
;
4192 ------------------------------------
4193 -- Find_Enclosing_Transient_Scope --
4194 ------------------------------------
4196 function Find_Enclosing_Transient_Scope
return Int
is
4198 for Index
in reverse Scope_Stack
.First
.. Scope_Stack
.Last
loop
4200 Scope
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Index
);
4202 -- Prevent the search from going too far or within the scope
4203 -- space of another unit.
4205 if Scope
.Entity
= Standard_Standard
4206 or else Is_Package_Or_Subprogram
(Scope
.Entity
)
4210 elsif Scope
.Is_Transient
then
4217 end Find_Enclosing_Transient_Scope
;
4219 ----------------------------
4220 -- Find_Transient_Context --
4221 ----------------------------
4223 function Find_Transient_Context
(N
: Node_Id
) return Node_Id
is
4224 Curr
: Node_Id
:= N
;
4225 Prev
: Node_Id
:= Empty
;
4228 while Present
(Curr
) loop
4229 case Nkind
(Curr
) is
4233 -- Declarations act as a boundary for a transient scope even if
4234 -- they are not wrapped, see Wrap_Transient_Declaration.
4236 when N_Object_Declaration
4237 | N_Object_Renaming_Declaration
4238 | N_Subtype_Declaration
4244 -- Statements and statement-like constructs act as a boundary
4245 -- for a transient scope.
4247 when N_Accept_Alternative
4248 | N_Attribute_Definition_Clause
4250 | N_Case_Statement_Alternative
4252 | N_Delay_Alternative
4253 | N_Delay_Until_Statement
4254 | N_Delay_Relative_Statement
4255 | N_Discriminant_Association
4257 | N_Entry_Body_Formal_Part
4260 | N_Iteration_Scheme
4261 | N_Terminate_Alternative
4263 pragma Assert
(Present
(Prev
));
4266 when N_Assignment_Statement
=>
4269 when N_Entry_Call_Statement
4270 | N_Procedure_Call_Statement
4272 -- When an entry or procedure call acts as the alternative
4273 -- of a conditional or timed entry call, the proper context
4274 -- is that of the alternative.
4276 if Nkind
(Parent
(Curr
)) = N_Entry_Call_Alternative
4277 and then Nkind
(Parent
(Parent
(Curr
))) in
4278 N_Conditional_Entry_Call | N_Timed_Entry_Call
4280 return Parent
(Parent
(Curr
));
4282 -- General case for entry or procedure calls
4290 -- Pragma Check is not a valid transient context in
4291 -- GNATprove mode because the pragma must remain unchanged.
4294 and then Get_Pragma_Id
(Curr
) = Pragma_Check
4298 -- General case for pragmas
4304 when N_Raise_Statement
=>
4307 when N_Simple_Return_Statement
=>
4309 Fun_Id
: constant Entity_Id
:=
4310 Return_Applies_To
(Return_Statement_Entity
(Curr
));
4313 -- A transient context that must manage the secondary
4314 -- stack cannot be a return statement of a function that
4315 -- itself requires secondary stack management, because
4316 -- the function's result would be reclaimed too early.
4317 -- And returns of thunks never require transient scopes.
4319 if (Manage_Sec_Stack
4320 and then Needs_Secondary_Stack
(Etype
(Fun_Id
)))
4321 or else Is_Thunk
(Fun_Id
)
4325 -- General case for return statements
4334 when N_Attribute_Reference
=>
4335 if Is_Procedure_Attribute_Name
(Attribute_Name
(Curr
)) then
4339 -- An Ada 2012 iterator specification is not a valid context
4340 -- because Analyze_Iterator_Specification already employs
4341 -- special processing for it.
4343 when N_Iterator_Specification
=>
4346 when N_Loop_Parameter_Specification
=>
4348 -- An iteration scheme is not a valid context because
4349 -- routine Analyze_Iteration_Scheme already employs
4350 -- special processing.
4352 if Nkind
(Parent
(Curr
)) = N_Iteration_Scheme
then
4355 return Parent
(Curr
);
4360 -- The following nodes represent "dummy contexts" which do not
4361 -- need to be wrapped.
4363 when N_Component_Declaration
4364 | N_Discriminant_Specification
4365 | N_Parameter_Specification
4369 -- If the traversal leaves a scope without having been able to
4370 -- find a construct to wrap, something is going wrong, but this
4371 -- can happen in error situations that are not detected yet
4372 -- (such as a dynamic string in a pragma Export).
4374 when N_Block_Statement
4377 | N_Package_Declaration
4391 Curr
:= Parent
(Curr
);
4395 end Find_Transient_Context
;
4397 ------------------------------
4398 -- Is_Package_Or_Subprogram --
4399 ------------------------------
4401 function Is_Package_Or_Subprogram
(Id
: Entity_Id
) return Boolean is
4403 return Ekind
(Id
) in E_Entry
4408 | E_Subprogram_Body
;
4409 end Is_Package_Or_Subprogram
;
4413 Trans_Idx
: constant Int
:= Find_Enclosing_Transient_Scope
;
4416 -- Start of processing for Establish_Transient_Scope
4419 -- Do not create a new transient scope if there is already an enclosing
4420 -- transient scope within the innermost enclosing package or subprogram.
4422 if Trans_Idx
>= 0 then
4424 -- If the transient scope was requested for purposes of managing the
4425 -- secondary stack, then the existing scope must perform this task,
4426 -- unless the node to be wrapped is a return statement of a function
4427 -- that requires secondary stack management, because the function's
4428 -- result would be reclaimed too early (see Find_Transient_Context).
4430 if Manage_Sec_Stack
then
4432 SE
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Trans_Idx
);
4435 if Nkind
(SE
.Node_To_Be_Wrapped
) /= N_Simple_Return_Statement
4437 Needs_Secondary_Stack
4440 (Return_Statement_Entity
(SE
.Node_To_Be_Wrapped
))))
4442 Set_Uses_Sec_Stack
(SE
.Entity
);
4450 -- Find the construct that must be serviced by a new transient scope, if
4453 Context
:= Find_Transient_Context
(N
);
4455 if Present
(Context
) then
4456 if Nkind
(Context
) = N_Assignment_Statement
then
4458 -- An assignment statement with suppressed controlled semantics
4459 -- does not need a transient scope because finalization is not
4460 -- desirable at this point. Note that No_Ctrl_Actions is also
4461 -- set for non-controlled assignments to suppress dispatching
4464 if No_Ctrl_Actions
(Context
)
4465 and then Needs_Finalization
(Etype
(Name
(Context
)))
4467 -- When a controlled component is initialized by a function
4468 -- call, the result on the secondary stack is always assigned
4469 -- to the component. Signal the nearest suitable scope that it
4470 -- is safe to manage the secondary stack.
4472 if Manage_Sec_Stack
and then Within_Init_Proc
then
4473 Delegate_Sec_Stack_Management
;
4476 -- Otherwise the assignment is a normal transient context and thus
4477 -- requires a transient scope.
4480 Create_Transient_Scope
(Context
);
4486 Create_Transient_Scope
(Context
);
4489 end Establish_Transient_Scope
;
4491 ----------------------------
4492 -- Expand_Cleanup_Actions --
4493 ----------------------------
4495 procedure Expand_Cleanup_Actions
(N
: Node_Id
) is
4497 (Nkind
(N
) in N_Block_Statement
4501 | N_Extended_Return_Statement
);
4503 Scop
: constant Entity_Id
:= Current_Scope
;
4505 Is_Asynchronous_Call
: constant Boolean :=
4506 Nkind
(N
) = N_Block_Statement
4507 and then Is_Asynchronous_Call_Block
(N
);
4508 Is_Master
: constant Boolean :=
4509 Nkind
(N
) /= N_Extended_Return_Statement
4510 and then Nkind
(N
) /= N_Entry_Body
4511 and then Is_Task_Master
(N
);
4512 Is_Protected_Subp_Body
: constant Boolean :=
4513 Nkind
(N
) = N_Subprogram_Body
4514 and then Is_Protected_Subprogram_Body
(N
);
4515 Is_Task_Allocation
: constant Boolean :=
4516 Nkind
(N
) = N_Block_Statement
4517 and then Is_Task_Allocation_Block
(N
);
4518 Is_Task_Body
: constant Boolean :=
4519 Nkind
(Original_Node
(N
)) = N_Task_Body
;
4521 -- We mark the secondary stack if it is used in this construct, and
4522 -- we're not returning a function result on the secondary stack, except
4523 -- that a build-in-place function that might or might not return on the
4524 -- secondary stack always needs a mark. A run-time test is required in
4525 -- the case where the build-in-place function has a BIP_Alloc extra
4526 -- parameter (see Create_Finalizer).
4528 Needs_Sec_Stack_Mark
: constant Boolean :=
4529 (Uses_Sec_Stack
(Scop
)
4531 not Sec_Stack_Needed_For_Return
(Scop
))
4533 (Is_Build_In_Place_Function
(Scop
)
4534 and then Needs_BIP_Alloc_Form
(Scop
));
4536 Needs_Custom_Cleanup
: constant Boolean :=
4537 Nkind
(N
) = N_Block_Statement
4538 and then Present
(Cleanup_Actions
(N
));
4540 Actions_Required
: constant Boolean :=
4541 Requires_Cleanup_Actions
(N
, True)
4542 or else Is_Asynchronous_Call
4544 or else Is_Protected_Subp_Body
4545 or else Is_Task_Allocation
4546 or else Is_Task_Body
4547 or else Needs_Sec_Stack_Mark
4548 or else Needs_Custom_Cleanup
;
4553 -- Start of processing for Expand_Cleanup_Actions
4556 -- The current construct does not need any form of servicing
4558 if not Actions_Required
then
4562 -- If an extended return statement contains something like
4566 -- where F is a build-in-place function call returning a controlled
4567 -- type, then a temporary object will be implicitly declared as part
4568 -- of the statement list, and this will need cleanup. In such cases,
4571 -- return Result : T := ... do
4572 -- <statements> -- possibly with handlers
4577 -- return Result : T := ... do
4578 -- declare -- no declarations
4580 -- <statements> -- possibly with handlers
4581 -- end; -- no handlers
4584 -- So Expand_Cleanup_Actions will end up being called recursively on the
4587 if Nkind
(N
) = N_Extended_Return_Statement
then
4589 Block
: constant Node_Id
:=
4590 Make_Block_Statement
(Sloc
(N
),
4591 Declarations
=> Empty_List
,
4592 Handled_Statement_Sequence
=>
4593 Handled_Statement_Sequence
(N
));
4595 Set_Handled_Statement_Sequence
(N
,
4596 Make_Handled_Sequence_Of_Statements
(Sloc
(N
),
4597 Statements
=> New_List
(Block
)));
4602 -- Analysis of the block did all the work
4607 if Needs_Custom_Cleanup
then
4608 Cln
:= Cleanup_Actions
(N
);
4613 if No
(Declarations
(N
)) then
4614 Set_Declarations
(N
, New_List
);
4618 Decls
: constant List_Id
:= Declarations
(N
);
4620 Mark
: Entity_Id
:= Empty
;
4622 -- If we are generating expanded code for debugging purposes, use the
4623 -- Sloc of the point of insertion for the cleanup code. The Sloc will
4624 -- be updated subsequently to reference the proper line in .dg files.
4625 -- If we are not debugging generated code, use No_Location instead,
4626 -- so that no debug information is generated for the cleanup code.
4627 -- This makes the behavior of the NEXT command in GDB monotonic, and
4628 -- makes the placement of breakpoints more accurate.
4630 if Debug_Generated_Code
then
4636 -- A task activation call has already been built for a task
4637 -- allocation block.
4639 if not Is_Task_Allocation
then
4640 Build_Task_Activation_Call
(N
);
4644 Establish_Task_Master
(N
);
4647 -- If secondary stack is in use, generate:
4649 -- Mnn : constant Mark_Id := SS_Mark;
4651 if Needs_Sec_Stack_Mark
then
4652 Set_Uses_Sec_Stack
(Scop
, False); -- avoid duplicate SS marks
4653 Mark
:= Make_Temporary
(Loc
, 'M');
4656 Mark_Call
: constant Node_Id
:= Build_SS_Mark_Call
(Loc
, Mark
);
4658 Prepend_To
(Decls
, Mark_Call
);
4659 Analyze
(Mark_Call
);
4663 -- Generate finalization calls for all controlled objects appearing
4664 -- in the statements of N. Add context specific cleanup for various
4669 Clean_Stmts
=> Build_Cleanup_Statements
(N
, Cln
),
4672 Defer_Abort
=> Nkind
(Original_Node
(N
)) = N_Task_Body
4676 if Present
(Fin_Id
) then
4677 Build_Finalizer_Call
(N
, Fin_Id
);
4680 end Expand_Cleanup_Actions
;
4682 ---------------------------
4683 -- Expand_N_Package_Body --
4684 ---------------------------
4686 -- Add call to Activate_Tasks if body is an activator (actual processing
4687 -- is in chapter 9).
4689 -- Generate subprogram descriptor for elaboration routine
4691 -- Encode entity names in package body
4693 procedure Expand_N_Package_Body
(N
: Node_Id
) is
4694 Id
: constant Entity_Id
:= Defining_Entity
(N
);
4695 Spec_Id
: constant Entity_Id
:= Corresponding_Spec
(N
);
4700 -- This is done only for non-generic packages
4702 if Ekind
(Spec_Id
) = E_Package
then
4703 -- Build dispatch tables of library-level tagged types for bodies
4704 -- that are not compilation units (see Analyze_Compilation_Unit),
4705 -- except for instances because they have no N_Compilation_Unit.
4707 if Tagged_Type_Expansion
4708 and then Is_Library_Level_Entity
(Spec_Id
)
4709 and then (not Is_Compilation_Unit
(Spec_Id
)
4710 or else Is_Generic_Instance
(Spec_Id
))
4712 Build_Static_Dispatch_Tables
(N
);
4715 Push_Scope
(Spec_Id
);
4717 Expand_CUDA_Package
(N
);
4719 Build_Task_Activation_Call
(N
);
4721 -- Verify the run-time semantics of pragma Initial_Condition at the
4722 -- end of the body statements.
4724 Expand_Pragma_Initial_Condition
(Spec_Id
, N
);
4726 -- If this is a library-level package and unnesting is enabled,
4727 -- check for the presence of blocks with nested subprograms occurring
4728 -- in elaboration code, and generate procedures to encapsulate the
4729 -- blocks in case the nested subprograms make up-level references.
4731 if Unnest_Subprogram_Mode
4733 Is_Library_Level_Entity
(Current_Scope
)
4735 Check_Unnesting_Elaboration_Code
(N
);
4736 Check_Unnesting_In_Decls_Or_Stmts
(Declarations
(N
));
4737 Check_Unnesting_In_Handlers
(N
);
4743 Set_Elaboration_Flag
(N
, Spec_Id
);
4744 Set_In_Package_Body
(Spec_Id
, False);
4746 -- Set to encode entity names in package body before gigi is called
4748 Qualify_Entity_Names
(N
);
4750 if Ekind
(Spec_Id
) /= E_Generic_Package
4751 and then not Delay_Cleanups
(Id
)
4755 Clean_Stmts
=> No_List
,
4757 Top_Decls
=> No_List
,
4758 Defer_Abort
=> False,
4761 if Present
(Fin_Id
) then
4762 Set_Finalizer
(Defining_Entity
(N
), Fin_Id
);
4765 end Expand_N_Package_Body
;
4767 ----------------------------------
4768 -- Expand_N_Package_Declaration --
4769 ----------------------------------
4771 -- Add call to Activate_Tasks if there are tasks declared and the package
4772 -- has no body. Note that in Ada 83 this may result in premature activation
4773 -- of some tasks, given that we cannot tell whether a body will eventually
4776 procedure Expand_N_Package_Declaration
(N
: Node_Id
) is
4777 Id
: constant Entity_Id
:= Defining_Entity
(N
);
4778 Spec
: constant Node_Id
:= Specification
(N
);
4782 No_Body
: Boolean := False;
4783 -- True in the case of a package declaration that is a compilation
4784 -- unit and for which no associated body will be compiled in this
4788 -- Case of a package declaration other than a compilation unit
4790 if Nkind
(Parent
(N
)) /= N_Compilation_Unit
then
4793 -- Case of a compilation unit that does not require a body
4795 elsif not Body_Required
(Parent
(N
))
4796 and then not Unit_Requires_Body
(Id
)
4800 -- Special case of generating calling stubs for a remote call interface
4801 -- package: even though the package declaration requires one, the body
4802 -- won't be processed in this compilation (so any stubs for RACWs
4803 -- declared in the package must be generated here, along with the spec).
4805 elsif Parent
(N
) = Cunit
(Main_Unit
)
4806 and then Is_Remote_Call_Interface
(Id
)
4807 and then Distribution_Stub_Mode
= Generate_Caller_Stub_Body
4812 -- For a nested instance, delay processing until freeze point
4814 if Has_Delayed_Freeze
(Id
)
4815 and then Nkind
(Parent
(N
)) /= N_Compilation_Unit
4820 -- For a package declaration that implies no associated body, generate
4821 -- task activation call and RACW supporting bodies now (since we won't
4822 -- have a specific separate compilation unit for that).
4827 -- Generate RACW subprogram bodies
4829 if Has_RACW
(Id
) then
4830 Decls
:= Private_Declarations
(Spec
);
4833 Decls
:= Visible_Declarations
(Spec
);
4838 Set_Visible_Declarations
(Spec
, Decls
);
4841 Append_RACW_Bodies
(Decls
, Id
);
4842 Analyze_List
(Decls
);
4845 -- Generate task activation call as last step of elaboration
4847 if Present
(Activation_Chain_Entity
(N
)) then
4848 Build_Task_Activation_Call
(N
);
4851 -- Verify the run-time semantics of pragma Initial_Condition at the
4852 -- end of the private declarations when the package lacks a body.
4854 Expand_Pragma_Initial_Condition
(Id
, N
);
4859 -- Build dispatch tables of library-level tagged types for instances
4860 -- that are not compilation units (see Analyze_Compilation_Unit).
4862 if Tagged_Type_Expansion
4863 and then Is_Library_Level_Entity
(Id
)
4864 and then Is_Generic_Instance
(Id
)
4865 and then not Is_Compilation_Unit
(Id
)
4867 Build_Static_Dispatch_Tables
(N
);
4870 -- Note: it is not necessary to worry about generating a subprogram
4871 -- descriptor, since the only way to get exception handlers into a
4872 -- package spec is to include instantiations, and that would cause
4873 -- generation of subprogram descriptors to be delayed in any case.
4875 -- Set to encode entity names in package spec before gigi is called
4877 Qualify_Entity_Names
(N
);
4879 if Ekind
(Id
) /= E_Generic_Package
4880 and then not Delay_Cleanups
(Id
)
4884 Clean_Stmts
=> No_List
,
4886 Top_Decls
=> No_List
,
4887 Defer_Abort
=> False,
4890 if Present
(Fin_Id
) then
4891 Set_Finalizer
(Id
, Fin_Id
);
4895 -- If this is a library-level package and unnesting is enabled,
4896 -- check for the presence of blocks with nested subprograms occurring
4897 -- in elaboration code, and generate procedures to encapsulate the
4898 -- blocks in case the nested subprograms make up-level references.
4900 if Unnest_Subprogram_Mode
4901 and then Is_Library_Level_Entity
(Current_Scope
)
4903 Check_Unnesting_In_Decls_Or_Stmts
(Visible_Declarations
(Spec
));
4904 Check_Unnesting_In_Decls_Or_Stmts
(Private_Declarations
(Spec
));
4906 end Expand_N_Package_Declaration
;
4908 ---------------------------------
4909 -- Has_Simple_Protected_Object --
4910 ---------------------------------
4912 function Has_Simple_Protected_Object
(T
: Entity_Id
) return Boolean is
4914 if Has_Task
(T
) then
4917 elsif Is_Simple_Protected_Type
(T
) then
4920 elsif Is_Array_Type
(T
) then
4921 return Has_Simple_Protected_Object
(Component_Type
(T
));
4923 elsif Is_Record_Type
(T
) then
4928 Comp
:= First_Component
(T
);
4929 while Present
(Comp
) loop
4930 if Has_Simple_Protected_Object
(Etype
(Comp
)) then
4934 Next_Component
(Comp
);
4943 end Has_Simple_Protected_Object
;
4945 ------------------------------------
4946 -- Insert_Actions_In_Scope_Around --
4947 ------------------------------------
4949 procedure Insert_Actions_In_Scope_Around
4952 Manage_SS
: Boolean)
4954 Act_Before
: constant List_Id
:=
4955 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Before
);
4956 Act_After
: constant List_Id
:=
4957 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(After
);
4958 Act_Cleanup
: constant List_Id
:=
4959 Scope_Stack
.Table
(Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Cleanup
);
4960 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
4961 -- Last), but this was incorrect as Process_Transients_In_Scope may
4962 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
4964 procedure Process_Transients_In_Scope
4965 (First_Object
: Node_Id
;
4966 Last_Object
: Node_Id
;
4967 Related_Node
: Node_Id
);
4968 -- Find all transient objects in the list First_Object .. Last_Object
4969 -- and generate finalization actions for them. Related_Node denotes the
4970 -- node which created all transient objects.
4972 ---------------------------------
4973 -- Process_Transients_In_Scope --
4974 ---------------------------------
4976 procedure Process_Transients_In_Scope
4977 (First_Object
: Node_Id
;
4978 Last_Object
: Node_Id
;
4979 Related_Node
: Node_Id
)
4981 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
;
4982 -- Return Abandon if arbitrary node denotes a subprogram call
4984 function Has_Subprogram_Call
is
4985 new Traverse_Func
(Is_Subprogram_Call
);
4987 procedure Process_Transient_In_Scope
4988 (Obj_Decl
: Node_Id
;
4989 Insert_Nod
: Node_Id
;
4990 Must_Export
: Boolean);
4991 -- Generate finalization actions for a single transient object
4992 -- denoted by object declaration Obj_Decl.
4994 ------------------------
4995 -- Is_Subprogram_Call --
4996 ------------------------
4998 function Is_Subprogram_Call
(N
: Node_Id
) return Traverse_Result
is
5000 -- A regular procedure or function call
5002 if Nkind
(N
) in N_Subprogram_Call
then
5007 -- Heavy expansion may relocate function calls outside the related
5008 -- node. Inspect the original node to detect the initial placement
5011 elsif Is_Rewrite_Substitution
(N
) then
5012 return Has_Subprogram_Call
(Original_Node
(N
));
5014 -- Generalized indexing always involves a function call
5016 elsif Nkind
(N
) = N_Indexed_Component
5017 and then Present
(Generalized_Indexing
(N
))
5026 end Is_Subprogram_Call
;
5028 --------------------------------
5029 -- Process_Transient_In_Scope --
5030 --------------------------------
5032 procedure Process_Transient_In_Scope
5033 (Obj_Decl
: Node_Id
;
5034 Insert_Nod
: Node_Id
;
5035 Must_Export
: Boolean)
5037 Loc
: constant Source_Ptr
:= Sloc
(Obj_Decl
);
5038 Obj_Id
: constant Entity_Id
:= Defining_Entity
(Obj_Decl
);
5040 Master_Node_Id
: Entity_Id
;
5041 Master_Node_Decl
: Node_Id
;
5043 Obj_Typ
: Entity_Id
;
5046 -- If the object needs to be exported to the outer finalizer,
5047 -- create the declaration of the Master_Node for the object,
5048 -- which will later be picked up by Build_Finalizer.
5051 Master_Node_Id
:= Make_Temporary
(Loc
, 'N');
5053 Make_Master_Node_Declaration
(Loc
, Master_Node_Id
, Obj_Id
);
5054 Insert_Before_And_Analyze
(Obj_Decl
, Master_Node_Decl
);
5056 -- Generate the attachment of the object to the Master_Node
5058 Attach_Object_To_Master_Node
(Obj_Decl
, Master_Node_Id
);
5060 -- Then add the finalization call for the object
5062 Insert_After_And_Analyze
(Insert_Nod
,
5063 Make_Procedure_Call_Statement
(Loc
,
5065 New_Occurrence_Of
(RTE
(RE_Finalize_Object
), Loc
),
5066 Parameter_Associations
=> New_List
(
5067 New_Occurrence_Of
(Master_Node_Id
, Loc
))));
5069 -- Otherwise generate a direct finalization call for the object
5072 -- Handle the object type and the reference to the object
5074 Obj_Ref
:= New_Occurrence_Of
(Obj_Id
, Loc
);
5075 Obj_Typ
:= Base_Type
(Etype
(Obj_Id
));
5077 if Is_Access_Type
(Obj_Typ
) then
5078 Obj_Ref
:= Make_Explicit_Dereference
(Loc
, Obj_Ref
);
5079 Obj_Typ
:= Available_View
(Designated_Type
(Obj_Typ
));
5082 Insert_After_And_Analyze
(Insert_Nod
,
5083 Make_Final_Call
(Obj_Ref
=> Obj_Ref
, Typ
=> Obj_Typ
));
5086 -- Mark the transient object to avoid double finalization
5088 Set_Is_Finalized_Transient
(Obj_Id
);
5089 end Process_Transient_In_Scope
;
5093 Insert_Nod
: Node_Id
;
5094 -- Insertion node for the finalization actions
5096 Must_Export
: Boolean;
5097 -- Flag denoting whether the context requires transient object
5098 -- export to the outer finalizer.
5102 -- Start of processing for Process_Transients_In_Scope
5105 -- The expansion performed by this routine is as follows:
5107 -- Ctrl_Trans_Obj_1MN : Master_Node;
5108 -- Ctrl_Trans_Obj_1 : ...;
5110 -- Ctrl_Trans_Obj_NMN : Master_Node;
5111 -- Ctrl_Trans_Obj_N : ...;
5113 -- Finalize_Object (Ctrl_Trans_Obj_NMN);
5115 -- Finalize_Object (Ctrl_Trans_Obj_1MN);
5117 -- Recognize a scenario where the transient context is an object
5118 -- declaration initialized by a build-in-place function call:
5120 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
5122 -- The rough expansion of the above is:
5124 -- Temp : ... := Ctrl_Func_Call;
5126 -- Res : ... := BIP_Func_Call (..., Obj, ...);
5128 -- The finalization of any transient object must happen after the
5129 -- build-in-place function call is executed.
5131 if Nkind
(N
) = N_Object_Declaration
5132 and then Present
(BIP_Initialization_Call
(Defining_Identifier
(N
)))
5134 Must_Export
:= True;
5135 Insert_Nod
:= BIP_Initialization_Call
(Defining_Identifier
(N
));
5137 -- Search the context for at least one subprogram call. If found, the
5138 -- machinery exports all transient objects to the enclosing finalizer
5139 -- due to the possibility of abnormal call termination.
5142 Must_Export
:= Has_Subprogram_Call
(N
) = Abandon
;
5143 Insert_Nod
:= Last_Object
;
5146 Insert_List_After_And_Analyze
(Insert_Nod
, Act_Cleanup
);
5148 -- Examine all the objects in the list First_Object .. Last_Object
5149 -- but skip the node to be wrapped because it is not transient as
5150 -- far as this scope is concerned.
5152 Obj_Decl
:= First_Object
;
5153 while Present
(Obj_Decl
) loop
5154 if Obj_Decl
/= Related_Node
5155 and then Nkind
(Obj_Decl
) = N_Object_Declaration
5156 and then Analyzed
(Obj_Decl
)
5157 and then Is_Finalizable_Transient
(Obj_Decl
, N
)
5159 Process_Transient_In_Scope
(Obj_Decl
, Insert_Nod
, Must_Export
);
5162 exit when Obj_Decl
= Last_Object
;
5166 end Process_Transients_In_Scope
;
5170 Loc
: constant Source_Ptr
:= Sloc
(N
);
5171 Node_To_Wrap
: constant Node_Id
:= Node_To_Be_Wrapped
;
5172 First_Obj
: Node_Id
;
5174 Mark_Id
: Entity_Id
;
5177 -- Start of processing for Insert_Actions_In_Scope_Around
5180 -- Nothing to do if the scope does not manage the secondary stack or
5181 -- does not contain meaningful actions for insertion.
5184 and then No
(Act_Before
)
5185 and then No
(Act_After
)
5186 and then No
(Act_Cleanup
)
5191 -- If the node to be wrapped is the trigger of an asynchronous select,
5192 -- it is not part of a statement list. The actions must be inserted
5193 -- before the select itself, which is part of some list of statements.
5194 -- Note that the triggering alternative includes the triggering
5195 -- statement and an optional statement list. If the node to be
5196 -- wrapped is part of that list, the normal insertion applies.
5198 if Nkind
(Parent
(Node_To_Wrap
)) = N_Triggering_Alternative
5199 and then not Is_List_Member
(Node_To_Wrap
)
5201 Target
:= Parent
(Parent
(Node_To_Wrap
));
5206 First_Obj
:= Target
;
5209 -- Add all actions associated with a transient scope into the main tree.
5210 -- There are several scenarios here:
5212 -- +--- Before ----+ +----- After ---+
5213 -- 1) First_Obj ....... Target ........ Last_Obj
5215 -- 2) First_Obj ....... Target
5217 -- 3) Target ........ Last_Obj
5219 -- Flag declarations are inserted before the first object
5221 if Present
(Act_Before
) then
5222 First_Obj
:= First
(Act_Before
);
5223 Insert_List_Before
(Target
, Act_Before
);
5226 -- Finalization calls are inserted after the last object
5228 if Present
(Act_After
) then
5229 Last_Obj
:= Last
(Act_After
);
5230 Insert_List_After
(Target
, Act_After
);
5233 -- Mark and release the secondary stack when the context warrants it
5236 Mark_Id
:= Make_Temporary
(Loc
, 'M');
5239 -- Mnn : constant Mark_Id := SS_Mark;
5241 Insert_Before_And_Analyze
5242 (First_Obj
, Build_SS_Mark_Call
(Loc
, Mark_Id
));
5245 -- SS_Release (Mnn);
5247 Insert_After_And_Analyze
5248 (Last_Obj
, Build_SS_Release_Call
(Loc
, Mark_Id
));
5251 -- If we are handling cleanups, check for transient objects associated
5252 -- with Target and generate the required finalization actions for them.
5255 Process_Transients_In_Scope
5256 (First_Object
=> First_Obj
,
5257 Last_Object
=> Last_Obj
,
5258 Related_Node
=> Target
);
5261 -- Reset the action lists
5264 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Before
) := No_List
;
5266 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(After
) := No_List
;
5270 (Scope_Stack
.Last
).Actions_To_Be_Wrapped
(Cleanup
) := No_List
;
5272 end Insert_Actions_In_Scope_Around
;
5274 ------------------------------
5275 -- Is_Simple_Protected_Type --
5276 ------------------------------
5278 function Is_Simple_Protected_Type
(T
: Entity_Id
) return Boolean is
5281 Is_Protected_Type
(T
)
5282 and then not Uses_Lock_Free
(T
)
5283 and then not Has_Entries
(T
)
5284 and then Is_RTE
(Find_Protection_Type
(T
), RE_Protection
);
5285 end Is_Simple_Protected_Type
;
5287 -------------------------------
5288 -- Make_Address_For_Finalize --
5289 -------------------------------
5291 function Make_Address_For_Finalize
5294 Obj_Typ
: Entity_Id
) return Node_Id
5300 Make_Attribute_Reference
(Loc
,
5302 Attribute_Name
=> Name_Address
);
5304 -- If the type of a constrained array has an unconstrained first
5305 -- subtype, its Finalize_Address primitive expects the address of
5306 -- an object with a dope vector (see Make_Finalize_Address_Stmts).
5307 -- This is achieved by setting Is_Constr_Array_Subt_With_Bounds,
5308 -- but the address of the object is still that of its elements,
5309 -- so we need to shift it.
5311 if Is_Array_Type
(Obj_Typ
)
5312 and then not Is_Constrained
(First_Subtype
(Obj_Typ
))
5314 -- Shift the address from the start of the elements to the
5315 -- start of the dope vector:
5317 -- V - (Obj_Typ'Descriptor_Size / Storage_Unit)
5319 -- Note that this is done through a wrapper routine as RTSfind
5320 -- cannot retrieve operations with string name of the form "+".
5323 Make_Function_Call
(Loc
,
5325 New_Occurrence_Of
(RTE
(RE_Add_Offset_To_Address
), Loc
),
5326 Parameter_Associations
=> New_List
(
5329 Make_Op_Divide
(Loc
,
5331 Make_Attribute_Reference
(Loc
,
5332 Prefix
=> New_Occurrence_Of
(Obj_Typ
, Loc
),
5333 Attribute_Name
=> Name_Descriptor_Size
),
5335 Make_Integer_Literal
(Loc
, System_Storage_Unit
)))));
5339 end Make_Address_For_Finalize
;
5341 -----------------------
5342 -- Make_Adjust_Call --
5343 -----------------------
5345 function Make_Adjust_Call
5348 Skip_Self
: Boolean := False) return Node_Id
5350 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
5351 Adj_Id
: Entity_Id
:= Empty
;
5358 -- Recover the proper type which contains Deep_Adjust
5360 if Is_Class_Wide_Type
(Typ
) then
5361 Utyp
:= Root_Type
(Typ
);
5366 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
5367 Set_Assignment_OK
(Ref
);
5369 -- Deal with untagged derivation of private views
5371 if Present
(Utyp
) and then Is_Untagged_Derivation
(Typ
) then
5372 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
5373 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
5374 Set_Assignment_OK
(Ref
);
5377 -- When dealing with the completion of a private type, use the base
5380 if Present
(Utyp
) and then Utyp
/= Base_Type
(Utyp
) then
5381 pragma Assert
(Is_Private_Type
(Typ
));
5383 Utyp
:= Base_Type
(Utyp
);
5384 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
5387 -- The underlying type may not be present due to a missing full view. In
5388 -- this case freezing did not take place and there is no [Deep_]Adjust
5389 -- primitive to call.
5394 elsif Skip_Self
then
5395 if Has_Controlled_Component
(Utyp
) then
5396 if Is_Tagged_Type
(Utyp
) then
5397 Adj_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5399 Adj_Id
:= TSS
(Utyp
, TSS_Deep_Adjust
);
5403 -- Class-wide types, interfaces and types with controlled components
5405 elsif Is_Class_Wide_Type
(Typ
)
5406 or else Is_Interface
(Typ
)
5407 or else Has_Controlled_Component
(Utyp
)
5409 if Is_Tagged_Type
(Utyp
) then
5410 Adj_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5412 Adj_Id
:= TSS
(Utyp
, TSS_Deep_Adjust
);
5415 -- Derivations from [Limited_]Controlled
5417 elsif Is_Controlled
(Utyp
) then
5418 Adj_Id
:= Find_Optional_Prim_Op
(Utyp
, Name_Of
(Adjust_Case
));
5422 elsif Is_Tagged_Type
(Utyp
) then
5423 Adj_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Adjust
);
5426 raise Program_Error
;
5429 if Present
(Adj_Id
) then
5431 -- If the object is unanalyzed, set its expected type for use in
5432 -- Convert_View in case an additional conversion is needed.
5435 and then Nkind
(Ref
) /= N_Unchecked_Type_Conversion
5437 Set_Etype
(Ref
, Typ
);
5440 -- The object reference may need another conversion depending on the
5441 -- type of the formal and that of the actual.
5443 if not Is_Class_Wide_Type
(Typ
) then
5444 Ref
:= Convert_View
(Adj_Id
, Ref
);
5451 Skip_Self
=> Skip_Self
);
5455 end Make_Adjust_Call
;
5463 Proc_Id
: Entity_Id
;
5465 Skip_Self
: Boolean := False) return Node_Id
5467 Params
: constant List_Id
:= New_List
(Param
);
5470 -- Do not apply the controlled action to the object itself by signaling
5471 -- the related routine to avoid self.
5474 Append_To
(Params
, New_Occurrence_Of
(Standard_False
, Loc
));
5478 Make_Procedure_Call_Statement
(Loc
,
5479 Name
=> New_Occurrence_Of
(Proc_Id
, Loc
),
5480 Parameter_Associations
=> Params
);
5483 --------------------------
5484 -- Make_Deep_Array_Body --
5485 --------------------------
5487 function Make_Deep_Array_Body
5488 (Prim
: Final_Primitives
;
5489 Typ
: Entity_Id
) return List_Id
5491 function Build_Adjust_Or_Finalize_Statements
5492 (Typ
: Entity_Id
) return List_Id
;
5493 -- Create the statements necessary to adjust or finalize an array of
5494 -- controlled elements. Generate:
5497 -- Abort : constant Boolean := Triggered_By_Abort;
5499 -- Abort : constant Boolean := False; -- no abort
5501 -- E : Exception_Occurrence;
5502 -- Raised : Boolean := False;
5505 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
5506 -- ^-- in the finalization case
5508 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
5510 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
5514 -- if not Raised then
5516 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5523 -- if Raised and then not Abort then
5524 -- Raise_From_Controlled_Operation (E);
5528 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
;
5529 -- Create the statements necessary to initialize an array of controlled
5530 -- elements. Include a mechanism to carry out partial finalization if an
5531 -- exception occurs. Generate:
5534 -- Counter : Integer := 0;
5537 -- for J1 in V'Range (1) loop
5539 -- for JN in V'Range (N) loop
5541 -- [Deep_]Initialize (V (J1, ..., JN));
5543 -- Counter := Counter + 1;
5548 -- Abort : constant Boolean := Triggered_By_Abort;
5550 -- Abort : constant Boolean := False; -- no abort
5551 -- E : Exception_Occurrence;
5552 -- Raised : Boolean := False;
5559 -- V'Length (N) - Counter;
5561 -- for F1 in reverse V'Range (1) loop
5563 -- for FN in reverse V'Range (N) loop
5564 -- if Counter > 0 then
5565 -- Counter := Counter - 1;
5568 -- [Deep_]Finalize (V (F1, ..., FN));
5572 -- if not Raised then
5574 -- Save_Occurrence (E,
5575 -- Get_Current_Excep.all.all);
5584 -- if Raised and then not Abort then
5585 -- Raise_From_Controlled_Operation (E);
5594 function New_References_To
5596 Loc
: Source_Ptr
) return List_Id
;
5597 -- Given a list of defining identifiers, return a list of references to
5598 -- the original identifiers, in the same order as they appear.
5600 -----------------------------------------
5601 -- Build_Adjust_Or_Finalize_Statements --
5602 -----------------------------------------
5604 function Build_Adjust_Or_Finalize_Statements
5605 (Typ
: Entity_Id
) return List_Id
5607 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5608 Index_List
: constant List_Id
:= New_List
;
5609 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5610 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5612 procedure Build_Indexes
;
5613 -- Generate the indexes used in the dimension loops
5619 procedure Build_Indexes
is
5621 -- Generate the following identifiers:
5622 -- Jnn - for initialization
5624 for Dim
in 1 .. Num_Dims
loop
5625 Append_To
(Index_List
,
5626 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5632 Final_Decls
: List_Id
:= No_List
;
5633 Final_Data
: Finalization_Exception_Data
;
5637 Core_Loop
: Node_Id
;
5640 Loop_Id
: Entity_Id
;
5643 -- Start of processing for Build_Adjust_Or_Finalize_Statements
5646 Final_Decls
:= New_List
;
5649 Build_Object_Declarations
(Final_Data
, Final_Decls
, Loc
);
5652 Make_Indexed_Component
(Loc
,
5653 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5654 Expressions
=> New_References_To
(Index_List
, Loc
));
5655 Set_Etype
(Comp_Ref
, Comp_Typ
);
5658 -- [Deep_]Adjust (V (J1, ..., JN))
5660 if Prim
= Adjust_Case
then
5661 Call
:= Make_Adjust_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5664 -- [Deep_]Finalize (V (J1, ..., JN))
5666 else pragma Assert
(Prim
= Finalize_Case
);
5667 Call
:= Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5670 if Present
(Call
) then
5672 -- Generate the block which houses the adjust or finalize call:
5675 -- <adjust or finalize call>
5679 -- if not Raised then
5681 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5685 if Exceptions_OK
then
5687 Make_Block_Statement
(Loc
,
5688 Handled_Statement_Sequence
=>
5689 Make_Handled_Sequence_Of_Statements
(Loc
,
5690 Statements
=> New_List
(Call
),
5691 Exception_Handlers
=> New_List
(
5692 Build_Exception_Handler
(Final_Data
))));
5697 -- Generate the dimension loops starting from the innermost one
5699 -- for Jnn in [reverse] V'Range (Dim) loop
5703 J
:= Last
(Index_List
);
5705 while Present
(J
) and then Dim
> 0 loop
5711 Make_Loop_Statement
(Loc
,
5713 Make_Iteration_Scheme
(Loc
,
5714 Loop_Parameter_Specification
=>
5715 Make_Loop_Parameter_Specification
(Loc
,
5716 Defining_Identifier
=> Loop_Id
,
5717 Discrete_Subtype_Definition
=>
5718 Make_Attribute_Reference
(Loc
,
5719 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5720 Attribute_Name
=> Name_Range
,
5721 Expressions
=> New_List
(
5722 Make_Integer_Literal
(Loc
, Dim
))),
5725 Prim
= Finalize_Case
)),
5727 Statements
=> New_List
(Core_Loop
),
5728 End_Label
=> Empty
);
5733 -- Generate the block which contains the core loop, declarations
5734 -- of the abort flag, the exception occurrence, the raised flag
5735 -- and the conditional raise:
5738 -- Abort : constant Boolean := Triggered_By_Abort;
5740 -- Abort : constant Boolean := False; -- no abort
5742 -- E : Exception_Occurrence;
5743 -- Raised : Boolean := False;
5748 -- if Raised and then not Abort then
5749 -- Raise_From_Controlled_Operation (E);
5753 Stmts
:= New_List
(Core_Loop
);
5755 if Exceptions_OK
then
5756 Append_To
(Stmts
, Build_Raise_Statement
(Final_Data
));
5760 Make_Block_Statement
(Loc
,
5761 Declarations
=> Final_Decls
,
5762 Handled_Statement_Sequence
=>
5763 Make_Handled_Sequence_Of_Statements
(Loc
,
5764 Statements
=> Stmts
));
5766 -- Otherwise previous errors or a missing full view may prevent the
5767 -- proper freezing of the component type. If this is the case, there
5768 -- is no [Deep_]Adjust or [Deep_]Finalize primitive to call.
5771 Block
:= Make_Null_Statement
(Loc
);
5774 return New_List
(Block
);
5775 end Build_Adjust_Or_Finalize_Statements
;
5777 ---------------------------------
5778 -- Build_Initialize_Statements --
5779 ---------------------------------
5781 function Build_Initialize_Statements
(Typ
: Entity_Id
) return List_Id
is
5782 Comp_Typ
: constant Entity_Id
:= Component_Type
(Typ
);
5783 Final_List
: constant List_Id
:= New_List
;
5784 Index_List
: constant List_Id
:= New_List
;
5785 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
5786 Num_Dims
: constant Int
:= Number_Dimensions
(Typ
);
5788 function Build_Assignment
(Counter_Id
: Entity_Id
) return Node_Id
;
5789 -- Generate the following assignment:
5790 -- Counter := V'Length (1) *
5792 -- V'Length (N) - Counter;
5794 -- Counter_Id denotes the entity of the counter.
5796 function Build_Finalization_Call
return Node_Id
;
5797 -- Generate a deep finalization call for an array element
5799 procedure Build_Indexes
;
5800 -- Generate the initialization and finalization indexes used in the
5803 function Build_Initialization_Call
return Node_Id
;
5804 -- Generate a deep initialization call for an array element
5806 ----------------------
5807 -- Build_Assignment --
5808 ----------------------
5810 function Build_Assignment
(Counter_Id
: Entity_Id
) return Node_Id
is
5815 -- Start from the first dimension and generate:
5820 Make_Attribute_Reference
(Loc
,
5821 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5822 Attribute_Name
=> Name_Length
,
5823 Expressions
=> New_List
(Make_Integer_Literal
(Loc
, Dim
)));
5825 -- Process the rest of the dimensions, generate:
5826 -- Expr * V'Length (N)
5829 while Dim
<= Num_Dims
loop
5831 Make_Op_Multiply
(Loc
,
5834 Make_Attribute_Reference
(Loc
,
5835 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5836 Attribute_Name
=> Name_Length
,
5837 Expressions
=> New_List
(
5838 Make_Integer_Literal
(Loc
, Dim
))));
5844 -- Counter := Expr - Counter;
5847 Make_Assignment_Statement
(Loc
,
5848 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5850 Make_Op_Subtract
(Loc
,
5852 Right_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
)));
5853 end Build_Assignment
;
5855 -----------------------------
5856 -- Build_Finalization_Call --
5857 -----------------------------
5859 function Build_Finalization_Call
return Node_Id
is
5860 Comp_Ref
: constant Node_Id
:=
5861 Make_Indexed_Component
(Loc
,
5862 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5863 Expressions
=> New_References_To
(Final_List
, Loc
));
5866 Set_Etype
(Comp_Ref
, Comp_Typ
);
5869 -- [Deep_]Finalize (V);
5871 return Make_Final_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5872 end Build_Finalization_Call
;
5878 procedure Build_Indexes
is
5880 -- Generate the following identifiers:
5881 -- Jnn - for initialization
5882 -- Fnn - for finalization
5884 for Dim
in 1 .. Num_Dims
loop
5885 Append_To
(Index_List
,
5886 Make_Defining_Identifier
(Loc
, New_External_Name
('J', Dim
)));
5888 Append_To
(Final_List
,
5889 Make_Defining_Identifier
(Loc
, New_External_Name
('F', Dim
)));
5893 -------------------------------
5894 -- Build_Initialization_Call --
5895 -------------------------------
5897 function Build_Initialization_Call
return Node_Id
is
5898 Comp_Ref
: constant Node_Id
:=
5899 Make_Indexed_Component
(Loc
,
5900 Prefix
=> Make_Identifier
(Loc
, Name_V
),
5901 Expressions
=> New_References_To
(Index_List
, Loc
));
5904 Set_Etype
(Comp_Ref
, Comp_Typ
);
5907 -- [Deep_]Initialize (V (J1, ..., JN));
5909 return Make_Init_Call
(Obj_Ref
=> Comp_Ref
, Typ
=> Comp_Typ
);
5910 end Build_Initialization_Call
;
5914 Counter_Id
: Entity_Id
;
5918 Final_Block
: Node_Id
;
5919 Final_Data
: Finalization_Exception_Data
;
5920 Final_Decls
: List_Id
:= No_List
;
5921 Final_Loop
: Node_Id
;
5922 Init_Block
: Node_Id
;
5923 Init_Call
: Node_Id
;
5924 Init_Loop
: Node_Id
;
5929 -- Start of processing for Build_Initialize_Statements
5932 Counter_Id
:= Make_Temporary
(Loc
, 'C');
5933 Final_Decls
:= New_List
;
5936 Build_Object_Declarations
(Final_Data
, Final_Decls
, Loc
);
5938 -- Generate the block which houses the finalization call, the index
5939 -- guard and the handler which triggers Program_Error later on.
5941 -- if Counter > 0 then
5942 -- Counter := Counter - 1;
5945 -- [Deep_]Finalize (V (F1, ..., FN));
5948 -- if not Raised then
5950 -- Save_Occurrence (E, Get_Current_Excep.all.all);
5955 Fin_Stmt
:= Build_Finalization_Call
;
5957 if Present
(Fin_Stmt
) then
5958 if Exceptions_OK
then
5960 Make_Block_Statement
(Loc
,
5961 Handled_Statement_Sequence
=>
5962 Make_Handled_Sequence_Of_Statements
(Loc
,
5963 Statements
=> New_List
(Fin_Stmt
),
5964 Exception_Handlers
=> New_List
(
5965 Build_Exception_Handler
(Final_Data
))));
5968 -- This is the core of the loop, the dimension iterators are added
5969 -- one by one in reverse.
5972 Make_If_Statement
(Loc
,
5975 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5976 Right_Opnd
=> Make_Integer_Literal
(Loc
, 0)),
5978 Then_Statements
=> New_List
(
5979 Make_Assignment_Statement
(Loc
,
5980 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5982 Make_Op_Subtract
(Loc
,
5983 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
5984 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1)))),
5986 Else_Statements
=> New_List
(Fin_Stmt
));
5988 -- Generate all finalization loops starting from the innermost
5991 -- for Fnn in reverse V'Range (Dim) loop
5995 F
:= Last
(Final_List
);
5997 while Present
(F
) and then Dim
> 0 loop
6003 Make_Loop_Statement
(Loc
,
6005 Make_Iteration_Scheme
(Loc
,
6006 Loop_Parameter_Specification
=>
6007 Make_Loop_Parameter_Specification
(Loc
,
6008 Defining_Identifier
=> Loop_Id
,
6009 Discrete_Subtype_Definition
=>
6010 Make_Attribute_Reference
(Loc
,
6011 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6012 Attribute_Name
=> Name_Range
,
6013 Expressions
=> New_List
(
6014 Make_Integer_Literal
(Loc
, Dim
))),
6016 Reverse_Present
=> True)),
6018 Statements
=> New_List
(Final_Loop
),
6019 End_Label
=> Empty
);
6024 -- Generate the block which contains the finalization loops, the
6025 -- declarations of the abort flag, the exception occurrence, the
6026 -- raised flag and the conditional raise.
6029 -- Abort : constant Boolean := Triggered_By_Abort;
6031 -- Abort : constant Boolean := False; -- no abort
6033 -- E : Exception_Occurrence;
6034 -- Raised : Boolean := False;
6040 -- V'Length (N) - Counter;
6044 -- if Raised and then not Abort then
6045 -- Raise_From_Controlled_Operation (E);
6051 Stmts
:= New_List
(Build_Assignment
(Counter_Id
), Final_Loop
);
6053 if Exceptions_OK
then
6054 Append_To
(Stmts
, Build_Raise_Statement
(Final_Data
));
6055 Append_To
(Stmts
, Make_Raise_Statement
(Loc
));
6059 Make_Block_Statement
(Loc
,
6060 Declarations
=> Final_Decls
,
6061 Handled_Statement_Sequence
=>
6062 Make_Handled_Sequence_Of_Statements
(Loc
,
6063 Statements
=> Stmts
));
6065 -- Otherwise previous errors or a missing full view may prevent the
6066 -- proper freezing of the component type. If this is the case, there
6067 -- is no [Deep_]Finalize primitive to call.
6070 Final_Block
:= Make_Null_Statement
(Loc
);
6073 -- Generate the block which contains the initialization call and
6074 -- the partial finalization code.
6077 -- [Deep_]Initialize (V (J1, ..., JN));
6079 -- Counter := Counter + 1;
6083 -- <finalization code>
6086 Init_Call
:= Build_Initialization_Call
;
6088 -- Only create finalization block if there is a nontrivial call
6089 -- to initialization or a Default_Initial_Condition check to be
6092 if (Present
(Init_Call
)
6093 and then Nkind
(Init_Call
) /= N_Null_Statement
)
6096 and then not GNATprove_Mode
6097 and then Present
(DIC_Procedure
(Comp_Typ
))
6098 and then not Has_Null_Body
(DIC_Procedure
(Comp_Typ
)))
6101 Init_Stmts
: constant List_Id
:= New_List
;
6104 if Present
(Init_Call
) then
6105 Append_To
(Init_Stmts
, Init_Call
);
6108 if Has_DIC
(Comp_Typ
)
6109 and then Present
(DIC_Procedure
(Comp_Typ
))
6113 Build_DIC_Call
(Loc
,
6114 Make_Indexed_Component
(Loc
,
6115 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6116 Expressions
=> New_References_To
(Index_List
, Loc
)),
6121 Make_Block_Statement
(Loc
,
6122 Handled_Statement_Sequence
=>
6123 Make_Handled_Sequence_Of_Statements
(Loc
,
6124 Statements
=> Init_Stmts
,
6125 Exception_Handlers
=> New_List
(
6126 Make_Exception_Handler
(Loc
,
6127 Exception_Choices
=> New_List
(
6128 Make_Others_Choice
(Loc
)),
6129 Statements
=> New_List
(Final_Block
)))));
6132 Append_To
(Statements
(Handled_Statement_Sequence
(Init_Loop
)),
6133 Make_Assignment_Statement
(Loc
,
6134 Name
=> New_Occurrence_Of
(Counter_Id
, Loc
),
6137 Left_Opnd
=> New_Occurrence_Of
(Counter_Id
, Loc
),
6138 Right_Opnd
=> Make_Integer_Literal
(Loc
, 1))));
6140 -- Generate all initialization loops starting from the innermost
6143 -- for Jnn in V'Range (Dim) loop
6147 J
:= Last
(Index_List
);
6149 while Present
(J
) and then Dim
> 0 loop
6155 Make_Loop_Statement
(Loc
,
6157 Make_Iteration_Scheme
(Loc
,
6158 Loop_Parameter_Specification
=>
6159 Make_Loop_Parameter_Specification
(Loc
,
6160 Defining_Identifier
=> Loop_Id
,
6161 Discrete_Subtype_Definition
=>
6162 Make_Attribute_Reference
(Loc
,
6163 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6164 Attribute_Name
=> Name_Range
,
6165 Expressions
=> New_List
(
6166 Make_Integer_Literal
(Loc
, Dim
))))),
6168 Statements
=> New_List
(Init_Loop
),
6169 End_Label
=> Empty
);
6174 -- Generate the block which contains the counter variable and the
6175 -- initialization loops.
6178 -- Counter : Integer := 0;
6184 Make_Block_Statement
(Loc
,
6185 Declarations
=> New_List
(
6186 Make_Object_Declaration
(Loc
,
6187 Defining_Identifier
=> Counter_Id
,
6188 Object_Definition
=>
6189 New_Occurrence_Of
(Standard_Integer
, Loc
),
6190 Expression
=> Make_Integer_Literal
(Loc
, 0))),
6192 Handled_Statement_Sequence
=>
6193 Make_Handled_Sequence_Of_Statements
(Loc
,
6194 Statements
=> New_List
(Init_Loop
)));
6196 if Debug_Generated_Code
then
6197 Set_Debug_Info_Needed
(Counter_Id
);
6200 -- Otherwise previous errors or a missing full view may prevent the
6201 -- proper freezing of the component type. If this is the case, there
6202 -- is no [Deep_]Initialize primitive to call.
6205 Init_Block
:= Make_Null_Statement
(Loc
);
6208 return New_List
(Init_Block
);
6209 end Build_Initialize_Statements
;
6211 -----------------------
6212 -- New_References_To --
6213 -----------------------
6215 function New_References_To
6217 Loc
: Source_Ptr
) return List_Id
6219 Refs
: constant List_Id
:= New_List
;
6224 while Present
(Id
) loop
6225 Append_To
(Refs
, New_Occurrence_Of
(Id
, Loc
));
6230 end New_References_To
;
6232 -- Start of processing for Make_Deep_Array_Body
6236 when Address_Case
=>
6237 return Make_Finalize_Address_Stmts
(Typ
);
6242 return Build_Adjust_Or_Finalize_Statements
(Typ
);
6244 when Initialize_Case
=>
6245 return Build_Initialize_Statements
(Typ
);
6247 end Make_Deep_Array_Body
;
6249 --------------------
6250 -- Make_Deep_Proc --
6251 --------------------
6253 function Make_Deep_Proc
6254 (Prim
: Final_Primitives
;
6256 Stmts
: List_Id
) return Entity_Id
6258 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6260 Proc_Id
: Entity_Id
;
6263 -- Create the object formal, generate:
6264 -- V : System.Address
6266 if Prim
= Address_Case
then
6267 Formals
:= New_List
(
6268 Make_Parameter_Specification
(Loc
,
6269 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
6271 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)));
6278 Formals
:= New_List
(
6279 Make_Parameter_Specification
(Loc
,
6280 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
6282 Out_Present
=> True,
6283 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
)));
6285 -- F : Boolean := True
6287 if Prim
= Adjust_Case
6288 or else Prim
= Finalize_Case
6291 Make_Parameter_Specification
(Loc
,
6292 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
6294 New_Occurrence_Of
(Standard_Boolean
, Loc
),
6296 New_Occurrence_Of
(Standard_True
, Loc
)));
6301 Make_Defining_Identifier
(Loc
,
6302 Chars
=> Make_TSS_Name
(Typ
, Deep_Name_Of
(Prim
)));
6305 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
6308 -- exception -- Finalize and Adjust cases only
6309 -- raise Program_Error;
6310 -- end Deep_Initialize / Adjust / Finalize;
6314 -- procedure Finalize_Address (V : System.Address) is
6317 -- end Finalize_Address;
6320 Make_Subprogram_Body
(Loc
,
6322 Make_Procedure_Specification
(Loc
,
6323 Defining_Unit_Name
=> Proc_Id
,
6324 Parameter_Specifications
=> Formals
),
6326 Declarations
=> Empty_List
,
6328 Handled_Statement_Sequence
=>
6329 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Stmts
)));
6331 -- If there are no calls to component initialization, indicate that
6332 -- the procedure is trivial, so prevent calls to it.
6334 if Is_Empty_List
(Stmts
)
6335 or else Nkind
(First
(Stmts
)) = N_Null_Statement
6337 Set_Is_Trivial_Subprogram
(Proc_Id
);
6343 ---------------------------
6344 -- Make_Deep_Record_Body --
6345 ---------------------------
6347 function Make_Deep_Record_Body
6348 (Prim
: Final_Primitives
;
6350 Is_Local
: Boolean := False) return List_Id
6352 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
;
6353 -- Build the statements necessary to adjust a record type. The type may
6354 -- have discriminants and contain variant parts. Generate:
6358 -- [Deep_]Adjust (V.Comp_1);
6360 -- when Id : others =>
6361 -- if not Raised then
6363 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6368 -- [Deep_]Adjust (V.Comp_N);
6370 -- when Id : others =>
6371 -- if not Raised then
6373 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6378 -- Deep_Adjust (V._parent, False); -- If applicable
6380 -- when Id : others =>
6381 -- if not Raised then
6383 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6389 -- Adjust (V); -- If applicable
6392 -- if not Raised then
6394 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6399 -- if Raised and then not Abort then
6400 -- Raise_From_Controlled_Operation (E);
6404 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
;
6405 -- Build the statements necessary to finalize a record type. The type
6406 -- may have discriminants and contain variant parts. Generate:
6409 -- Abort : constant Boolean := Triggered_By_Abort;
6411 -- Abort : constant Boolean := False; -- no abort
6412 -- E : Exception_Occurrence;
6413 -- Raised : Boolean := False;
6418 -- Finalize (V); -- If applicable
6421 -- if not Raised then
6423 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6428 -- case Variant_1 is
6430 -- case State_Counter_N => -- If Is_Local is enabled
6440 -- <<LN>> -- If Is_Local is enabled
6442 -- [Deep_]Finalize (V.Comp_N);
6445 -- if not Raised then
6447 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6453 -- [Deep_]Finalize (V.Comp_1);
6456 -- if not Raised then
6458 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6464 -- case State_Counter_1 => -- If Is_Local is enabled
6470 -- Deep_Finalize (V._parent, False); -- If applicable
6472 -- when Id : others =>
6473 -- if not Raised then
6475 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6479 -- if Raised and then not Abort then
6480 -- Raise_From_Controlled_Operation (E);
6484 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
;
6485 -- Given a derived tagged type Typ, traverse all components, find field
6486 -- _parent and return its type.
6488 procedure Preprocess_Components
6490 Num_Comps
: out Nat
;
6491 Has_POC
: out Boolean);
6492 -- Examine all components in component list Comps, count all controlled
6493 -- components and determine whether at least one of them is per-object
6494 -- constrained. Component _parent is always skipped.
6496 -----------------------------
6497 -- Build_Adjust_Statements --
6498 -----------------------------
6500 function Build_Adjust_Statements
(Typ
: Entity_Id
) return List_Id
is
6501 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6502 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
6504 Finalizer_Data
: Finalization_Exception_Data
;
6506 function Process_Component_List_For_Adjust
6507 (Comps
: Node_Id
) return List_Id
;
6508 -- Build all necessary adjust statements for a single component list
6510 ---------------------------------------
6511 -- Process_Component_List_For_Adjust --
6512 ---------------------------------------
6514 function Process_Component_List_For_Adjust
6515 (Comps
: Node_Id
) return List_Id
6517 Stmts
: constant List_Id
:= New_List
;
6519 procedure Process_Component_For_Adjust
(Decl
: Node_Id
);
6520 -- Process the declaration of a single controlled component
6522 ----------------------------------
6523 -- Process_Component_For_Adjust --
6524 ----------------------------------
6526 procedure Process_Component_For_Adjust
(Decl
: Node_Id
) is
6527 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
6528 Typ
: constant Entity_Id
:= Etype
(Id
);
6534 -- [Deep_]Adjust (V.Id);
6538 -- if not Raised then
6540 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6547 Make_Selected_Component
(Loc
,
6548 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6549 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
6552 -- Guard against a missing [Deep_]Adjust when the component
6553 -- type was not properly frozen.
6555 if Present
(Adj_Call
) then
6556 if Exceptions_OK
then
6558 Make_Block_Statement
(Loc
,
6559 Handled_Statement_Sequence
=>
6560 Make_Handled_Sequence_Of_Statements
(Loc
,
6561 Statements
=> New_List
(Adj_Call
),
6562 Exception_Handlers
=> New_List
(
6563 Build_Exception_Handler
(Finalizer_Data
))));
6566 Append_To
(Stmts
, Adj_Call
);
6568 end Process_Component_For_Adjust
;
6573 Decl_Id
: Entity_Id
;
6574 Decl_Typ
: Entity_Id
;
6579 -- Start of processing for Process_Component_List_For_Adjust
6582 -- Perform an initial check, determine the number of controlled
6583 -- components in the current list and whether at least one of them
6584 -- is per-object constrained.
6586 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
6588 -- The processing in this routine is done in the following order:
6589 -- 1) Regular components
6590 -- 2) Per-object constrained components
6593 if Num_Comps
> 0 then
6595 -- Process all regular components in order of declarations
6597 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6598 while Present
(Decl
) loop
6599 Decl_Id
:= Defining_Identifier
(Decl
);
6600 Decl_Typ
:= Etype
(Decl_Id
);
6602 -- Skip _parent as well as per-object constrained components
6604 if Chars
(Decl_Id
) /= Name_uParent
6605 and then Needs_Finalization
(Decl_Typ
)
6607 if Has_Access_Constraint
(Decl_Id
)
6608 and then No
(Expression
(Decl
))
6612 Process_Component_For_Adjust
(Decl
);
6616 Next_Non_Pragma
(Decl
);
6619 -- Process all per-object constrained components in order of
6623 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
6624 while Present
(Decl
) loop
6625 Decl_Id
:= Defining_Identifier
(Decl
);
6626 Decl_Typ
:= Etype
(Decl_Id
);
6630 if Chars
(Decl_Id
) /= Name_uParent
6631 and then Needs_Finalization
(Decl_Typ
)
6632 and then Has_Access_Constraint
(Decl_Id
)
6633 and then No
(Expression
(Decl
))
6635 Process_Component_For_Adjust
(Decl
);
6638 Next_Non_Pragma
(Decl
);
6643 -- Process all variants, if any
6646 if Present
(Variant_Part
(Comps
)) then
6648 Var_Alts
: constant List_Id
:= New_List
;
6652 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
6653 while Present
(Var
) loop
6656 -- when <discrete choices> =>
6657 -- <adjust statements>
6659 Append_To
(Var_Alts
,
6660 Make_Case_Statement_Alternative
(Loc
,
6662 New_Copy_List
(Discrete_Choices
(Var
)),
6664 Process_Component_List_For_Adjust
(
6665 Component_List
(Var
))));
6667 Next_Non_Pragma
(Var
);
6671 -- case V.<discriminant> is
6672 -- when <discrete choices 1> =>
6673 -- <adjust statements 1>
6675 -- when <discrete choices N> =>
6676 -- <adjust statements N>
6680 Make_Case_Statement
(Loc
,
6682 Make_Selected_Component
(Loc
,
6683 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6685 Make_Identifier
(Loc
,
6686 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
6687 Alternatives
=> Var_Alts
);
6691 -- Add the variant case statement to the list of statements
6693 if Present
(Var_Case
) then
6694 Append_To
(Stmts
, Var_Case
);
6697 -- If the component list did not have any controlled components
6698 -- nor variants, return null.
6700 if Is_Empty_List
(Stmts
) then
6701 Append_To
(Stmts
, Make_Null_Statement
(Loc
));
6705 end Process_Component_List_For_Adjust
;
6709 Bod_Stmts
: List_Id
:= No_List
;
6710 Finalizer_Decls
: List_Id
:= No_List
;
6713 -- Start of processing for Build_Adjust_Statements
6716 Finalizer_Decls
:= New_List
;
6717 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
6719 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
6720 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
6725 -- Create an adjust sequence for all record components
6727 if Present
(Component_List
(Rec_Def
)) then
6729 Process_Component_List_For_Adjust
(Component_List
(Rec_Def
));
6732 -- A derived record type must adjust all inherited components. This
6733 -- action poses the following problem:
6735 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
6740 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
6742 -- Deep_Adjust (Obj._parent);
6747 -- Adjusting the derived type will invoke Adjust of the parent and
6748 -- then that of the derived type. This is undesirable because both
6749 -- routines may modify shared components. Only the Adjust of the
6750 -- derived type should be invoked.
6752 -- To prevent this double adjustment of shared components,
6753 -- Deep_Adjust uses a flag to control the invocation of Adjust:
6755 -- procedure Deep_Adjust
6756 -- (Obj : in out Some_Type;
6757 -- Flag : Boolean := True)
6765 -- When Deep_Adjust is invoked for field _parent, a value of False is
6766 -- provided for the flag:
6768 -- Deep_Adjust (Obj._parent, False);
6770 if Is_Tagged_Type
(Typ
) and then Is_Derived_Type
(Typ
) then
6772 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
6777 if Needs_Finalization
(Par_Typ
) then
6781 Make_Selected_Component
(Loc
,
6782 Prefix
=> Make_Identifier
(Loc
, Name_V
),
6784 Make_Identifier
(Loc
, Name_uParent
)),
6790 -- Deep_Adjust (V._parent, False);
6793 -- when Id : others =>
6794 -- if not Raised then
6796 -- Save_Occurrence (E,
6797 -- Get_Current_Excep.all.all);
6801 if Present
(Call
) then
6804 if Exceptions_OK
then
6806 Make_Block_Statement
(Loc
,
6807 Handled_Statement_Sequence
=>
6808 Make_Handled_Sequence_Of_Statements
(Loc
,
6809 Statements
=> New_List
(Adj_Stmt
),
6810 Exception_Handlers
=> New_List
(
6811 Build_Exception_Handler
(Finalizer_Data
))));
6814 Prepend_To
(Bod_Stmts
, Adj_Stmt
);
6820 -- Adjust the object. This action must be performed last after all
6821 -- components have been adjusted.
6823 if Is_Controlled
(Typ
) then
6829 Proc
:= Find_Optional_Prim_Op
(Typ
, Name_Adjust
);
6838 -- if not Raised then
6840 -- Save_Occurrence (E,
6841 -- Get_Current_Excep.all.all);
6846 if Present
(Proc
) then
6848 Make_Procedure_Call_Statement
(Loc
,
6849 Name
=> New_Occurrence_Of
(Proc
, Loc
),
6850 Parameter_Associations
=> New_List
(
6851 Make_Identifier
(Loc
, Name_V
)));
6853 if Exceptions_OK
then
6855 Make_Block_Statement
(Loc
,
6856 Handled_Statement_Sequence
=>
6857 Make_Handled_Sequence_Of_Statements
(Loc
,
6858 Statements
=> New_List
(Adj_Stmt
),
6859 Exception_Handlers
=> New_List
(
6860 Build_Exception_Handler
6861 (Finalizer_Data
))));
6864 Append_To
(Bod_Stmts
,
6865 Make_If_Statement
(Loc
,
6866 Condition
=> Make_Identifier
(Loc
, Name_F
),
6867 Then_Statements
=> New_List
(Adj_Stmt
)));
6872 -- At this point either all adjustment statements have been generated
6873 -- or the type is not controlled.
6875 if Is_Empty_List
(Bod_Stmts
) then
6876 Append_To
(Bod_Stmts
, Make_Null_Statement
(Loc
));
6882 -- Abort : constant Boolean := Triggered_By_Abort;
6884 -- Abort : constant Boolean := False; -- no abort
6886 -- E : Exception_Occurrence;
6887 -- Raised : Boolean := False;
6890 -- <adjust statements>
6892 -- if Raised and then not Abort then
6893 -- Raise_From_Controlled_Operation (E);
6898 if Exceptions_OK
then
6899 Append_To
(Bod_Stmts
, Build_Raise_Statement
(Finalizer_Data
));
6904 Make_Block_Statement
(Loc
,
6907 Handled_Statement_Sequence
=>
6908 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
6910 end Build_Adjust_Statements
;
6912 -------------------------------
6913 -- Build_Finalize_Statements --
6914 -------------------------------
6916 function Build_Finalize_Statements
(Typ
: Entity_Id
) return List_Id
is
6917 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
6918 Typ_Def
: constant Node_Id
:= Type_Definition
(Parent
(Typ
));
6921 Finalizer_Data
: Finalization_Exception_Data
;
6922 Last_POC_Call
: Node_Id
:= Empty
;
6924 function Process_Component_List_For_Finalize
6926 In_Variant_Part
: Boolean := False) return List_Id
;
6927 -- Build all necessary finalization statements for a single component
6928 -- list. The statements may include a jump circuitry if flag Is_Local
6929 -- is enabled. In_Variant_Part indicates whether this is a recursive
6932 -----------------------------------------
6933 -- Process_Component_List_For_Finalize --
6934 -----------------------------------------
6936 function Process_Component_List_For_Finalize
6938 In_Variant_Part
: Boolean := False) return List_Id
6940 procedure Process_Component_For_Finalize
6945 Num_Comps
: in out Nat
);
6946 -- Process the declaration of a single controlled component. If
6947 -- flag Is_Local is enabled, create the corresponding label and
6948 -- jump circuitry. Alts is the list of case alternatives, Decls
6949 -- is the top level declaration list where labels are declared
6950 -- and Stmts is the list of finalization actions. Num_Comps
6951 -- denotes the current number of components needing finalization.
6953 ------------------------------------
6954 -- Process_Component_For_Finalize --
6955 ------------------------------------
6957 procedure Process_Component_For_Finalize
6962 Num_Comps
: in out Nat
)
6964 Id
: constant Entity_Id
:= Defining_Identifier
(Decl
);
6965 Typ
: constant Entity_Id
:= Etype
(Id
);
6972 Label_Id
: Entity_Id
;
6979 Make_Identifier
(Loc
,
6980 Chars
=> New_External_Name
('L', Num_Comps
));
6981 Set_Entity
(Label_Id
,
6982 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
6983 Label
:= Make_Label
(Loc
, Label_Id
);
6986 Make_Implicit_Label_Declaration
(Loc
,
6987 Defining_Identifier
=> Entity
(Label_Id
),
6988 Label_Construct
=> Label
));
6995 Make_Case_Statement_Alternative
(Loc
,
6996 Discrete_Choices
=> New_List
(
6997 Make_Integer_Literal
(Loc
, Num_Comps
)),
6999 Statements
=> New_List
(
7000 Make_Goto_Statement
(Loc
,
7002 New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
7007 Append_To
(Stmts
, Label
);
7009 -- Decrease the number of components to be processed.
7010 -- This action yields a new Label_Id in future calls.
7012 Num_Comps
:= Num_Comps
- 1;
7017 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
7019 -- begin -- Exception handlers allowed
7020 -- [Deep_]Finalize (V.Id);
7023 -- if not Raised then
7025 -- Save_Occurrence (E,
7026 -- Get_Current_Excep.all.all);
7033 Make_Selected_Component
(Loc
,
7034 Prefix
=> Make_Identifier
(Loc
, Name_V
),
7035 Selector_Name
=> Make_Identifier
(Loc
, Chars
(Id
))),
7038 -- Guard against a missing [Deep_]Finalize when the component
7039 -- type was not properly frozen.
7041 if Present
(Fin_Call
) then
7042 if Exceptions_OK
then
7044 Make_Block_Statement
(Loc
,
7045 Handled_Statement_Sequence
=>
7046 Make_Handled_Sequence_Of_Statements
(Loc
,
7047 Statements
=> New_List
(Fin_Call
),
7048 Exception_Handlers
=> New_List
(
7049 Build_Exception_Handler
(Finalizer_Data
))));
7052 Append_To
(Stmts
, Fin_Call
);
7054 end Process_Component_For_Finalize
;
7059 Counter_Id
: Entity_Id
:= Empty
;
7061 Decl_Id
: Entity_Id
;
7062 Decl_Typ
: Entity_Id
;
7065 Jump_Block
: Node_Id
;
7067 Label_Id
: Entity_Id
;
7072 -- Start of processing for Process_Component_List_For_Finalize
7075 -- Perform an initial check, look for controlled and per-object
7076 -- constrained components.
7078 Preprocess_Components
(Comps
, Num_Comps
, Has_POC
);
7080 -- Create a state counter to service the current component list.
7081 -- This step is performed before the variants are inspected in
7082 -- order to generate the same state counter names as those from
7083 -- Build_Initialize_Statements.
7085 if Num_Comps
> 0 and then Is_Local
then
7086 Counter
:= Counter
+ 1;
7089 Make_Defining_Identifier
(Loc
,
7090 Chars
=> New_External_Name
('C', Counter
));
7093 -- Process the component in the following order:
7095 -- 2) Per-object constrained components
7096 -- 3) Regular components
7098 -- Start with the variant parts
7101 if Present
(Variant_Part
(Comps
)) then
7103 Var_Alts
: constant List_Id
:= New_List
;
7107 Var
:= First_Non_Pragma
(Variants
(Variant_Part
(Comps
)));
7108 while Present
(Var
) loop
7111 -- when <discrete choices> =>
7112 -- <finalize statements>
7114 Append_To
(Var_Alts
,
7115 Make_Case_Statement_Alternative
(Loc
,
7117 New_Copy_List
(Discrete_Choices
(Var
)),
7119 Process_Component_List_For_Finalize
(
7120 Component_List
(Var
),
7121 In_Variant_Part
=> True)));
7123 Next_Non_Pragma
(Var
);
7127 -- case V.<discriminant> is
7128 -- when <discrete choices 1> =>
7129 -- <finalize statements 1>
7131 -- when <discrete choices N> =>
7132 -- <finalize statements N>
7136 Make_Case_Statement
(Loc
,
7138 Make_Selected_Component
(Loc
,
7139 Prefix
=> Make_Identifier
(Loc
, Name_V
),
7141 Make_Identifier
(Loc
,
7142 Chars
=> Chars
(Name
(Variant_Part
(Comps
))))),
7143 Alternatives
=> Var_Alts
);
7147 -- The current component list does not have a single controlled
7148 -- component, however it may contain variants. Return the case
7149 -- statement for the variants or nothing.
7151 if Num_Comps
= 0 then
7152 if Present
(Var_Case
) then
7153 return New_List
(Var_Case
);
7155 return New_List
(Make_Null_Statement
(Loc
));
7159 -- Prepare all lists
7165 -- Process all per-object constrained components in reverse order
7168 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
7169 while Present
(Decl
) loop
7170 Decl_Id
:= Defining_Identifier
(Decl
);
7171 Decl_Typ
:= Etype
(Decl_Id
);
7175 if Chars
(Decl_Id
) /= Name_uParent
7176 and then Needs_Finalization
(Decl_Typ
)
7177 and then Has_Access_Constraint
(Decl_Id
)
7178 and then No
(Expression
(Decl
))
7180 Process_Component_For_Finalize
7181 (Decl
, Alts
, Decls
, Stmts
, Num_Comps
);
7184 Prev_Non_Pragma
(Decl
);
7188 if not In_Variant_Part
then
7189 Last_POC_Call
:= Last
(Stmts
);
7190 -- In the case of a type extension, the deep-finalize call
7191 -- for the _Parent component will be inserted here.
7194 -- Process the rest of the components in reverse order
7196 Decl
:= Last_Non_Pragma
(Component_Items
(Comps
));
7197 while Present
(Decl
) loop
7198 Decl_Id
:= Defining_Identifier
(Decl
);
7199 Decl_Typ
:= Etype
(Decl_Id
);
7203 if Chars
(Decl_Id
) /= Name_uParent
7204 and then Needs_Finalization
(Decl_Typ
)
7206 -- Skip per-object constrained components since they were
7207 -- handled in the above step.
7209 if Has_Access_Constraint
(Decl_Id
)
7210 and then No
(Expression
(Decl
))
7214 Process_Component_For_Finalize
7215 (Decl
, Alts
, Decls
, Stmts
, Num_Comps
);
7219 Prev_Non_Pragma
(Decl
);
7224 -- LN : label; -- If Is_Local is enabled
7229 -- case CounterX is .
7239 -- <<LN>> -- If Is_Local is enabled
7241 -- [Deep_]Finalize (V.CompY);
7243 -- when Id : others =>
7244 -- if not Raised then
7246 -- Save_Occurrence (E,
7247 -- Get_Current_Excep.all.all);
7251 -- <<L0>> -- If Is_Local is enabled
7256 -- Add the declaration of default jump location L0, its
7257 -- corresponding alternative and its place in the statements.
7259 Label_Id
:= Make_Identifier
(Loc
, New_External_Name
('L', 0));
7260 Set_Entity
(Label_Id
,
7261 Make_Defining_Identifier
(Loc
, Chars
(Label_Id
)));
7262 Label
:= Make_Label
(Loc
, Label_Id
);
7264 Append_To
(Decls
, -- declaration
7265 Make_Implicit_Label_Declaration
(Loc
,
7266 Defining_Identifier
=> Entity
(Label_Id
),
7267 Label_Construct
=> Label
));
7269 Append_To
(Alts
, -- alternative
7270 Make_Case_Statement_Alternative
(Loc
,
7271 Discrete_Choices
=> New_List
(
7272 Make_Others_Choice
(Loc
)),
7274 Statements
=> New_List
(
7275 Make_Goto_Statement
(Loc
,
7276 Name
=> New_Occurrence_Of
(Entity
(Label_Id
), Loc
)))));
7278 Append_To
(Stmts
, Label
); -- statement
7280 -- Create the jump block
7283 Make_Case_Statement
(Loc
,
7284 Expression
=> Make_Identifier
(Loc
, Chars
(Counter_Id
)),
7285 Alternatives
=> Alts
));
7289 Make_Block_Statement
(Loc
,
7290 Declarations
=> Decls
,
7291 Handled_Statement_Sequence
=>
7292 Make_Handled_Sequence_Of_Statements
(Loc
, Stmts
));
7294 if Present
(Var_Case
) then
7295 return New_List
(Var_Case
, Jump_Block
);
7297 return New_List
(Jump_Block
);
7299 end Process_Component_List_For_Finalize
;
7303 Bod_Stmts
: List_Id
:= No_List
;
7304 Finalizer_Decls
: List_Id
:= No_List
;
7307 -- Start of processing for Build_Finalize_Statements
7310 Finalizer_Decls
:= New_List
;
7311 Build_Object_Declarations
(Finalizer_Data
, Finalizer_Decls
, Loc
);
7313 if Nkind
(Typ_Def
) = N_Derived_Type_Definition
then
7314 Rec_Def
:= Record_Extension_Part
(Typ_Def
);
7319 -- Create a finalization sequence for all record components
7321 if Present
(Component_List
(Rec_Def
)) then
7323 Process_Component_List_For_Finalize
(Component_List
(Rec_Def
));
7326 -- A derived record type must finalize all inherited components. This
7327 -- action poses the following problem:
7329 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
7334 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
7336 -- Deep_Finalize (Obj._parent);
7341 -- Finalizing the derived type will invoke Finalize of the parent and
7342 -- then that of the derived type. This is undesirable because both
7343 -- routines may modify shared components. Only the Finalize of the
7344 -- derived type should be invoked.
7346 -- To prevent this double adjustment of shared components,
7347 -- Deep_Finalize uses a flag to control the invocation of Finalize:
7349 -- procedure Deep_Finalize
7350 -- (Obj : in out Some_Type;
7351 -- Flag : Boolean := True)
7359 -- When Deep_Finalize is invoked for field _parent, a value of False
7360 -- is provided for the flag:
7362 -- Deep_Finalize (Obj._parent, False);
7364 if Is_Tagged_Type
(Typ
) and then Is_Derived_Type
(Typ
) then
7366 Par_Typ
: constant Entity_Id
:= Parent_Field_Type
(Typ
);
7371 if Needs_Finalization
(Par_Typ
) then
7375 Make_Selected_Component
(Loc
,
7376 Prefix
=> Make_Identifier
(Loc
, Name_V
),
7378 Make_Identifier
(Loc
, Name_uParent
)),
7384 -- Deep_Finalize (V._parent, False);
7387 -- when Id : others =>
7388 -- if not Raised then
7390 -- Save_Occurrence (E,
7391 -- Get_Current_Excep.all.all);
7395 if Present
(Call
) then
7398 if Exceptions_OK
then
7400 Make_Block_Statement
(Loc
,
7401 Handled_Statement_Sequence
=>
7402 Make_Handled_Sequence_Of_Statements
(Loc
,
7403 Statements
=> New_List
(Fin_Stmt
),
7404 Exception_Handlers
=> New_List
(
7405 Build_Exception_Handler
7406 (Finalizer_Data
))));
7409 -- The intended component finalization order is
7410 -- 1) POC components of extension
7411 -- 2) _Parent component
7412 -- 3) non-POC components of extension.
7414 -- With this "finalize the parent part in the middle"
7415 -- ordering, we can avoid the need for making two
7416 -- calls to the parent's subprogram in the way that
7417 -- is necessary for Init_Procs. This does have the
7418 -- peculiar (but legal) consequence that the parent's
7419 -- non-POC components are finalized before the
7420 -- non-POC extension components. This violates the
7421 -- usual "finalize in reverse declaration order"
7422 -- principle, but that's ok (see RM 7.6.1(9)).
7424 -- Last_POC_Call should be non-empty if the extension
7425 -- has at least one POC. Interactions with variant
7426 -- parts are incorrectly ignored.
7428 if Present
(Last_POC_Call
) then
7429 Insert_After
(Last_POC_Call
, Fin_Stmt
);
7431 -- At this point, we could look for the common case
7432 -- where there are no POC components anywhere in
7433 -- sight (inherited or not) and, in that common case,
7434 -- call Append_To instead of Prepend_To. That would
7435 -- result in finalizing the parent part after, rather
7436 -- than before, the extension components. That might
7437 -- be more intuitive (as discussed in preceding
7438 -- comment), but it is not required.
7439 Prepend_To
(Bod_Stmts
, Fin_Stmt
);
7446 -- Finalize the object. This action must be performed first before
7447 -- all components have been finalized.
7449 if Is_Controlled
(Typ
) and then not Is_Local
then
7455 Proc
:= Find_Optional_Prim_Op
(Typ
, Name_Finalize
);
7464 -- if not Raised then
7466 -- Save_Occurrence (E,
7467 -- Get_Current_Excep.all.all);
7472 if Present
(Proc
) then
7474 Make_Procedure_Call_Statement
(Loc
,
7475 Name
=> New_Occurrence_Of
(Proc
, Loc
),
7476 Parameter_Associations
=> New_List
(
7477 Make_Identifier
(Loc
, Name_V
)));
7479 if Exceptions_OK
then
7481 Make_Block_Statement
(Loc
,
7482 Handled_Statement_Sequence
=>
7483 Make_Handled_Sequence_Of_Statements
(Loc
,
7484 Statements
=> New_List
(Fin_Stmt
),
7485 Exception_Handlers
=> New_List
(
7486 Build_Exception_Handler
7487 (Finalizer_Data
))));
7490 Prepend_To
(Bod_Stmts
,
7491 Make_If_Statement
(Loc
,
7492 Condition
=> Make_Identifier
(Loc
, Name_F
),
7493 Then_Statements
=> New_List
(Fin_Stmt
)));
7498 -- At this point either all finalization statements have been
7499 -- generated or the type is not controlled.
7501 if No
(Bod_Stmts
) then
7502 return New_List
(Make_Null_Statement
(Loc
));
7506 -- Abort : constant Boolean := Triggered_By_Abort;
7508 -- Abort : constant Boolean := False; -- no abort
7510 -- E : Exception_Occurrence;
7511 -- Raised : Boolean := False;
7514 -- <finalize statements>
7516 -- if Raised and then not Abort then
7517 -- Raise_From_Controlled_Operation (E);
7522 if Exceptions_OK
then
7523 Append_To
(Bod_Stmts
, Build_Raise_Statement
(Finalizer_Data
));
7528 Make_Block_Statement
(Loc
,
7531 Handled_Statement_Sequence
=>
7532 Make_Handled_Sequence_Of_Statements
(Loc
, Bod_Stmts
)));
7534 end Build_Finalize_Statements
;
7536 -----------------------
7537 -- Parent_Field_Type --
7538 -----------------------
7540 function Parent_Field_Type
(Typ
: Entity_Id
) return Entity_Id
is
7544 Field
:= First_Entity
(Typ
);
7545 while Present
(Field
) loop
7546 if Chars
(Field
) = Name_uParent
then
7547 return Etype
(Field
);
7550 Next_Entity
(Field
);
7553 -- A derived tagged type should always have a parent field
7555 raise Program_Error
;
7556 end Parent_Field_Type
;
7558 ---------------------------
7559 -- Preprocess_Components --
7560 ---------------------------
7562 procedure Preprocess_Components
7564 Num_Comps
: out Nat
;
7565 Has_POC
: out Boolean)
7575 Decl
:= First_Non_Pragma
(Component_Items
(Comps
));
7576 while Present
(Decl
) loop
7577 Id
:= Defining_Identifier
(Decl
);
7580 -- Skip field _parent
7582 if Chars
(Id
) /= Name_uParent
7583 and then Needs_Finalization
(Typ
)
7585 Num_Comps
:= Num_Comps
+ 1;
7587 if Has_Access_Constraint
(Id
)
7588 and then No
(Expression
(Decl
))
7594 Next_Non_Pragma
(Decl
);
7596 end Preprocess_Components
;
7598 -- Start of processing for Make_Deep_Record_Body
7602 when Address_Case
=>
7603 return Make_Finalize_Address_Stmts
(Typ
);
7606 return Build_Adjust_Statements
(Typ
);
7608 when Finalize_Case
=>
7609 return Build_Finalize_Statements
(Typ
);
7611 when Initialize_Case
=>
7613 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7616 if Is_Controlled
(Typ
) then
7618 Make_Procedure_Call_Statement
(Loc
,
7621 (Find_Prim_Op
(Typ
, Name_Of
(Prim
)), Loc
),
7622 Parameter_Associations
=> New_List
(
7623 Make_Identifier
(Loc
, Name_V
))));
7629 end Make_Deep_Record_Body
;
7631 ----------------------
7632 -- Make_Final_Call --
7633 ----------------------
7635 function Make_Final_Call
7638 Skip_Self
: Boolean := False) return Node_Id
7640 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
7642 Prot_Typ
: Entity_Id
:= Empty
;
7643 Fin_Id
: Entity_Id
:= Empty
;
7650 -- Recover the proper type which contains [Deep_]Finalize
7652 if Is_Class_Wide_Type
(Typ
) then
7653 Utyp
:= Root_Type
(Typ
);
7656 elsif Is_Concurrent_Type
(Typ
) then
7657 Utyp
:= Corresponding_Record_Type
(Typ
);
7659 Ref
:= Convert_Concurrent
(Ref
, Typ
);
7661 elsif Is_Private_Type
(Typ
)
7662 and then Present
(Underlying_Type
(Typ
))
7663 and then Is_Concurrent_Type
(Underlying_Type
(Typ
))
7665 Utyp
:= Corresponding_Record_Type
(Underlying_Type
(Typ
));
7667 Ref
:= Convert_Concurrent
(Ref
, Underlying_Type
(Typ
));
7674 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
7675 Set_Assignment_OK
(Ref
);
7677 -- Deal with untagged derivation of private views. If the parent type
7678 -- is a protected type, Deep_Finalize is found on the corresponding
7679 -- record of the ancestor.
7681 if Is_Untagged_Derivation
(Typ
) then
7682 if Is_Protected_Type
(Typ
) then
7683 Utyp
:= Corresponding_Record_Type
(Root_Type
(Base_Type
(Typ
)));
7685 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
7687 if Is_Protected_Type
(Utyp
) then
7688 Utyp
:= Corresponding_Record_Type
(Utyp
);
7692 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7693 Set_Assignment_OK
(Ref
);
7696 -- Deal with derived private types which do not inherit primitives from
7697 -- their parents. In this case, [Deep_]Finalize can be found in the full
7698 -- view of the parent type.
7701 and then Is_Tagged_Type
(Utyp
)
7702 and then Is_Derived_Type
(Utyp
)
7703 and then Is_Empty_Elmt_List
(Primitive_Operations
(Utyp
))
7704 and then Is_Private_Type
(Etype
(Utyp
))
7705 and then Present
(Full_View
(Etype
(Utyp
)))
7707 Utyp
:= Full_View
(Etype
(Utyp
));
7708 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7709 Set_Assignment_OK
(Ref
);
7712 -- When dealing with the completion of a private type, use the base type
7715 if Present
(Utyp
) and then Utyp
/= Base_Type
(Utyp
) then
7716 pragma Assert
(Present
(Atyp
) and then Is_Private_Type
(Atyp
));
7718 Utyp
:= Base_Type
(Utyp
);
7719 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
7720 Set_Assignment_OK
(Ref
);
7723 -- Detect if Typ is a protected type or an expanded protected type and
7724 -- store the relevant type within Prot_Typ for later processing.
7726 if Is_Protected_Type
(Typ
) then
7729 elsif Ekind
(Typ
) = E_Record_Type
7730 and then Present
(Corresponding_Concurrent_Type
(Typ
))
7731 and then Is_Protected_Type
(Corresponding_Concurrent_Type
(Typ
))
7733 Prot_Typ
:= Corresponding_Concurrent_Type
(Typ
);
7736 -- The underlying type may not be present due to a missing full view. In
7737 -- this case freezing did not take place and there is no [Deep_]Finalize
7738 -- primitive to call.
7743 elsif Skip_Self
then
7744 if Has_Controlled_Component
(Utyp
) then
7745 if Is_Tagged_Type
(Utyp
) then
7746 Fin_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7748 Fin_Id
:= TSS
(Utyp
, TSS_Deep_Finalize
);
7752 -- Class-wide types, interfaces and types with controlled components
7754 elsif Is_Class_Wide_Type
(Typ
)
7755 or else Is_Interface
(Typ
)
7756 or else Has_Controlled_Component
(Utyp
)
7758 if Is_Tagged_Type
(Utyp
) then
7759 Fin_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7761 Fin_Id
:= TSS
(Utyp
, TSS_Deep_Finalize
);
7764 -- Derivations from [Limited_]Controlled
7766 elsif Is_Controlled
(Utyp
) then
7767 Fin_Id
:= Find_Optional_Prim_Op
(Utyp
, Name_Of
(Finalize_Case
));
7771 elsif Is_Tagged_Type
(Utyp
) then
7772 Fin_Id
:= Find_Optional_Prim_Op
(Utyp
, TSS_Deep_Finalize
);
7774 -- Protected types: these also require finalization even though they
7775 -- are not marked controlled explicitly.
7777 elsif Present
(Prot_Typ
) then
7778 -- Protected objects do not need to be finalized on restricted
7781 if Restricted_Profile
then
7784 -- ??? Only handle the simple case for now. Will not support a record
7785 -- or array containing protected objects.
7787 elsif Is_Simple_Protected_Type
(Prot_Typ
) then
7788 Fin_Id
:= RTE
(RE_Finalize_Protection
);
7790 raise Program_Error
;
7794 raise Program_Error
;
7797 if Present
(Fin_Id
) then
7799 -- When finalizing a class-wide object, do not convert to the root
7800 -- type in order to produce a dispatching call.
7802 if Is_Class_Wide_Type
(Typ
) then
7805 -- Ensure that a finalization routine is at least decorated in order
7806 -- to inspect the object parameter.
7808 elsif Analyzed
(Fin_Id
)
7809 or else Ekind
(Fin_Id
) = E_Procedure
7811 -- In certain cases, such as the creation of Stream_Read, the
7812 -- visible entity of the type is its full view. Since Stream_Read
7813 -- will have to create an object of type Typ, the local object
7814 -- will be finalzed by the scope finalizer generated later on. The
7815 -- object parameter of Deep_Finalize will always use the private
7816 -- view of the type. To avoid such a clash between a private and a
7817 -- full view, perform an unchecked conversion of the object
7818 -- reference to the private view.
7821 Formal_Typ
: constant Entity_Id
:=
7822 Etype
(First_Formal
(Fin_Id
));
7824 if Is_Private_Type
(Formal_Typ
)
7825 and then Present
(Full_View
(Formal_Typ
))
7826 and then Full_View
(Formal_Typ
) = Utyp
7828 Ref
:= Unchecked_Convert_To
(Formal_Typ
, Ref
);
7832 -- If the object is unanalyzed, set its expected type for use in
7833 -- Convert_View in case an additional conversion is needed.
7836 and then Nkind
(Ref
) /= N_Unchecked_Type_Conversion
7838 Set_Etype
(Ref
, Typ
);
7841 Ref
:= Convert_View
(Fin_Id
, Ref
);
7848 Skip_Self
=> Skip_Self
);
7850 pragma Assert
(Serious_Errors_Detected
> 0
7851 or else not Has_Controlled_Component
(Utyp
));
7854 end Make_Final_Call
;
7856 --------------------------------
7857 -- Make_Finalize_Address_Body --
7858 --------------------------------
7860 procedure Make_Finalize_Address_Body
(Typ
: Entity_Id
) is
7861 Is_Task
: constant Boolean :=
7862 Ekind
(Typ
) = E_Record_Type
7863 and then Is_Concurrent_Record_Type
(Typ
)
7864 and then Ekind
(Corresponding_Concurrent_Type
(Typ
)) =
7866 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7867 Proc_Id
: Entity_Id
;
7871 -- The corresponding records of task types are not controlled by design.
7872 -- For the sake of completeness, create an empty Finalize_Address to be
7873 -- used in task class-wide allocations.
7878 -- Nothing to do if the type is not controlled or it already has a
7879 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
7880 -- come from source. These are usually generated for completeness and
7881 -- do not need the Finalize_Address primitive.
7883 elsif not Needs_Finalization
(Typ
)
7884 or else Present
(TSS
(Typ
, TSS_Finalize_Address
))
7886 (Is_Class_Wide_Type
(Typ
)
7887 and then Ekind
(Root_Type
(Typ
)) = E_Record_Subtype
7888 and then not Comes_From_Source
(Root_Type
(Typ
)))
7893 -- Do not generate Finalize_Address routine for CodePeer
7895 if CodePeer_Mode
then
7900 Make_Defining_Identifier
(Loc
,
7901 Make_TSS_Name
(Typ
, TSS_Finalize_Address
));
7905 -- procedure <Typ>FD (V : System.Address) is
7907 -- null; -- for tasks
7909 -- declare -- for all other types
7910 -- type Pnn is access all Typ;
7911 -- for Pnn'Storage_Size use 0;
7913 -- [Deep_]Finalize (Pnn (V).all);
7918 Stmts
:= New_List
(Make_Null_Statement
(Loc
));
7920 Stmts
:= Make_Finalize_Address_Stmts
(Typ
);
7924 Make_Subprogram_Body
(Loc
,
7926 Make_Procedure_Specification
(Loc
,
7927 Defining_Unit_Name
=> Proc_Id
,
7929 Parameter_Specifications
=> New_List
(
7930 Make_Parameter_Specification
(Loc
,
7931 Defining_Identifier
=>
7932 Make_Defining_Identifier
(Loc
, Name_V
),
7934 New_Occurrence_Of
(RTE
(RE_Address
), Loc
)))),
7936 Declarations
=> No_List
,
7938 Handled_Statement_Sequence
=>
7939 Make_Handled_Sequence_Of_Statements
(Loc
,
7940 Statements
=> Stmts
)));
7942 Set_TSS
(Typ
, Proc_Id
);
7943 end Make_Finalize_Address_Body
;
7945 ---------------------------------
7946 -- Make_Finalize_Address_Stmts --
7947 ---------------------------------
7949 function Make_Finalize_Address_Stmts
(Typ
: Entity_Id
) return List_Id
is
7950 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
7953 Desig_Typ
: Entity_Id
;
7954 Fin_Block
: Node_Id
;
7957 Ptr_Typ
: Entity_Id
;
7960 if Is_Array_Type
(Typ
) then
7961 if Is_Constrained
(First_Subtype
(Typ
)) then
7962 Desig_Typ
:= First_Subtype
(Typ
);
7964 Desig_Typ
:= Base_Type
(Typ
);
7967 -- Class-wide types of constrained root types
7969 elsif Is_Class_Wide_Type
(Typ
)
7970 and then Has_Discriminants
(Root_Type
(Typ
))
7972 Is_Empty_Elmt_List
(Discriminant_Constraint
(Root_Type
(Typ
)))
7975 Parent_Typ
: Entity_Id
;
7976 Parent_Utyp
: Entity_Id
;
7979 -- Climb the parent type chain looking for a non-constrained type
7981 Parent_Typ
:= Root_Type
(Typ
);
7982 while Parent_Typ
/= Etype
(Parent_Typ
)
7983 and then Has_Discriminants
(Parent_Typ
)
7985 Is_Empty_Elmt_List
(Discriminant_Constraint
(Parent_Typ
))
7987 Parent_Typ
:= Etype
(Parent_Typ
);
7990 -- Handle views created for tagged types with unknown
7993 if Is_Underlying_Record_View
(Parent_Typ
) then
7994 Parent_Typ
:= Underlying_Record_View
(Parent_Typ
);
7997 Parent_Utyp
:= Underlying_Type
(Parent_Typ
);
7999 -- Handle views created for a synchronized private extension with
8000 -- known, non-defaulted discriminants. In that case, parent_typ
8001 -- will be the private extension, as it is the first "non
8002 -- -constrained" type in the parent chain. Unfortunately, the
8003 -- underlying type, being a protected or task type, is not the
8004 -- "real" type needing finalization. Rather, the "corresponding
8005 -- record type" should be the designated type here. In fact, TSS
8006 -- finalizer generation is specifically skipped for the nominal
8007 -- class-wide type of (the full view of) a concurrent type (see
8008 -- exp_ch7.Expand_Freeze_Class_Wide_Type). If we don't designate
8009 -- the underlying record (Tprot_typeVC), we will end up trying to
8010 -- dispatch to prot_typeVDF from an incorrectly designated
8011 -- Tprot_typeC, which is, of course, not actually a member of
8012 -- prot_typeV'Class, and thus incompatible.
8014 if Ekind
(Parent_Utyp
) in Concurrent_Kind
8015 and then Present
(Corresponding_Record_Type
(Parent_Utyp
))
8017 Parent_Utyp
:= Corresponding_Record_Type
(Parent_Utyp
);
8020 Desig_Typ
:= Class_Wide_Type
(Parent_Utyp
);
8030 -- type Ptr_Typ is access all Typ;
8031 -- for Ptr_Typ'Storage_Size use 0;
8033 Ptr_Typ
:= Make_Temporary
(Loc
, 'P');
8036 Make_Full_Type_Declaration
(Loc
,
8037 Defining_Identifier
=> Ptr_Typ
,
8039 Make_Access_To_Object_Definition
(Loc
,
8040 All_Present
=> True,
8041 Subtype_Indication
=> New_Occurrence_Of
(Desig_Typ
, Loc
))),
8043 Make_Attribute_Definition_Clause
(Loc
,
8044 Name
=> New_Occurrence_Of
(Ptr_Typ
, Loc
),
8045 Chars
=> Name_Storage_Size
,
8046 Expression
=> Make_Integer_Literal
(Loc
, 0)));
8048 Obj_Expr
:= Make_Identifier
(Loc
, Name_V
);
8050 -- Unconstrained arrays require special processing in order to retrieve
8051 -- the elements. To achieve this, we have to skip the dope vector which
8052 -- lays in front of the elements and then use a thin pointer to perform
8053 -- the address-to-access conversion.
8055 if Is_Array_Type
(Typ
)
8056 and then not Is_Constrained
(First_Subtype
(Typ
))
8059 Dope_Id
: Entity_Id
;
8062 -- Ensure that Ptr_Typ is a thin pointer; generate:
8063 -- for Ptr_Typ'Size use System.Address'Size;
8066 Make_Attribute_Definition_Clause
(Loc
,
8067 Name
=> New_Occurrence_Of
(Ptr_Typ
, Loc
),
8070 Make_Integer_Literal
(Loc
, System_Address_Size
)));
8073 -- Dnn : constant Storage_Offset :=
8074 -- Desig_Typ'Descriptor_Size / Storage_Unit;
8076 Dope_Id
:= Make_Temporary
(Loc
, 'D');
8079 Make_Object_Declaration
(Loc
,
8080 Defining_Identifier
=> Dope_Id
,
8081 Constant_Present
=> True,
8082 Object_Definition
=>
8083 New_Occurrence_Of
(RTE
(RE_Storage_Offset
), Loc
),
8085 Make_Op_Divide
(Loc
,
8087 Make_Attribute_Reference
(Loc
,
8088 Prefix
=> New_Occurrence_Of
(Desig_Typ
, Loc
),
8089 Attribute_Name
=> Name_Descriptor_Size
),
8091 Make_Integer_Literal
(Loc
, System_Storage_Unit
))));
8093 -- Shift the address from the start of the dope vector to the
8094 -- start of the elements:
8098 -- Note that this is done through a wrapper routine since RTSfind
8099 -- cannot retrieve operations with string names of the form "+".
8102 Make_Function_Call
(Loc
,
8104 New_Occurrence_Of
(RTE
(RE_Add_Offset_To_Address
), Loc
),
8105 Parameter_Associations
=> New_List
(
8107 New_Occurrence_Of
(Dope_Id
, Loc
)));
8114 Make_Explicit_Dereference
(Loc
,
8115 Prefix
=> Unchecked_Convert_To
(Ptr_Typ
, Obj_Expr
)),
8118 if Present
(Fin_Call
) then
8120 Make_Block_Statement
(Loc
,
8121 Declarations
=> Decls
,
8122 Handled_Statement_Sequence
=>
8123 Make_Handled_Sequence_Of_Statements
(Loc
,
8124 Statements
=> New_List
(Fin_Call
)));
8126 -- Otherwise previous errors or a missing full view may prevent the
8127 -- proper freezing of the designated type. If this is the case, there
8128 -- is no [Deep_]Finalize primitive to call.
8131 Fin_Block
:= Make_Null_Statement
(Loc
);
8134 return New_List
(Fin_Block
);
8135 end Make_Finalize_Address_Stmts
;
8137 -------------------------------------
8138 -- Make_Handler_For_Ctrl_Operation --
8139 -------------------------------------
8143 -- when E : others =>
8144 -- Raise_From_Controlled_Operation (E);
8149 -- raise Program_Error [finalize raised exception];
8151 -- depending on whether Raise_From_Controlled_Operation is available
8153 function Make_Handler_For_Ctrl_Operation
8154 (Loc
: Source_Ptr
) return Node_Id
8157 -- Choice parameter (for the first case above)
8159 Raise_Node
: Node_Id
;
8160 -- Procedure call or raise statement
8163 -- Standard run-time: add choice parameter E and pass it to
8164 -- Raise_From_Controlled_Operation so that the original exception
8165 -- name and message can be recorded in the exception message for
8168 if RTE_Available
(RE_Raise_From_Controlled_Operation
) then
8169 E_Occ
:= Make_Defining_Identifier
(Loc
, Name_E
);
8171 Make_Procedure_Call_Statement
(Loc
,
8174 (RTE
(RE_Raise_From_Controlled_Operation
), Loc
),
8175 Parameter_Associations
=> New_List
(
8176 New_Occurrence_Of
(E_Occ
, Loc
)));
8178 -- Restricted run-time: exception messages are not supported
8183 Make_Raise_Program_Error
(Loc
,
8184 Reason
=> PE_Finalize_Raised_Exception
);
8188 Make_Implicit_Exception_Handler
(Loc
,
8189 Exception_Choices
=> New_List
(Make_Others_Choice
(Loc
)),
8190 Choice_Parameter
=> E_Occ
,
8191 Statements
=> New_List
(Raise_Node
));
8192 end Make_Handler_For_Ctrl_Operation
;
8194 --------------------
8195 -- Make_Init_Call --
8196 --------------------
8198 function Make_Init_Call
8200 Typ
: Entity_Id
) return Node_Id
8202 Loc
: constant Source_Ptr
:= Sloc
(Obj_Ref
);
8211 -- Deal with the type and object reference. Depending on the context, an
8212 -- object reference may need several conversions.
8214 if Is_Concurrent_Type
(Typ
) then
8216 Utyp
:= Corresponding_Record_Type
(Typ
);
8217 Ref
:= Convert_Concurrent
(Ref
, Typ
);
8219 elsif Is_Private_Type
(Typ
)
8220 and then Present
(Full_View
(Typ
))
8221 and then Is_Concurrent_Type
(Underlying_Type
(Typ
))
8224 Utyp
:= Corresponding_Record_Type
(Underlying_Type
(Typ
));
8225 Ref
:= Convert_Concurrent
(Ref
, Underlying_Type
(Typ
));
8232 Utyp
:= Underlying_Type
(Base_Type
(Utyp
));
8233 Set_Assignment_OK
(Ref
);
8235 -- Deal with untagged derivation of private views
8237 if Is_Untagged_Derivation
(Typ
) and then not Is_Conc
then
8238 Utyp
:= Underlying_Type
(Root_Type
(Base_Type
(Typ
)));
8239 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
8241 -- The following is to prevent problems with UC see 1.156 RH ???
8243 Set_Assignment_OK
(Ref
);
8246 -- If the underlying_type is a subtype, then we are dealing with the
8247 -- completion of a private type. We need to access the base type and
8248 -- generate a conversion to it.
8250 if Present
(Utyp
) and then Utyp
/= Base_Type
(Utyp
) then
8251 pragma Assert
(Is_Private_Type
(Typ
));
8252 Utyp
:= Base_Type
(Utyp
);
8253 Ref
:= Unchecked_Convert_To
(Utyp
, Ref
);
8256 -- The underlying type may not be present due to a missing full view.
8257 -- In this case freezing did not take place and there is no suitable
8258 -- [Deep_]Initialize primitive to call.
8259 -- If Typ is protected then no additional processing is needed either.
8262 or else Is_Protected_Type
(Typ
)
8267 -- Select the appropriate version of initialize
8269 if Has_Controlled_Component
(Utyp
) then
8270 Proc
:= TSS
(Utyp
, Deep_Name_Of
(Initialize_Case
));
8272 Proc
:= Find_Prim_Op
(Utyp
, Name_Of
(Initialize_Case
));
8273 Check_Visibly_Controlled
(Initialize_Case
, Typ
, Proc
, Ref
);
8276 -- If initialization procedure for an array of controlled objects is
8277 -- trivial, do not generate a useless call to it.
8278 -- The initialization procedure may be missing altogether in the case
8279 -- of a derived container whose components have trivial initialization.
8282 or else (Is_Array_Type
(Utyp
) and then Is_Trivial_Subprogram
(Proc
))
8284 (not Comes_From_Source
(Proc
)
8285 and then Present
(Alias
(Proc
))
8286 and then Is_Trivial_Subprogram
(Alias
(Proc
)))
8291 -- The object reference may need another conversion depending on the
8292 -- type of the formal and that of the actual.
8294 Ref
:= Convert_View
(Proc
, Ref
);
8297 -- [Deep_]Initialize (Ref);
8300 Make_Procedure_Call_Statement
(Loc
,
8301 Name
=> New_Occurrence_Of
(Proc
, Loc
),
8302 Parameter_Associations
=> New_List
(Ref
));
8305 ------------------------------
8306 -- Make_Local_Deep_Finalize --
8307 ------------------------------
8309 function Make_Local_Deep_Finalize
8311 Nam
: Entity_Id
) return Node_Id
8313 Loc
: constant Source_Ptr
:= Sloc
(Typ
);
8317 Formals
:= New_List
(
8321 Make_Parameter_Specification
(Loc
,
8322 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_V
),
8324 Out_Present
=> True,
8325 Parameter_Type
=> New_Occurrence_Of
(Typ
, Loc
)),
8327 -- F : Boolean := True
8329 Make_Parameter_Specification
(Loc
,
8330 Defining_Identifier
=> Make_Defining_Identifier
(Loc
, Name_F
),
8331 Parameter_Type
=> New_Occurrence_Of
(Standard_Boolean
, Loc
),
8332 Expression
=> New_Occurrence_Of
(Standard_True
, Loc
)));
8334 -- Add the necessary number of counters to represent the initialization
8335 -- state of an object.
8338 Make_Subprogram_Body
(Loc
,
8340 Make_Procedure_Specification
(Loc
,
8341 Defining_Unit_Name
=> Nam
,
8342 Parameter_Specifications
=> Formals
),
8344 Declarations
=> No_List
,
8346 Handled_Statement_Sequence
=>
8347 Make_Handled_Sequence_Of_Statements
(Loc
,
8348 Statements
=> Make_Deep_Record_Body
(Finalize_Case
, Typ
, True)));
8349 end Make_Local_Deep_Finalize
;
8351 ----------------------------------
8352 -- Make_Master_Node_Declaration --
8353 ----------------------------------
8355 function Make_Master_Node_Declaration
8357 Master_Node
: Entity_Id
;
8358 Obj
: Entity_Id
) return Node_Id
8361 Set_Finalization_Master_Node
(Obj
, Master_Node
);
8364 Make_Object_Declaration
(Loc
,
8365 Defining_Identifier
=> Master_Node
,
8366 Aliased_Present
=> True,
8367 Object_Definition
=>
8368 New_Occurrence_Of
(RTE
(RE_Master_Node
), Loc
));
8369 end Make_Master_Node_Declaration
;
8371 ----------------------------------------
8372 -- Make_Suppress_Object_Finalize_Call --
8373 ----------------------------------------
8375 function Make_Suppress_Object_Finalize_Call
8377 Obj
: Entity_Id
) return Node_Id
8379 Obj_Decl
: constant Node_Id
:= Declaration_Node
(Obj
);
8381 Master_Node_Decl
: Node_Id
;
8382 Master_Node_Id
: Entity_Id
;
8385 -- Create the declaration of the Master_Node for the object and
8386 -- insert it before the declaration of the object itself.
8388 if Present
(Finalization_Master_Node
(Obj
)) then
8389 Master_Node_Id
:= Finalization_Master_Node
(Obj
);
8392 Master_Node_Id
:= Make_Temporary
(Loc
, 'N');
8394 Make_Master_Node_Declaration
(Loc
, Master_Node_Id
, Obj
);
8395 Insert_Before_And_Analyze
(Obj_Decl
, Master_Node_Decl
);
8397 -- Generate the attachment of the object to the Master_Node
8399 Attach_Object_To_Master_Node
(Obj_Decl
, Master_Node_Id
);
8401 -- Mark the object to avoid double finalization
8403 Set_Is_Ignored_For_Finalization
(Obj
);
8407 Make_Procedure_Call_Statement
(Loc
,
8409 New_Occurrence_Of
(RTE
(RE_Suppress_Object_Finalize_At_End
), Loc
),
8410 Parameter_Associations
=> New_List
(
8411 New_Occurrence_Of
(Master_Node_Id
, Loc
)));
8412 end Make_Suppress_Object_Finalize_Call
;
8414 --------------------------
8415 -- Make_Transient_Block --
8416 --------------------------
8418 function Make_Transient_Block
8421 Par
: Node_Id
) return Node_Id
8423 function Manages_Sec_Stack
(Id
: Entity_Id
) return Boolean;
8424 -- Determine whether scoping entity Id manages the secondary stack
8426 function Within_Loop_Statement
(N
: Node_Id
) return Boolean;
8427 -- Return True when N appears within a loop and no block is containing N
8429 -----------------------
8430 -- Manages_Sec_Stack --
8431 -----------------------
8433 function Manages_Sec_Stack
(Id
: Entity_Id
) return Boolean is
8437 -- An exception handler with a choice parameter utilizes a dummy
8438 -- block to provide a declarative region. Such a block should not
8439 -- be considered because it never manifests in the tree and can
8440 -- never release the secondary stack.
8444 Uses_Sec_Stack
(Id
) and then not Is_Exception_Handler
(Id
);
8451 return Uses_Sec_Stack
(Id
);
8456 end Manages_Sec_Stack
;
8458 ---------------------------
8459 -- Within_Loop_Statement --
8460 ---------------------------
8462 function Within_Loop_Statement
(N
: Node_Id
) return Boolean is
8463 Par
: Node_Id
:= Parent
(N
);
8466 while Nkind
(Par
) not in
8467 N_Handled_Sequence_Of_Statements | N_Loop_Statement |
8468 N_Package_Specification | N_Proper_Body
8470 pragma Assert
(Present
(Par
));
8471 Par
:= Parent
(Par
);
8474 return Nkind
(Par
) = N_Loop_Statement
;
8475 end Within_Loop_Statement
;
8479 Decls
: constant List_Id
:= New_List
;
8480 Instrs
: constant List_Id
:= New_List
(Action
);
8481 Trans_Id
: constant Entity_Id
:= Current_Scope
;
8487 -- Start of processing for Make_Transient_Block
8490 -- Even though the transient block is tasked with managing the secondary
8491 -- stack, the block may forgo this functionality depending on how the
8492 -- secondary stack is managed by enclosing scopes.
8494 if Manages_Sec_Stack
(Trans_Id
) then
8496 -- Determine whether an enclosing scope already manages the secondary
8499 Scop
:= Scope
(Trans_Id
);
8500 while Present
(Scop
) loop
8502 -- It should not be possible to reach Standard without hitting one
8503 -- of the other cases first unless Standard was manually pushed.
8505 if Scop
= Standard_Standard
then
8508 -- The transient block is within a function which returns on the
8509 -- secondary stack. Take a conservative approach and assume that
8510 -- the value on the secondary stack is part of the result. Note
8511 -- that it is not possible to detect this dependency without flow
8512 -- analysis which the compiler does not have. Letting the object
8513 -- live longer than the transient block will not leak any memory
8514 -- because the caller will reclaim the total storage used by the
8517 elsif Ekind
(Scop
) = E_Function
8518 and then Sec_Stack_Needed_For_Return
(Scop
)
8520 Set_Uses_Sec_Stack
(Trans_Id
, False);
8523 -- The transient block must manage the secondary stack when the
8524 -- block appears within a loop in order to reclaim the memory at
8527 elsif Ekind
(Scop
) = E_Loop
then
8530 -- Ditto when the block appears without a block that does not
8531 -- manage the secondary stack and is located within a loop.
8533 elsif Ekind
(Scop
) = E_Block
8534 and then not Manages_Sec_Stack
(Scop
)
8535 and then Present
(Block_Node
(Scop
))
8536 and then Within_Loop_Statement
(Block_Node
(Scop
))
8540 -- The transient block does not need to manage the secondary stack
8541 -- when there is an enclosing construct which already does that.
8542 -- This optimization saves on SS_Mark and SS_Release calls but may
8543 -- allow objects to live a little longer than required.
8545 -- The transient block must manage the secondary stack when switch
8546 -- -gnatd.s (strict management) is in effect.
8548 elsif Manages_Sec_Stack
(Scop
) and then not Debug_Flag_Dot_S
then
8549 Set_Uses_Sec_Stack
(Trans_Id
, False);
8552 -- Prevent the search from going too far because transient blocks
8553 -- are bounded by packages and subprogram scopes.
8555 elsif Ekind
(Scop
) in E_Entry
8565 Scop
:= Scope
(Scop
);
8569 -- Create the transient block. Set the parent now since the block itself
8570 -- is not part of the tree. The current scope is the E_Block entity that
8571 -- has been pushed by Establish_Transient_Scope.
8573 pragma Assert
(Ekind
(Trans_Id
) = E_Block
);
8576 Make_Block_Statement
(Loc
,
8577 Identifier
=> New_Occurrence_Of
(Trans_Id
, Loc
),
8578 Declarations
=> Decls
,
8579 Handled_Statement_Sequence
=>
8580 Make_Handled_Sequence_Of_Statements
(Loc
, Statements
=> Instrs
),
8581 Has_Created_Identifier
=> True);
8582 Set_Parent
(Block
, Par
);
8584 -- Insert actions stuck in the transient scopes as well as all freezing
8585 -- nodes needed by those actions. Do not insert cleanup actions here,
8586 -- they will be transferred to the newly created block.
8588 Insert_Actions_In_Scope_Around
8589 (Action
, Clean
=> False, Manage_SS
=> False);
8591 Insert
:= Prev
(Action
);
8593 if Present
(Insert
) then
8594 Freeze_All
(First_Entity
(Trans_Id
), Insert
);
8597 -- Transfer cleanup actions to the newly created block
8600 Cleanup_Actions
: List_Id
8601 renames Scope_Stack
.Table
(Scope_Stack
.Last
).
8602 Actions_To_Be_Wrapped
(Cleanup
);
8604 Set_Cleanup_Actions
(Block
, Cleanup_Actions
);
8605 Cleanup_Actions
:= No_List
;
8608 -- When the transient scope was established, we pushed the entry for the
8609 -- transient scope onto the scope stack, so that the scope was active
8610 -- for the installation of finalizable entities etc. Now we must remove
8611 -- this entry, since we have constructed a proper block.
8616 end Make_Transient_Block
;
8618 ------------------------
8619 -- Node_To_Be_Wrapped --
8620 ------------------------
8622 function Node_To_Be_Wrapped
return Node_Id
is
8624 return Scope_Stack
.Table
(Scope_Stack
.Last
).Node_To_Be_Wrapped
;
8625 end Node_To_Be_Wrapped
;
8627 ----------------------------
8628 -- Store_Actions_In_Scope --
8629 ----------------------------
8631 procedure Store_Actions_In_Scope
(AK
: Scope_Action_Kind
; L
: List_Id
) is
8632 SE
: Scope_Stack_Entry
renames Scope_Stack
.Table
(Scope_Stack
.Last
);
8633 Actions
: List_Id
renames SE
.Actions_To_Be_Wrapped
(AK
);
8636 if Is_Empty_List
(Actions
) then
8639 if Is_List_Member
(SE
.Node_To_Be_Wrapped
) then
8640 Set_Parent
(L
, Parent
(SE
.Node_To_Be_Wrapped
));
8642 Set_Parent
(L
, SE
.Node_To_Be_Wrapped
);
8647 elsif AK
= Before
then
8648 Insert_List_After_And_Analyze
(Last
(Actions
), L
);
8651 Insert_List_Before_And_Analyze
(First
(Actions
), L
);
8653 end Store_Actions_In_Scope
;
8655 ----------------------------------
8656 -- Store_After_Actions_In_Scope --
8657 ----------------------------------
8659 procedure Store_After_Actions_In_Scope
(L
: List_Id
) is
8661 Store_Actions_In_Scope
(After
, L
);
8662 end Store_After_Actions_In_Scope
;
8664 -----------------------------------
8665 -- Store_Before_Actions_In_Scope --
8666 -----------------------------------
8668 procedure Store_Before_Actions_In_Scope
(L
: List_Id
) is
8670 Store_Actions_In_Scope
(Before
, L
);
8671 end Store_Before_Actions_In_Scope
;
8673 -----------------------------------
8674 -- Store_Cleanup_Actions_In_Scope --
8675 -----------------------------------
8677 procedure Store_Cleanup_Actions_In_Scope
(L
: List_Id
) is
8679 Store_Actions_In_Scope
(Cleanup
, L
);
8680 end Store_Cleanup_Actions_In_Scope
;
8686 procedure Unnest_Block
(Decl
: Node_Id
) is
8687 Loc
: constant Source_Ptr
:= Sloc
(Decl
);
8689 Local_Body
: Node_Id
;
8690 Local_Call
: Node_Id
;
8691 Local_Proc
: Entity_Id
;
8692 Local_Scop
: Entity_Id
;
8695 Local_Scop
:= Entity
(Identifier
(Decl
));
8696 Ent
:= First_Entity
(Local_Scop
);
8698 Local_Proc
:= Make_Temporary
(Loc
, 'P');
8701 Make_Subprogram_Body
(Loc
,
8703 Make_Procedure_Specification
(Loc
,
8704 Defining_Unit_Name
=> Local_Proc
),
8705 Declarations
=> Declarations
(Decl
),
8706 Handled_Statement_Sequence
=>
8707 Handled_Statement_Sequence
(Decl
));
8709 -- Handlers in the block may contain nested subprograms that require
8712 Check_Unnesting_In_Handlers
(Local_Body
);
8714 Rewrite
(Decl
, Local_Body
);
8716 Set_Has_Nested_Subprogram
(Local_Proc
);
8719 Make_Procedure_Call_Statement
(Loc
,
8720 Name
=> New_Occurrence_Of
(Local_Proc
, Loc
));
8722 Insert_After
(Decl
, Local_Call
);
8723 Analyze
(Local_Call
);
8725 -- The new subprogram has the same scope as the original block
8727 Set_Scope
(Local_Proc
, Scope
(Local_Scop
));
8729 -- And the entity list of the new procedure is that of the block
8731 Set_First_Entity
(Local_Proc
, Ent
);
8733 -- Reset the scopes of all the entities to the new procedure
8735 while Present
(Ent
) loop
8736 Set_Scope
(Ent
, Local_Proc
);
8741 -------------------------
8742 -- Unnest_If_Statement --
8743 -------------------------
8745 procedure Unnest_If_Statement
(If_Stmt
: Node_Id
) is
8747 procedure Check_Stmts_For_Subp_Unnesting
(Stmts
: in out List_Id
);
8748 -- A list of statements (that may be a list associated with a then,
8749 -- elsif, or else part of an if-statement) is traversed at the top
8750 -- level to determine whether it contains a subprogram body, and if so,
8751 -- the statements will be replaced with a new procedure body containing
8752 -- the statements followed by a call to the procedure. The individual
8753 -- statements may also be blocks, loops, or other if statements that
8754 -- themselves may require contain nested subprograms needing unnesting.
8756 procedure Check_Stmts_For_Subp_Unnesting
(Stmts
: in out List_Id
) is
8757 Subp_Found
: Boolean := False;
8760 if Is_Empty_List
(Stmts
) then
8765 Stmt
: Node_Id
:= First
(Stmts
);
8767 while Present
(Stmt
) loop
8768 if Nkind
(Stmt
) = N_Subprogram_Body
then
8777 -- The statements themselves may be blocks, loops, etc. that in turn
8778 -- contain nested subprograms requiring an unnesting transformation.
8779 -- We perform this traversal after looking for subprogram bodies, to
8780 -- avoid considering procedures created for one of those statements
8781 -- (such as a block rewritten as a procedure) as a nested subprogram
8782 -- of the statement list (which could result in an unneeded wrapper
8785 Check_Unnesting_In_Decls_Or_Stmts
(Stmts
);
8787 -- If there was a top-level subprogram body in the statement list,
8788 -- then perform an unnesting transformation on the list by replacing
8789 -- the statements with a wrapper procedure body containing the
8790 -- original statements followed by a call to that procedure.
8793 Unnest_Statement_List
(Stmts
);
8795 end Check_Stmts_For_Subp_Unnesting
;
8799 Then_Stmts
: List_Id
:= Then_Statements
(If_Stmt
);
8800 Else_Stmts
: List_Id
:= Else_Statements
(If_Stmt
);
8802 -- Start of processing for Unnest_If_Statement
8805 Check_Stmts_For_Subp_Unnesting
(Then_Stmts
);
8806 Set_Then_Statements
(If_Stmt
, Then_Stmts
);
8808 if not Is_Empty_List
(Elsif_Parts
(If_Stmt
)) then
8810 Elsif_Part
: Node_Id
:=
8811 First
(Elsif_Parts
(If_Stmt
));
8812 Elsif_Stmts
: List_Id
;
8814 while Present
(Elsif_Part
) loop
8815 Elsif_Stmts
:= Then_Statements
(Elsif_Part
);
8817 Check_Stmts_For_Subp_Unnesting
(Elsif_Stmts
);
8818 Set_Then_Statements
(Elsif_Part
, Elsif_Stmts
);
8825 Check_Stmts_For_Subp_Unnesting
(Else_Stmts
);
8826 Set_Else_Statements
(If_Stmt
, Else_Stmts
);
8827 end Unnest_If_Statement
;
8833 procedure Unnest_Loop
(Loop_Stmt
: Node_Id
) is
8835 procedure Fixup_Inner_Scopes
(Loop_Or_Block
: Node_Id
);
8836 -- This procedure fixes the scope for 2 identified cases of incorrect
8837 -- scope information.
8839 -- 1) The loops created by the compiler for array aggregates can have
8840 -- nested finalization procedure when the type of the array components
8841 -- needs finalization. It has the following form:
8843 -- for J4b in 10 .. 12 loop
8845 -- procedure __finalizer;
8847 -- procedure __finalizer is
8851 -- obj (J4b) := ...;
8853 -- When the compiler creates the N_Block_Statement, it sets its scope to
8854 -- the outer scope (the one containing the loop).
8856 -- The Unnest_Loop procedure moves the N_Loop_Statement inside a new
8857 -- procedure and correctly sets the scopes for both the new procedure
8858 -- and the loop entity. The inner block scope is not modified and this
8859 -- leaves the Tree in an incoherent state (i.e. the inner procedure must
8860 -- have its enclosing procedure in its scope ancestries).
8862 -- 2) The second case happens when an object declaration is created
8863 -- within a loop used to initialize the 'others' components of an
8864 -- aggregate that is nested within a transient scope. When the transient
8865 -- scope is removed, the object scope is set to the outer scope. For
8870 -- L98s : for J90s in 2 .. 19 loop
8872 -- R92s : aliased some_type;
8875 -- The loop L98s was initially wrapped in a transient scope B72s and
8876 -- R92s was nested within it. Then the transient scope is removed and
8877 -- the scope of R92s is set to 'pack'. And finally, when the unnester
8878 -- moves the loop body in a new procedure, R92s's scope is still left
8881 -- This procedure finds the two previous patterns and fixes the scope
8884 -- Another (better) fix would be to have the block scope set to be the
8885 -- loop entity earlier (when the block is created or when the loop gets
8886 -- an actual entity set). But unfortunately this proved harder to
8889 procedure Fixup_Inner_Scopes
(Loop_Or_Block
: Node_Id
) is
8891 Loop_Or_Block_Ent
: Entity_Id
;
8892 Ent_To_Fix
: Entity_Id
;
8893 Decl
: Node_Id
:= Empty
;
8895 pragma Assert
(Nkind
(Loop_Or_Block
) in
8896 N_Loop_Statement | N_Block_Statement
);
8898 Loop_Or_Block_Ent
:= Entity
(Identifier
(Loop_Or_Block
));
8899 if Nkind
(Loop_Or_Block
) = N_Loop_Statement
then
8900 Stmt
:= First
(Statements
(Loop_Or_Block
));
8901 else -- N_Block_Statement
8903 (Statements
(Handled_Statement_Sequence
(Loop_Or_Block
)));
8904 Decl
:= First
(Declarations
(Loop_Or_Block
));
8907 -- Fix scopes for any object declaration found in the block
8908 while Present
(Decl
) loop
8909 if Nkind
(Decl
) = N_Object_Declaration
then
8910 Ent_To_Fix
:= Defining_Identifier
(Decl
);
8911 Set_Scope
(Ent_To_Fix
, Loop_Or_Block_Ent
);
8916 while Present
(Stmt
) loop
8917 if Nkind
(Stmt
) = N_Block_Statement
8918 and then Is_Abort_Block
(Stmt
)
8920 Ent_To_Fix
:= Entity
(Identifier
(Stmt
));
8921 Set_Scope
(Ent_To_Fix
, Loop_Or_Block_Ent
);
8922 elsif Nkind
(Stmt
) in N_Block_Statement | N_Loop_Statement
8924 Fixup_Inner_Scopes
(Stmt
);
8928 end Fixup_Inner_Scopes
;
8930 Loc
: constant Source_Ptr
:= Sloc
(Loop_Stmt
);
8932 Local_Body
: Node_Id
;
8933 Local_Call
: Node_Id
;
8934 Loop_Ent
: Entity_Id
;
8935 Local_Proc
: Entity_Id
;
8936 Loop_Copy
: constant Node_Id
:=
8937 Relocate_Node
(Loop_Stmt
);
8939 Loop_Ent
:= Entity
(Identifier
(Loop_Stmt
));
8940 Ent
:= First_Entity
(Loop_Ent
);
8942 Local_Proc
:= Make_Temporary
(Loc
, 'P');
8945 Make_Subprogram_Body
(Loc
,
8947 Make_Procedure_Specification
(Loc
,
8948 Defining_Unit_Name
=> Local_Proc
),
8949 Declarations
=> Empty_List
,
8950 Handled_Statement_Sequence
=>
8951 Make_Handled_Sequence_Of_Statements
(Loc
,
8952 Statements
=> New_List
(Loop_Copy
)));
8954 Rewrite
(Loop_Stmt
, Local_Body
);
8955 Analyze
(Loop_Stmt
);
8957 Set_Has_Nested_Subprogram
(Local_Proc
);
8960 Make_Procedure_Call_Statement
(Loc
,
8961 Name
=> New_Occurrence_Of
(Local_Proc
, Loc
));
8963 Insert_After
(Loop_Stmt
, Local_Call
);
8964 Analyze
(Local_Call
);
8966 -- New procedure has the same scope as the original loop, and the scope
8967 -- of the loop is the new procedure.
8969 Set_Scope
(Local_Proc
, Scope
(Loop_Ent
));
8970 Set_Scope
(Loop_Ent
, Local_Proc
);
8972 Fixup_Inner_Scopes
(Loop_Copy
);
8974 -- The entity list of the new procedure is that of the loop
8976 Set_First_Entity
(Local_Proc
, Ent
);
8978 -- Note that the entities associated with the loop don't need to have
8979 -- their Scope fields reset, since they're still associated with the
8980 -- same loop entity that now belongs to the copied loop statement.
8983 ---------------------------
8984 -- Unnest_Statement_List --
8985 ---------------------------
8987 procedure Unnest_Statement_List
(Stmts
: in out List_Id
) is
8988 Loc
: constant Source_Ptr
:= Sloc
(First
(Stmts
));
8989 Local_Body
: Node_Id
;
8990 Local_Call
: Node_Id
;
8991 Local_Proc
: Entity_Id
;
8992 New_Stmts
: constant List_Id
:= Empty_List
;
8995 Local_Proc
:= Make_Temporary
(Loc
, 'P');
8998 Make_Subprogram_Body
(Loc
,
9000 Make_Procedure_Specification
(Loc
,
9001 Defining_Unit_Name
=> Local_Proc
),
9002 Declarations
=> Empty_List
,
9003 Handled_Statement_Sequence
=>
9004 Make_Handled_Sequence_Of_Statements
(Loc
,
9005 Statements
=> Stmts
));
9007 Append_To
(New_Stmts
, Local_Body
);
9009 Analyze
(Local_Body
);
9011 Set_Has_Nested_Subprogram
(Local_Proc
);
9014 Make_Procedure_Call_Statement
(Loc
,
9015 Name
=> New_Occurrence_Of
(Local_Proc
, Loc
));
9017 Append_To
(New_Stmts
, Local_Call
);
9018 Analyze
(Local_Call
);
9020 -- Traverse the statements, and for any that are declarations or
9021 -- subprogram bodies that have entities, set the Scope of those
9022 -- entities to the new procedure's Entity_Id.
9025 Stmt
: Node_Id
:= First
(Stmts
);
9028 while Present
(Stmt
) loop
9029 case Nkind
(Stmt
) is
9031 | N_Renaming_Declaration
9033 Set_Scope
(Defining_Identifier
(Stmt
), Local_Proc
);
9035 when N_Subprogram_Body
=>
9037 (Defining_Unit_Name
(Specification
(Stmt
)), Local_Proc
);
9048 end Unnest_Statement_List
;
9050 --------------------------------
9051 -- Wrap_Transient_Declaration --
9052 --------------------------------
9054 -- If a transient scope has been established during the processing of the
9055 -- Expression of an Object_Declaration, it is not possible to wrap the
9056 -- declaration into a transient block as usual case, otherwise the object
9057 -- would be itself declared in the wrong scope. Therefore, all entities (if
9058 -- any) defined in the transient block are moved to the proper enclosing
9059 -- scope. Furthermore, if they are controlled variables they are finalized
9060 -- right after the declaration. The finalization list of the transient
9061 -- scope is defined as a renaming of the enclosing one so during their
9062 -- initialization they will be attached to the proper finalization list.
9063 -- For instance, the following declaration :
9065 -- X : Typ := F (G (A), G (B));
9067 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
9068 -- is expanded into :
9070 -- X : Typ := [ complex Expression-Action ];
9071 -- [Deep_]Finalize (_v1);
9072 -- [Deep_]Finalize (_v2);
9074 procedure Wrap_Transient_Declaration
(N
: Node_Id
) is
9079 Curr_S
:= Current_Scope
;
9080 Encl_S
:= Scope
(Curr_S
);
9082 -- Insert all actions including cleanup generated while analyzing or
9083 -- expanding the transient context back into the tree. Manage the
9084 -- secondary stack when the object declaration appears in a library
9085 -- level package [body].
9087 Insert_Actions_In_Scope_Around
9091 Uses_Sec_Stack
(Curr_S
)
9092 and then Nkind
(N
) = N_Object_Declaration
9093 and then Ekind
(Encl_S
) in E_Package | E_Package_Body
9094 and then Is_Library_Level_Entity
(Encl_S
));
9097 -- Relocate local entities declared within the transient scope to the
9098 -- enclosing scope. This action sets their Is_Public flag accordingly.
9100 Transfer_Entities
(Curr_S
, Encl_S
);
9102 -- Mark the enclosing dynamic scope to ensure that the secondary stack
9103 -- is properly released upon exiting the said scope.
9105 if Uses_Sec_Stack
(Curr_S
) then
9106 Curr_S
:= Enclosing_Dynamic_Scope
(Curr_S
);
9108 -- Do not mark a function that returns on the secondary stack as the
9109 -- reclamation is done by the caller.
9111 if Ekind
(Curr_S
) = E_Function
9112 and then Needs_Secondary_Stack
(Etype
(Curr_S
))
9116 -- Otherwise mark the enclosing dynamic scope
9119 Set_Uses_Sec_Stack
(Curr_S
);
9120 Check_Restriction
(No_Secondary_Stack
, N
);
9123 end Wrap_Transient_Declaration
;
9125 -------------------------------
9126 -- Wrap_Transient_Expression --
9127 -------------------------------
9129 procedure Wrap_Transient_Expression
(N
: Node_Id
) is
9130 Loc
: constant Source_Ptr
:= Sloc
(N
);
9131 Expr
: Node_Id
:= Relocate_Node
(N
);
9132 Temp
: constant Entity_Id
:= Make_Temporary
(Loc
, 'E', N
);
9133 Typ
: constant Entity_Id
:= Etype
(N
);
9140 -- M : constant Mark_Id := SS_Mark;
9141 -- procedure Finalizer is ... (See Build_Finalizer)
9144 -- Temp := <Expr>; -- general case
9145 -- Temp := (if <Expr> then True else False); -- boolean case
9151 -- A special case is made for Boolean expressions so that the back end
9152 -- knows to generate a conditional branch instruction, if running with
9153 -- -fpreserve-control-flow. This ensures that a control-flow change
9154 -- signaling the decision outcome occurs before the cleanup actions.
9156 if Opt
.Suppress_Control_Flow_Optimizations
9157 and then Is_Boolean_Type
(Typ
)
9160 Make_If_Expression
(Loc
,
9161 Expressions
=> New_List
(
9163 New_Occurrence_Of
(Standard_True
, Loc
),
9164 New_Occurrence_Of
(Standard_False
, Loc
)));
9167 Insert_Actions
(N
, New_List
(
9168 Make_Object_Declaration
(Loc
,
9169 Defining_Identifier
=> Temp
,
9170 Object_Definition
=> New_Occurrence_Of
(Typ
, Loc
)),
9172 Make_Transient_Block
(Loc
,
9174 Make_Assignment_Statement
(Loc
,
9175 Name
=> New_Occurrence_Of
(Temp
, Loc
),
9176 Expression
=> Expr
),
9177 Par
=> Parent
(N
))));
9179 if Debug_Generated_Code
then
9180 Set_Debug_Info_Needed
(Temp
);
9183 Rewrite
(N
, New_Occurrence_Of
(Temp
, Loc
));
9184 Analyze_And_Resolve
(N
, Typ
);
9185 end Wrap_Transient_Expression
;
9187 ------------------------------
9188 -- Wrap_Transient_Statement --
9189 ------------------------------
9191 procedure Wrap_Transient_Statement
(N
: Node_Id
) is
9192 Loc
: constant Source_Ptr
:= Sloc
(N
);
9193 New_Stmt
: constant Node_Id
:= Relocate_Node
(N
);
9198 -- M : constant Mark_Id := SS_Mark;
9199 -- procedure Finalizer is ... (See Build_Finalizer)
9209 Make_Transient_Block
(Loc
,
9211 Par
=> Parent
(N
)));
9213 -- With the scope stack back to normal, we can call analyze on the
9214 -- resulting block. At this point, the transient scope is being
9215 -- treated like a perfectly normal scope, so there is nothing
9216 -- special about it.
9218 -- Note: Wrap_Transient_Statement is called with the node already
9219 -- analyzed (i.e. Analyzed (N) is True). This is important, since
9220 -- otherwise we would get a recursive processing of the node when
9221 -- we do this Analyze call.
9224 end Wrap_Transient_Statement
;