PR c/79855: add full stop to store merging param descriptions
[official-gcc.git] / gcc / ada / exp_ch7.adb
blob93573a29ea349d69979be5f0acfb17376aa77af4
1 ------------------------------------------------------------------------------
2 -- --
3 -- GNAT COMPILER COMPONENTS --
4 -- --
5 -- E X P _ C H 7 --
6 -- --
7 -- B o d y --
8 -- --
9 -- Copyright (C) 1992-2016, Free Software Foundation, Inc. --
10 -- --
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. --
20 -- --
21 -- GNAT was originally developed by the GNAT team at New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc. --
23 -- --
24 ------------------------------------------------------------------------------
26 -- This package contains virtually all expansion mechanisms related to
27 -- - controlled types
28 -- - transient scopes
30 with Atree; use Atree;
31 with Debug; use Debug;
32 with Einfo; use Einfo;
33 with Elists; use Elists;
34 with Errout; use Errout;
35 with Exp_Ch6; use Exp_Ch6;
36 with Exp_Ch9; use Exp_Ch9;
37 with Exp_Ch11; use Exp_Ch11;
38 with Exp_Dbug; use Exp_Dbug;
39 with Exp_Dist; use Exp_Dist;
40 with Exp_Disp; use Exp_Disp;
41 with Exp_Prag; use Exp_Prag;
42 with Exp_Tss; use Exp_Tss;
43 with Exp_Util; use Exp_Util;
44 with Freeze; use Freeze;
45 with Ghost; use Ghost;
46 with Lib; use Lib;
47 with Nlists; use Nlists;
48 with Nmake; use Nmake;
49 with Opt; use Opt;
50 with Output; use Output;
51 with Restrict; use Restrict;
52 with Rident; use Rident;
53 with Rtsfind; use Rtsfind;
54 with Sinfo; use Sinfo;
55 with Sem; use Sem;
56 with Sem_Aux; use Sem_Aux;
57 with Sem_Ch3; use Sem_Ch3;
58 with Sem_Ch6; use Sem_Ch6;
59 with Sem_Ch7; use Sem_Ch7;
60 with Sem_Ch8; use Sem_Ch8;
61 with Sem_Ch13; use Sem_Ch13;
62 with Sem_Res; use Sem_Res;
63 with Sem_Util; use Sem_Util;
64 with Snames; use Snames;
65 with Stand; use Stand;
66 with Stringt; use Stringt;
67 with Tbuild; use Tbuild;
68 with Ttypes; use Ttypes;
69 with Uintp; use Uintp;
71 package body Exp_Ch7 is
73 --------------------------------
74 -- Transient Scope Management --
75 --------------------------------
77 -- A transient scope is created when temporary objects are created by the
78 -- compiler. These temporary objects are allocated on the secondary stack
79 -- and the transient scope is responsible for finalizing the object when
80 -- appropriate and reclaiming the memory at the right time. The temporary
81 -- objects are generally the objects allocated to store the result of a
82 -- function returning an unconstrained or a tagged value. Expressions
83 -- needing to be wrapped in a transient scope (functions calls returning
84 -- unconstrained or tagged values) may appear in 3 different contexts which
85 -- lead to 3 different kinds of transient scope expansion:
87 -- 1. In a simple statement (procedure call, assignment, ...). In this
88 -- case the instruction is wrapped into a transient block. See
89 -- Wrap_Transient_Statement for details.
91 -- 2. In an expression of a control structure (test in a IF statement,
92 -- expression in a CASE statement, ...). See Wrap_Transient_Expression
93 -- for details.
95 -- 3. In a expression of an object_declaration. No wrapping is possible
96 -- here, so the finalization actions, if any, are done right after the
97 -- declaration and the secondary stack deallocation is done in the
98 -- proper enclosing scope. See Wrap_Transient_Declaration for details.
100 -- Note about functions returning tagged types: it has been decided to
101 -- always allocate their result in the secondary stack, even though is not
102 -- absolutely mandatory when the tagged type is constrained because the
103 -- caller knows the size of the returned object and thus could allocate the
104 -- result in the primary stack. An exception to this is when the function
105 -- builds its result in place, as is done for functions with inherently
106 -- limited result types for Ada 2005. In that case, certain callers may
107 -- pass the address of a constrained object as the target object for the
108 -- function result.
110 -- By allocating tagged results in the secondary stack a number of
111 -- implementation difficulties are avoided:
113 -- - If it is a dispatching function call, the computation of the size of
114 -- the result is possible but complex from the outside.
116 -- - If the returned type is controlled, the assignment of the returned
117 -- value to the anonymous object involves an Adjust, and we have no
118 -- easy way to access the anonymous object created by the back end.
120 -- - If the returned type is class-wide, this is an unconstrained type
121 -- anyway.
123 -- Furthermore, the small loss in efficiency which is the result of this
124 -- decision is not such a big deal because functions returning tagged types
125 -- are not as common in practice compared to functions returning access to
126 -- a tagged type.
128 --------------------------------------------------
129 -- Transient Blocks and Finalization Management --
130 --------------------------------------------------
132 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id;
133 -- N is a node which may generate a transient scope. Loop over the parent
134 -- pointers of N until we find the appropriate node to wrap. If it returns
135 -- Empty, it means that no transient scope is needed in this context.
137 procedure Insert_Actions_In_Scope_Around
138 (N : Node_Id;
139 Clean : Boolean;
140 Manage_SS : Boolean);
141 -- Insert the before-actions kept in the scope stack before N, and the
142 -- after-actions after N, which must be a member of a list. If flag Clean
143 -- is set, insert any cleanup actions. If flag Manage_SS is set, insert
144 -- calls to mark and release the secondary stack.
146 function Make_Transient_Block
147 (Loc : Source_Ptr;
148 Action : Node_Id;
149 Par : Node_Id) return Node_Id;
150 -- Action is a single statement or object declaration. Par is the proper
151 -- parent of the generated block. Create a transient block whose name is
152 -- the current scope and the only handled statement is Action. If Action
153 -- involves controlled objects or secondary stack usage, the corresponding
154 -- cleanup actions are performed at the end of the block.
156 procedure Set_Node_To_Be_Wrapped (N : Node_Id);
157 -- Set the field Node_To_Be_Wrapped of the current scope
159 -- ??? The entire comment needs to be rewritten
160 -- ??? which entire comment?
162 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
163 -- Shared processing for Store_xxx_Actions_In_Scope
165 -----------------------------
166 -- Finalization Management --
167 -----------------------------
169 -- This part describe how Initialization/Adjustment/Finalization procedures
170 -- are generated and called. Two cases must be considered, types that are
171 -- Controlled (Is_Controlled flag set) and composite types that contain
172 -- controlled components (Has_Controlled_Component flag set). In the first
173 -- case the procedures to call are the user-defined primitive operations
174 -- Initialize/Adjust/Finalize. In the second case, GNAT generates
175 -- Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
176 -- of calling the former procedures on the controlled components.
178 -- For records with Has_Controlled_Component set, a hidden "controller"
179 -- component is inserted. This controller component contains its own
180 -- finalization list on which all controlled components are attached
181 -- creating an indirection on the upper-level Finalization list. This
182 -- technique facilitates the management of objects whose number of
183 -- controlled components changes during execution. This controller
184 -- component is itself controlled and is attached to the upper-level
185 -- finalization chain. Its adjust primitive is in charge of calling adjust
186 -- on the components and adjusting the finalization pointer to match their
187 -- new location (see a-finali.adb).
189 -- It is not possible to use a similar technique for arrays that have
190 -- Has_Controlled_Component set. In this case, deep procedures are
191 -- generated that call initialize/adjust/finalize + attachment or
192 -- detachment on the finalization list for all component.
194 -- Initialize calls: they are generated for declarations or dynamic
195 -- allocations of Controlled objects with no initial value. They are always
196 -- followed by an attachment to the current Finalization Chain. For the
197 -- dynamic allocation case this the chain attached to the scope of the
198 -- access type definition otherwise, this is the chain of the current
199 -- scope.
201 -- Adjust Calls: They are generated on 2 occasions: (1) for declarations
202 -- or dynamic allocations of Controlled objects with an initial value.
203 -- (2) after an assignment. In the first case they are followed by an
204 -- attachment to the final chain, in the second case they are not.
206 -- Finalization Calls: They are generated on (1) scope exit, (2)
207 -- assignments, (3) unchecked deallocations. In case (3) they have to
208 -- be detached from the final chain, in case (2) they must not and in
209 -- case (1) this is not important since we are exiting the scope anyway.
211 -- Other details:
213 -- Type extensions will have a new record controller at each derivation
214 -- level containing controlled components. The record controller for
215 -- the parent/ancestor is attached to the finalization list of the
216 -- extension's record controller (i.e. the parent is like a component
217 -- of the extension).
219 -- For types that are both Is_Controlled and Has_Controlled_Components,
220 -- the record controller and the object itself are handled separately.
221 -- It could seem simpler to attach the object at the end of its record
222 -- controller but this would not tackle view conversions properly.
224 -- A classwide type can always potentially have controlled components
225 -- but the record controller of the corresponding actual type may not
226 -- be known at compile time so the dispatch table contains a special
227 -- field that allows computation of the offset of the record controller
228 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
230 -- Here is a simple example of the expansion of a controlled block :
232 -- declare
233 -- X : Controlled;
234 -- Y : Controlled := Init;
236 -- type R is record
237 -- C : Controlled;
238 -- end record;
239 -- W : R;
240 -- Z : R := (C => X);
242 -- begin
243 -- X := Y;
244 -- W := Z;
245 -- end;
247 -- is expanded into
249 -- declare
250 -- _L : System.FI.Finalizable_Ptr;
252 -- procedure _Clean is
253 -- begin
254 -- Abort_Defer;
255 -- System.FI.Finalize_List (_L);
256 -- Abort_Undefer;
257 -- end _Clean;
259 -- X : Controlled;
260 -- begin
261 -- Abort_Defer;
262 -- Initialize (X);
263 -- Attach_To_Final_List (_L, Finalizable (X), 1);
264 -- at end: Abort_Undefer;
265 -- Y : Controlled := Init;
266 -- Adjust (Y);
267 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
269 -- type R is record
270 -- C : Controlled;
271 -- end record;
272 -- W : R;
273 -- begin
274 -- Abort_Defer;
275 -- Deep_Initialize (W, _L, 1);
276 -- at end: Abort_Under;
277 -- Z : R := (C => X);
278 -- Deep_Adjust (Z, _L, 1);
280 -- begin
281 -- _Assign (X, Y);
282 -- Deep_Finalize (W, False);
283 -- <save W's final pointers>
284 -- W := Z;
285 -- <restore W's final pointers>
286 -- Deep_Adjust (W, _L, 0);
287 -- at end
288 -- _Clean;
289 -- end;
291 type Final_Primitives is
292 (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
293 -- This enumeration type is defined in order to ease sharing code for
294 -- building finalization procedures for composite types.
296 Name_Of : constant array (Final_Primitives) of Name_Id :=
297 (Initialize_Case => Name_Initialize,
298 Adjust_Case => Name_Adjust,
299 Finalize_Case => Name_Finalize,
300 Address_Case => Name_Finalize_Address);
301 Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
302 (Initialize_Case => TSS_Deep_Initialize,
303 Adjust_Case => TSS_Deep_Adjust,
304 Finalize_Case => TSS_Deep_Finalize,
305 Address_Case => TSS_Finalize_Address);
307 function Allows_Finalization_Master (Typ : Entity_Id) return Boolean;
308 -- Determine whether access type Typ may have a finalization master
310 procedure Build_Array_Deep_Procs (Typ : Entity_Id);
311 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
312 -- Has_Controlled_Component set and store them using the TSS mechanism.
314 function Build_Cleanup_Statements
315 (N : Node_Id;
316 Additional_Cleanup : List_Id) return List_Id;
317 -- Create the clean up calls for an asynchronous call block, task master,
318 -- protected subprogram body, task allocation block or task body, or
319 -- additional cleanup actions parked on a transient block. If the context
320 -- does not contain the above constructs, the routine returns an empty
321 -- list.
323 procedure Build_Finalizer
324 (N : Node_Id;
325 Clean_Stmts : List_Id;
326 Mark_Id : Entity_Id;
327 Top_Decls : List_Id;
328 Defer_Abort : Boolean;
329 Fin_Id : out Entity_Id);
330 -- N may denote an accept statement, block, entry body, package body,
331 -- package spec, protected body, subprogram body, or a task body. Create
332 -- a procedure which contains finalization calls for all controlled objects
333 -- declared in the declarative or statement region of N. The calls are
334 -- built in reverse order relative to the original declarations. In the
335 -- case of a task body, the routine delays the creation of the finalizer
336 -- until all statements have been moved to the task body procedure.
337 -- Clean_Stmts may contain additional context-dependent code used to abort
338 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
339 -- Mark_Id is the secondary stack used in the current context or Empty if
340 -- missing. Top_Decls is the list on which the declaration of the finalizer
341 -- is attached in the non-package case. Defer_Abort indicates that the
342 -- statements passed in perform actions that require abort to be deferred,
343 -- such as for task termination. Fin_Id is the finalizer declaration
344 -- entity.
346 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
347 -- N is a construct which contains a handled sequence of statements, Fin_Id
348 -- is the entity of a finalizer. Create an At_End handler which covers the
349 -- statements of N and calls Fin_Id. If the handled statement sequence has
350 -- an exception handler, the statements will be wrapped in a block to avoid
351 -- unwanted interaction with the new At_End handler.
353 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
354 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
355 -- Has_Component_Component set and store them using the TSS mechanism.
357 procedure Check_Visibly_Controlled
358 (Prim : Final_Primitives;
359 Typ : Entity_Id;
360 E : in out Entity_Id;
361 Cref : in out Node_Id);
362 -- The controlled operation declared for a derived type may not be
363 -- overriding, if the controlled operations of the parent type are hidden,
364 -- for example when the parent is a private type whose full view is
365 -- controlled. For other primitive operations we modify the name of the
366 -- operation to indicate that it is not overriding, but this is not
367 -- possible for Initialize, etc. because they have to be retrievable by
368 -- name. Before generating the proper call to one of these operations we
369 -- check whether Typ is known to be controlled at the point of definition.
370 -- If it is not then we must retrieve the hidden operation of the parent
371 -- and use it instead. This is one case that might be solved more cleanly
372 -- once Overriding pragmas or declarations are in place.
374 function Convert_View
375 (Proc : Entity_Id;
376 Arg : Node_Id;
377 Ind : Pos := 1) return Node_Id;
378 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
379 -- argument being passed to it. Ind indicates which formal of procedure
380 -- Proc we are trying to match. This function will, if necessary, generate
381 -- a conversion between the partial and full view of Arg to match the type
382 -- of the formal of Proc, or force a conversion to the class-wide type in
383 -- the case where the operation is abstract.
385 function Enclosing_Function (E : Entity_Id) return Entity_Id;
386 -- Given an arbitrary entity, traverse the scope chain looking for the
387 -- first enclosing function. Return Empty if no function was found.
389 function Make_Call
390 (Loc : Source_Ptr;
391 Proc_Id : Entity_Id;
392 Param : Node_Id;
393 Skip_Self : Boolean := False) return Node_Id;
394 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
395 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
396 -- an adjust or finalization call. Wnen flag Skip_Self is set, the related
397 -- action has an effect on the components only (if any).
399 function Make_Deep_Proc
400 (Prim : Final_Primitives;
401 Typ : Entity_Id;
402 Stmts : List_Id) return Node_Id;
403 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
404 -- Deep_Finalize procedures according to the first parameter, these
405 -- procedures operate on the type Typ. The Stmts parameter gives the body
406 -- of the procedure.
408 function Make_Deep_Array_Body
409 (Prim : Final_Primitives;
410 Typ : Entity_Id) return List_Id;
411 -- This function generates the list of statements for implementing
412 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
413 -- the first parameter, these procedures operate on the array type Typ.
415 function Make_Deep_Record_Body
416 (Prim : Final_Primitives;
417 Typ : Entity_Id;
418 Is_Local : Boolean := False) return List_Id;
419 -- This function generates the list of statements for implementing
420 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
421 -- the first parameter, these procedures operate on the record type Typ.
422 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
423 -- whether the inner logic should be dictated by state counters.
425 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
426 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
427 -- Make_Deep_Record_Body. Generate the following statements:
429 -- declare
430 -- type Acc_Typ is access all Typ;
431 -- for Acc_Typ'Storage_Size use 0;
432 -- begin
433 -- [Deep_]Finalize (Acc_Typ (V).all);
434 -- end;
436 --------------------------------
437 -- Allows_Finalization_Master --
438 --------------------------------
440 function Allows_Finalization_Master (Typ : Entity_Id) return Boolean is
441 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
442 -- Determine whether entity E is inside a wrapper package created for
443 -- an instance of Ada.Unchecked_Deallocation.
445 ------------------------------
446 -- In_Deallocation_Instance --
447 ------------------------------
449 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
450 Pkg : constant Entity_Id := Scope (E);
451 Par : Node_Id := Empty;
453 begin
454 if Ekind (Pkg) = E_Package
455 and then Present (Related_Instance (Pkg))
456 and then Ekind (Related_Instance (Pkg)) = E_Procedure
457 then
458 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
460 return
461 Present (Par)
462 and then Chars (Par) = Name_Unchecked_Deallocation
463 and then Chars (Scope (Par)) = Name_Ada
464 and then Scope (Scope (Par)) = Standard_Standard;
465 end if;
467 return False;
468 end In_Deallocation_Instance;
470 -- Local variables
472 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
473 Ptr_Typ : constant Entity_Id :=
474 Root_Type_Of_Full_View (Base_Type (Typ));
476 -- Start of processing for Allows_Finalization_Master
478 begin
479 -- Certain run-time configurations and targets do not provide support
480 -- for controlled types and therefore do not need masters.
482 if Restriction_Active (No_Finalization) then
483 return False;
485 -- Do not consider C and C++ types since it is assumed that the non-Ada
486 -- side will handle their clean up.
488 elsif Convention (Desig_Typ) = Convention_C
489 or else Convention (Desig_Typ) = Convention_CPP
490 then
491 return False;
493 -- Do not consider types that return on the secondary stack
495 elsif Present (Associated_Storage_Pool (Ptr_Typ))
496 and then Is_RTE (Associated_Storage_Pool (Ptr_Typ), RE_SS_Pool)
497 then
498 return False;
500 -- Do not consider types which may never allocate an object
502 elsif No_Pool_Assigned (Ptr_Typ) then
503 return False;
505 -- Do not consider access types coming from Ada.Unchecked_Deallocation
506 -- instances. Even though the designated type may be controlled, the
507 -- access type will never participate in allocation.
509 elsif In_Deallocation_Instance (Ptr_Typ) then
510 return False;
512 -- Do not consider non-library access types when restriction
513 -- No_Nested_Finalization is in effect since masters are controlled
514 -- objects.
516 elsif Restriction_Active (No_Nested_Finalization)
517 and then not Is_Library_Level_Entity (Ptr_Typ)
518 then
519 return False;
521 -- Do not create finalization masters in GNATprove mode because this
522 -- causes unwanted extra expansion. A compilation in this mode must
523 -- keep the tree as close as possible to the original sources.
525 elsif GNATprove_Mode then
526 return False;
528 -- Otherwise the access type may use a finalization master
530 else
531 return True;
532 end if;
533 end Allows_Finalization_Master;
535 ----------------------------
536 -- Build_Anonymous_Master --
537 ----------------------------
539 procedure Build_Anonymous_Master (Ptr_Typ : Entity_Id) is
540 function Create_Anonymous_Master
541 (Desig_Typ : Entity_Id;
542 Unit_Id : Entity_Id;
543 Unit_Decl : Node_Id) return Entity_Id;
544 -- Create a new anonymous master for access type Ptr_Typ with designated
545 -- type Desig_Typ. The declaration of the master and its initialization
546 -- are inserted in the declarative part of unit Unit_Decl. Unit_Id is
547 -- the entity of Unit_Decl.
549 function Current_Anonymous_Master
550 (Desig_Typ : Entity_Id;
551 Unit_Id : Entity_Id) return Entity_Id;
552 -- Find an anonymous master declared within unit Unit_Id which services
553 -- designated type Desig_Typ. If there is no such master, return Empty.
555 -----------------------------
556 -- Create_Anonymous_Master --
557 -----------------------------
559 function Create_Anonymous_Master
560 (Desig_Typ : Entity_Id;
561 Unit_Id : Entity_Id;
562 Unit_Decl : Node_Id) return Entity_Id
564 Loc : constant Source_Ptr := Sloc (Unit_Id);
566 All_FMs : Elist_Id;
567 Decls : List_Id;
568 FM_Decl : Node_Id;
569 FM_Id : Entity_Id;
570 FM_Init : Node_Id;
571 Unit_Spec : Node_Id;
573 begin
574 -- Generate:
575 -- <FM_Id> : Finalization_Master;
577 FM_Id := Make_Temporary (Loc, 'A');
579 FM_Decl :=
580 Make_Object_Declaration (Loc,
581 Defining_Identifier => FM_Id,
582 Object_Definition =>
583 New_Occurrence_Of (RTE (RE_Finalization_Master), Loc));
585 -- Generate:
586 -- Set_Base_Pool
587 -- (<FM_Id>, Global_Pool_Object'Unrestricted_Access);
589 FM_Init :=
590 Make_Procedure_Call_Statement (Loc,
591 Name =>
592 New_Occurrence_Of (RTE (RE_Set_Base_Pool), Loc),
593 Parameter_Associations => New_List (
594 New_Occurrence_Of (FM_Id, Loc),
595 Make_Attribute_Reference (Loc,
596 Prefix =>
597 New_Occurrence_Of (RTE (RE_Global_Pool_Object), Loc),
598 Attribute_Name => Name_Unrestricted_Access)));
600 -- Find the declarative list of the unit
602 if Nkind (Unit_Decl) = N_Package_Declaration then
603 Unit_Spec := Specification (Unit_Decl);
604 Decls := Visible_Declarations (Unit_Spec);
606 if No (Decls) then
607 Decls := New_List;
608 Set_Visible_Declarations (Unit_Spec, Decls);
609 end if;
611 -- Package body or subprogram case
613 -- ??? A subprogram spec or body that acts as a compilation unit may
614 -- contain a formal parameter of an anonymous access-to-controlled
615 -- type initialized by an allocator.
617 -- procedure Comp_Unit_Proc (Param : access Ctrl := new Ctrl);
619 -- There is no suitable place to create the master as the subprogram
620 -- is not in a declarative list.
622 else
623 Decls := Declarations (Unit_Decl);
625 if No (Decls) then
626 Decls := New_List;
627 Set_Declarations (Unit_Decl, Decls);
628 end if;
629 end if;
631 Prepend_To (Decls, FM_Init);
632 Prepend_To (Decls, FM_Decl);
634 -- Use the scope of the unit when analyzing the declaration of the
635 -- master and its initialization actions.
637 Push_Scope (Unit_Id);
638 Analyze (FM_Decl);
639 Analyze (FM_Init);
640 Pop_Scope;
642 -- Mark the master as servicing this specific designated type
644 Set_Anonymous_Designated_Type (FM_Id, Desig_Typ);
646 -- Include the anonymous master in the list of existing masters which
647 -- appear in this unit. This effectively creates a mapping between a
648 -- master and a designated type which in turn allows for the reuse of
649 -- masters on a per-unit basis.
651 All_FMs := Anonymous_Masters (Unit_Id);
653 if No (All_FMs) then
654 All_FMs := New_Elmt_List;
655 Set_Anonymous_Masters (Unit_Id, All_FMs);
656 end if;
658 Prepend_Elmt (FM_Id, All_FMs);
660 return FM_Id;
661 end Create_Anonymous_Master;
663 ------------------------------
664 -- Current_Anonymous_Master --
665 ------------------------------
667 function Current_Anonymous_Master
668 (Desig_Typ : Entity_Id;
669 Unit_Id : Entity_Id) return Entity_Id
671 All_FMs : constant Elist_Id := Anonymous_Masters (Unit_Id);
672 FM_Elmt : Elmt_Id;
673 FM_Id : Entity_Id;
675 begin
676 -- Inspect the list of anonymous masters declared within the unit
677 -- looking for an existing master which services the same designated
678 -- type.
680 if Present (All_FMs) then
681 FM_Elmt := First_Elmt (All_FMs);
682 while Present (FM_Elmt) loop
683 FM_Id := Node (FM_Elmt);
685 -- The currect master services the same designated type. As a
686 -- result the master can be reused and associated with another
687 -- anonymous access-to-controlled type.
689 if Anonymous_Designated_Type (FM_Id) = Desig_Typ then
690 return FM_Id;
691 end if;
693 Next_Elmt (FM_Elmt);
694 end loop;
695 end if;
697 return Empty;
698 end Current_Anonymous_Master;
700 -- Local variables
702 Desig_Typ : Entity_Id;
703 FM_Id : Entity_Id;
704 Priv_View : Entity_Id;
705 Unit_Decl : Node_Id;
706 Unit_Id : Entity_Id;
708 -- Start of processing for Build_Anonymous_Master
710 begin
711 -- Nothing to do if the circumstances do not allow for a finalization
712 -- master.
714 if not Allows_Finalization_Master (Ptr_Typ) then
715 return;
716 end if;
718 Unit_Decl := Unit (Cunit (Current_Sem_Unit));
719 Unit_Id := Unique_Defining_Entity (Unit_Decl);
721 -- The compilation unit is a package instantiation. In this case the
722 -- anonymous master is associated with the package spec as both the
723 -- spec and body appear at the same level.
725 if Nkind (Unit_Decl) = N_Package_Body
726 and then Nkind (Original_Node (Unit_Decl)) = N_Package_Instantiation
727 then
728 Unit_Id := Corresponding_Spec (Unit_Decl);
729 Unit_Decl := Unit_Declaration_Node (Unit_Id);
730 end if;
732 -- Use the initial declaration of the designated type when it denotes
733 -- the full view of an incomplete or private type. This ensures that
734 -- types with one and two views are treated the same.
736 Desig_Typ := Directly_Designated_Type (Ptr_Typ);
737 Priv_View := Incomplete_Or_Partial_View (Desig_Typ);
739 if Present (Priv_View) then
740 Desig_Typ := Priv_View;
741 end if;
743 -- Determine whether the current semantic unit already has an anonymous
744 -- master which services the designated type.
746 FM_Id := Current_Anonymous_Master (Desig_Typ, Unit_Id);
748 -- If this is not the case, create a new master
750 if No (FM_Id) then
751 FM_Id := Create_Anonymous_Master (Desig_Typ, Unit_Id, Unit_Decl);
752 end if;
754 Set_Finalization_Master (Ptr_Typ, FM_Id);
755 end Build_Anonymous_Master;
757 ----------------------------
758 -- Build_Array_Deep_Procs --
759 ----------------------------
761 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
762 begin
763 Set_TSS (Typ,
764 Make_Deep_Proc
765 (Prim => Initialize_Case,
766 Typ => Typ,
767 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
769 if not Is_Limited_View (Typ) then
770 Set_TSS (Typ,
771 Make_Deep_Proc
772 (Prim => Adjust_Case,
773 Typ => Typ,
774 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
775 end if;
777 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
778 -- suppressed since these routine will not be used.
780 if not Restriction_Active (No_Finalization) then
781 Set_TSS (Typ,
782 Make_Deep_Proc
783 (Prim => Finalize_Case,
784 Typ => Typ,
785 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
787 -- Create TSS primitive Finalize_Address.
789 Set_TSS (Typ,
790 Make_Deep_Proc
791 (Prim => Address_Case,
792 Typ => Typ,
793 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
794 end if;
795 end Build_Array_Deep_Procs;
797 ------------------------------
798 -- Build_Cleanup_Statements --
799 ------------------------------
801 function Build_Cleanup_Statements
802 (N : Node_Id;
803 Additional_Cleanup : List_Id) return List_Id
805 Is_Asynchronous_Call : constant Boolean :=
806 Nkind (N) = N_Block_Statement
807 and then Is_Asynchronous_Call_Block (N);
808 Is_Master : constant Boolean :=
809 Nkind (N) /= N_Entry_Body
810 and then Is_Task_Master (N);
811 Is_Protected_Body : constant Boolean :=
812 Nkind (N) = N_Subprogram_Body
813 and then Is_Protected_Subprogram_Body (N);
814 Is_Task_Allocation : constant Boolean :=
815 Nkind (N) = N_Block_Statement
816 and then Is_Task_Allocation_Block (N);
817 Is_Task_Body : constant Boolean :=
818 Nkind (Original_Node (N)) = N_Task_Body;
820 Loc : constant Source_Ptr := Sloc (N);
821 Stmts : constant List_Id := New_List;
823 begin
824 if Is_Task_Body then
825 if Restricted_Profile then
826 Append_To (Stmts,
827 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
828 else
829 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
830 end if;
832 elsif Is_Master then
833 if Restriction_Active (No_Task_Hierarchy) = False then
834 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
835 end if;
837 -- Add statements to unlock the protected object parameter and to
838 -- undefer abort. If the context is a protected procedure and the object
839 -- has entries, call the entry service routine.
841 -- NOTE: The generated code references _object, a parameter to the
842 -- procedure.
844 elsif Is_Protected_Body then
845 declare
846 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
847 Conc_Typ : Entity_Id;
848 Param : Node_Id;
849 Param_Typ : Entity_Id;
851 begin
852 -- Find the _object parameter representing the protected object
854 Param := First (Parameter_Specifications (Spec));
855 loop
856 Param_Typ := Etype (Parameter_Type (Param));
858 if Ekind (Param_Typ) = E_Record_Type then
859 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
860 end if;
862 exit when No (Param) or else Present (Conc_Typ);
863 Next (Param);
864 end loop;
866 pragma Assert (Present (Param));
868 -- Historical note: In earlier versions of GNAT, there was code
869 -- at this point to generate stuff to service entry queues. It is
870 -- now abstracted in Build_Protected_Subprogram_Call_Cleanup.
872 Build_Protected_Subprogram_Call_Cleanup
873 (Specification (N), Conc_Typ, Loc, Stmts);
874 end;
876 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
877 -- tasks. Other unactivated tasks are completed by Complete_Task or
878 -- Complete_Master.
880 -- NOTE: The generated code references _chain, a local object
882 elsif Is_Task_Allocation then
884 -- Generate:
885 -- Expunge_Unactivated_Tasks (_chain);
887 -- where _chain is the list of tasks created by the allocator but not
888 -- yet activated. This list will be empty unless the block completes
889 -- abnormally.
891 Append_To (Stmts,
892 Make_Procedure_Call_Statement (Loc,
893 Name =>
894 New_Occurrence_Of
895 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
896 Parameter_Associations => New_List (
897 New_Occurrence_Of (Activation_Chain_Entity (N), Loc))));
899 -- Attempt to cancel an asynchronous entry call whenever the block which
900 -- contains the abortable part is exited.
902 -- NOTE: The generated code references Cnn, a local object
904 elsif Is_Asynchronous_Call then
905 declare
906 Cancel_Param : constant Entity_Id :=
907 Entry_Cancel_Parameter (Entity (Identifier (N)));
909 begin
910 -- If it is of type Communication_Block, this must be a protected
911 -- entry call. Generate:
913 -- if Enqueued (Cancel_Param) then
914 -- Cancel_Protected_Entry_Call (Cancel_Param);
915 -- end if;
917 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
918 Append_To (Stmts,
919 Make_If_Statement (Loc,
920 Condition =>
921 Make_Function_Call (Loc,
922 Name =>
923 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
924 Parameter_Associations => New_List (
925 New_Occurrence_Of (Cancel_Param, Loc))),
927 Then_Statements => New_List (
928 Make_Procedure_Call_Statement (Loc,
929 Name =>
930 New_Occurrence_Of
931 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
932 Parameter_Associations => New_List (
933 New_Occurrence_Of (Cancel_Param, Loc))))));
935 -- Asynchronous delay, generate:
936 -- Cancel_Async_Delay (Cancel_Param);
938 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
939 Append_To (Stmts,
940 Make_Procedure_Call_Statement (Loc,
941 Name =>
942 New_Occurrence_Of (RTE (RE_Cancel_Async_Delay), Loc),
943 Parameter_Associations => New_List (
944 Make_Attribute_Reference (Loc,
945 Prefix =>
946 New_Occurrence_Of (Cancel_Param, Loc),
947 Attribute_Name => Name_Unchecked_Access))));
949 -- Task entry call, generate:
950 -- Cancel_Task_Entry_Call (Cancel_Param);
952 else
953 Append_To (Stmts,
954 Make_Procedure_Call_Statement (Loc,
955 Name =>
956 New_Occurrence_Of (RTE (RE_Cancel_Task_Entry_Call), Loc),
957 Parameter_Associations => New_List (
958 New_Occurrence_Of (Cancel_Param, Loc))));
959 end if;
960 end;
961 end if;
963 Append_List_To (Stmts, Additional_Cleanup);
964 return Stmts;
965 end Build_Cleanup_Statements;
967 -----------------------------
968 -- Build_Controlling_Procs --
969 -----------------------------
971 procedure Build_Controlling_Procs (Typ : Entity_Id) is
972 begin
973 if Is_Array_Type (Typ) then
974 Build_Array_Deep_Procs (Typ);
975 else pragma Assert (Is_Record_Type (Typ));
976 Build_Record_Deep_Procs (Typ);
977 end if;
978 end Build_Controlling_Procs;
980 -----------------------------
981 -- Build_Exception_Handler --
982 -----------------------------
984 function Build_Exception_Handler
985 (Data : Finalization_Exception_Data;
986 For_Library : Boolean := False) return Node_Id
988 Actuals : List_Id;
989 Proc_To_Call : Entity_Id;
990 Except : Node_Id;
991 Stmts : List_Id;
993 begin
994 pragma Assert (Present (Data.Raised_Id));
996 if Exception_Extra_Info
997 or else (For_Library and not Restricted_Profile)
998 then
999 if Exception_Extra_Info then
1001 -- Generate:
1003 -- Get_Current_Excep.all
1005 Except :=
1006 Make_Function_Call (Data.Loc,
1007 Name =>
1008 Make_Explicit_Dereference (Data.Loc,
1009 Prefix =>
1010 New_Occurrence_Of
1011 (RTE (RE_Get_Current_Excep), Data.Loc)));
1013 else
1014 -- Generate:
1016 -- null
1018 Except := Make_Null (Data.Loc);
1019 end if;
1021 if For_Library and then not Restricted_Profile then
1022 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
1023 Actuals := New_List (Except);
1025 else
1026 Proc_To_Call := RTE (RE_Save_Occurrence);
1028 -- The dereference occurs only when Exception_Extra_Info is true,
1029 -- and therefore Except is not null.
1031 Actuals :=
1032 New_List (
1033 New_Occurrence_Of (Data.E_Id, Data.Loc),
1034 Make_Explicit_Dereference (Data.Loc, Except));
1035 end if;
1037 -- Generate:
1039 -- when others =>
1040 -- if not Raised_Id then
1041 -- Raised_Id := True;
1043 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
1044 -- or
1045 -- Save_Library_Occurrence (Get_Current_Excep.all);
1046 -- end if;
1048 Stmts :=
1049 New_List (
1050 Make_If_Statement (Data.Loc,
1051 Condition =>
1052 Make_Op_Not (Data.Loc,
1053 Right_Opnd => New_Occurrence_Of (Data.Raised_Id, Data.Loc)),
1055 Then_Statements => New_List (
1056 Make_Assignment_Statement (Data.Loc,
1057 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1058 Expression => New_Occurrence_Of (Standard_True, Data.Loc)),
1060 Make_Procedure_Call_Statement (Data.Loc,
1061 Name =>
1062 New_Occurrence_Of (Proc_To_Call, Data.Loc),
1063 Parameter_Associations => Actuals))));
1065 else
1066 -- Generate:
1068 -- Raised_Id := True;
1070 Stmts := New_List (
1071 Make_Assignment_Statement (Data.Loc,
1072 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1073 Expression => New_Occurrence_Of (Standard_True, Data.Loc)));
1074 end if;
1076 -- Generate:
1078 -- when others =>
1080 return
1081 Make_Exception_Handler (Data.Loc,
1082 Exception_Choices => New_List (Make_Others_Choice (Data.Loc)),
1083 Statements => Stmts);
1084 end Build_Exception_Handler;
1086 -------------------------------
1087 -- Build_Finalization_Master --
1088 -------------------------------
1090 procedure Build_Finalization_Master
1091 (Typ : Entity_Id;
1092 For_Lib_Level : Boolean := False;
1093 For_Private : Boolean := False;
1094 Context_Scope : Entity_Id := Empty;
1095 Insertion_Node : Node_Id := Empty)
1097 procedure Add_Pending_Access_Type
1098 (Typ : Entity_Id;
1099 Ptr_Typ : Entity_Id);
1100 -- Add access type Ptr_Typ to the pending access type list for type Typ
1102 -----------------------------
1103 -- Add_Pending_Access_Type --
1104 -----------------------------
1106 procedure Add_Pending_Access_Type
1107 (Typ : Entity_Id;
1108 Ptr_Typ : Entity_Id)
1110 List : Elist_Id;
1112 begin
1113 if Present (Pending_Access_Types (Typ)) then
1114 List := Pending_Access_Types (Typ);
1115 else
1116 List := New_Elmt_List;
1117 Set_Pending_Access_Types (Typ, List);
1118 end if;
1120 Prepend_Elmt (Ptr_Typ, List);
1121 end Add_Pending_Access_Type;
1123 -- Local variables
1125 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
1127 Ptr_Typ : constant Entity_Id := Root_Type_Of_Full_View (Base_Type (Typ));
1128 -- A finalization master created for a named access type is associated
1129 -- with the full view (if applicable) as a consequence of freezing. The
1130 -- full view criteria does not apply to anonymous access types because
1131 -- those cannot have a private and a full view.
1133 -- Start of processing for Build_Finalization_Master
1135 begin
1136 -- Nothing to do if the circumstances do not allow for a finalization
1137 -- master.
1139 if not Allows_Finalization_Master (Typ) then
1140 return;
1142 -- Various machinery such as freezing may have already created a
1143 -- finalization master.
1145 elsif Present (Finalization_Master (Ptr_Typ)) then
1146 return;
1147 end if;
1149 declare
1150 Actions : constant List_Id := New_List;
1151 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
1152 Fin_Mas_Id : Entity_Id;
1153 Pool_Id : Entity_Id;
1155 begin
1156 -- Source access types use fixed master names since the master is
1157 -- inserted in the same source unit only once. The only exception to
1158 -- this are instances using the same access type as generic actual.
1160 if Comes_From_Source (Ptr_Typ) and then not Inside_A_Generic then
1161 Fin_Mas_Id :=
1162 Make_Defining_Identifier (Loc,
1163 Chars => New_External_Name (Chars (Ptr_Typ), "FM"));
1165 -- Internally generated access types use temporaries as their names
1166 -- due to possible collision with identical names coming from other
1167 -- packages.
1169 else
1170 Fin_Mas_Id := Make_Temporary (Loc, 'F');
1171 end if;
1173 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
1175 -- Generate:
1176 -- <Ptr_Typ>FM : aliased Finalization_Master;
1178 Append_To (Actions,
1179 Make_Object_Declaration (Loc,
1180 Defining_Identifier => Fin_Mas_Id,
1181 Aliased_Present => True,
1182 Object_Definition =>
1183 New_Occurrence_Of (RTE (RE_Finalization_Master), Loc)));
1185 -- Set the associated pool and primitive Finalize_Address of the new
1186 -- finalization master.
1188 -- The access type has a user-defined storage pool, use it
1190 if Present (Associated_Storage_Pool (Ptr_Typ)) then
1191 Pool_Id := Associated_Storage_Pool (Ptr_Typ);
1193 -- Otherwise the default choice is the global storage pool
1195 else
1196 Pool_Id := RTE (RE_Global_Pool_Object);
1197 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
1198 end if;
1200 -- Generate:
1201 -- Set_Base_Pool (<Ptr_Typ>FM, Pool_Id'Unchecked_Access);
1203 Append_To (Actions,
1204 Make_Procedure_Call_Statement (Loc,
1205 Name =>
1206 New_Occurrence_Of (RTE (RE_Set_Base_Pool), Loc),
1207 Parameter_Associations => New_List (
1208 New_Occurrence_Of (Fin_Mas_Id, Loc),
1209 Make_Attribute_Reference (Loc,
1210 Prefix => New_Occurrence_Of (Pool_Id, Loc),
1211 Attribute_Name => Name_Unrestricted_Access))));
1213 -- Finalize_Address is not generated in CodePeer mode because the
1214 -- body contains address arithmetic. Skip this step.
1216 if CodePeer_Mode then
1217 null;
1219 -- Associate the Finalize_Address primitive of the designated type
1220 -- with the finalization master of the access type. The designated
1221 -- type must be forzen as Finalize_Address is generated when the
1222 -- freeze node is expanded.
1224 elsif Is_Frozen (Desig_Typ)
1225 and then Present (Finalize_Address (Desig_Typ))
1227 -- The finalization master of an anonymous access type may need
1228 -- to be inserted in a specific place in the tree. For instance:
1230 -- type Comp_Typ;
1232 -- <finalization master of "access Comp_Typ">
1234 -- type Rec_Typ is record
1235 -- Comp : access Comp_Typ;
1236 -- end record;
1238 -- <freeze node for Comp_Typ>
1239 -- <freeze node for Rec_Typ>
1241 -- Due to this oddity, the anonymous access type is stored for
1242 -- later processing (see below).
1244 and then Ekind (Ptr_Typ) /= E_Anonymous_Access_Type
1245 then
1246 -- Generate:
1247 -- Set_Finalize_Address
1248 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
1250 Append_To (Actions,
1251 Make_Set_Finalize_Address_Call
1252 (Loc => Loc,
1253 Ptr_Typ => Ptr_Typ));
1255 -- Otherwise the designated type is either anonymous access or a
1256 -- Taft-amendment type and has not been frozen. Store the access
1257 -- type for later processing (see Freeze_Type).
1259 else
1260 Add_Pending_Access_Type (Desig_Typ, Ptr_Typ);
1261 end if;
1263 -- A finalization master created for an access designating a type
1264 -- with private components is inserted before a context-dependent
1265 -- node.
1267 if For_Private then
1269 -- At this point both the scope of the context and the insertion
1270 -- mode must be known.
1272 pragma Assert (Present (Context_Scope));
1273 pragma Assert (Present (Insertion_Node));
1275 Push_Scope (Context_Scope);
1277 -- Treat use clauses as declarations and insert directly in front
1278 -- of them.
1280 if Nkind_In (Insertion_Node, N_Use_Package_Clause,
1281 N_Use_Type_Clause)
1282 then
1283 Insert_List_Before_And_Analyze (Insertion_Node, Actions);
1284 else
1285 Insert_Actions (Insertion_Node, Actions);
1286 end if;
1288 Pop_Scope;
1290 -- The finalization master belongs to an access result type related
1291 -- to a build-in-place function call used to initialize a library
1292 -- level object. The master must be inserted in front of the access
1293 -- result type declaration denoted by Insertion_Node.
1295 elsif For_Lib_Level then
1296 pragma Assert (Present (Insertion_Node));
1297 Insert_Actions (Insertion_Node, Actions);
1299 -- Otherwise the finalization master and its initialization become a
1300 -- part of the freeze node.
1302 else
1303 Append_Freeze_Actions (Ptr_Typ, Actions);
1304 end if;
1305 end;
1306 end Build_Finalization_Master;
1308 ---------------------
1309 -- Build_Finalizer --
1310 ---------------------
1312 procedure Build_Finalizer
1313 (N : Node_Id;
1314 Clean_Stmts : List_Id;
1315 Mark_Id : Entity_Id;
1316 Top_Decls : List_Id;
1317 Defer_Abort : Boolean;
1318 Fin_Id : out Entity_Id)
1320 Acts_As_Clean : constant Boolean :=
1321 Present (Mark_Id)
1322 or else
1323 (Present (Clean_Stmts)
1324 and then Is_Non_Empty_List (Clean_Stmts));
1325 Exceptions_OK : constant Boolean :=
1326 not Restriction_Active (No_Exception_Propagation);
1327 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1328 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1329 For_Package : constant Boolean :=
1330 For_Package_Body or else For_Package_Spec;
1331 Loc : constant Source_Ptr := Sloc (N);
1333 -- NOTE: Local variable declarations are conservative and do not create
1334 -- structures right from the start. Entities and lists are created once
1335 -- it has been established that N has at least one controlled object.
1337 Components_Built : Boolean := False;
1338 -- A flag used to avoid double initialization of entities and lists. If
1339 -- the flag is set then the following variables have been initialized:
1340 -- Counter_Id
1341 -- Finalizer_Decls
1342 -- Finalizer_Stmts
1343 -- Jump_Alts
1345 Counter_Id : Entity_Id := Empty;
1346 Counter_Val : Nat := 0;
1347 -- Name and value of the state counter
1349 Decls : List_Id := No_List;
1350 -- Declarative region of N (if available). If N is a package declaration
1351 -- Decls denotes the visible declarations.
1353 Finalizer_Data : Finalization_Exception_Data;
1354 -- Data for the exception
1356 Finalizer_Decls : List_Id := No_List;
1357 -- Local variable declarations. This list holds the label declarations
1358 -- of all jump block alternatives as well as the declaration of the
1359 -- local exception occurrence and the raised flag:
1360 -- E : Exception_Occurrence;
1361 -- Raised : Boolean := False;
1362 -- L<counter value> : label;
1364 Finalizer_Insert_Nod : Node_Id := Empty;
1365 -- Insertion point for the finalizer body. Depending on the context
1366 -- (Nkind of N) and the individual grouping of controlled objects, this
1367 -- node may denote a package declaration or body, package instantiation,
1368 -- block statement or a counter update statement.
1370 Finalizer_Stmts : List_Id := No_List;
1371 -- The statement list of the finalizer body. It contains the following:
1373 -- Abort_Defer; -- Added if abort is allowed
1374 -- <call to Prev_At_End> -- Added if exists
1375 -- <cleanup statements> -- Added if Acts_As_Clean
1376 -- <jump block> -- Added if Has_Ctrl_Objs
1377 -- <finalization statements> -- Added if Has_Ctrl_Objs
1378 -- <stack release> -- Added if Mark_Id exists
1379 -- Abort_Undefer; -- Added if abort is allowed
1381 Has_Ctrl_Objs : Boolean := False;
1382 -- A general flag which denotes whether N has at least one controlled
1383 -- object.
1385 Has_Tagged_Types : Boolean := False;
1386 -- A general flag which indicates whether N has at least one library-
1387 -- level tagged type declaration.
1389 HSS : Node_Id := Empty;
1390 -- The sequence of statements of N (if available)
1392 Jump_Alts : List_Id := No_List;
1393 -- Jump block alternatives. Depending on the value of the state counter,
1394 -- the control flow jumps to a sequence of finalization statements. This
1395 -- list contains the following:
1397 -- when <counter value> =>
1398 -- goto L<counter value>;
1400 Jump_Block_Insert_Nod : Node_Id := Empty;
1401 -- Specific point in the finalizer statements where the jump block is
1402 -- inserted.
1404 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1405 -- The last controlled construct encountered when processing the top
1406 -- level lists of N. This can be a nested package, an instantiation or
1407 -- an object declaration.
1409 Prev_At_End : Entity_Id := Empty;
1410 -- The previous at end procedure of the handled statements block of N
1412 Priv_Decls : List_Id := No_List;
1413 -- The private declarations of N if N is a package declaration
1415 Spec_Id : Entity_Id := Empty;
1416 Spec_Decls : List_Id := Top_Decls;
1417 Stmts : List_Id := No_List;
1419 Tagged_Type_Stmts : List_Id := No_List;
1420 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1421 -- tagged types found in N.
1423 -----------------------
1424 -- Local subprograms --
1425 -----------------------
1427 procedure Build_Components;
1428 -- Create all entites and initialize all lists used in the creation of
1429 -- the finalizer.
1431 procedure Create_Finalizer;
1432 -- Create the spec and body of the finalizer and insert them in the
1433 -- proper place in the tree depending on the context.
1435 procedure Process_Declarations
1436 (Decls : List_Id;
1437 Preprocess : Boolean := False;
1438 Top_Level : Boolean := False);
1439 -- Inspect a list of declarations or statements which may contain
1440 -- objects that need finalization. When flag Preprocess is set, the
1441 -- routine will simply count the total number of controlled objects in
1442 -- Decls. Flag Top_Level denotes whether the processing is done for
1443 -- objects in nested package declarations or instances.
1445 procedure Process_Object_Declaration
1446 (Decl : Node_Id;
1447 Has_No_Init : Boolean := False;
1448 Is_Protected : Boolean := False);
1449 -- Generate all the machinery associated with the finalization of a
1450 -- single object. Flag Has_No_Init is used to denote certain contexts
1451 -- where Decl does not have initialization call(s). Flag Is_Protected
1452 -- is set when Decl denotes a simple protected object.
1454 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1455 -- Generate all the code necessary to unregister the external tag of a
1456 -- tagged type.
1458 ----------------------
1459 -- Build_Components --
1460 ----------------------
1462 procedure Build_Components is
1463 Counter_Decl : Node_Id;
1464 Counter_Typ : Entity_Id;
1465 Counter_Typ_Decl : Node_Id;
1467 begin
1468 pragma Assert (Present (Decls));
1470 -- This routine might be invoked several times when dealing with
1471 -- constructs that have two lists (either two declarative regions
1472 -- or declarations and statements). Avoid double initialization.
1474 if Components_Built then
1475 return;
1476 end if;
1478 Components_Built := True;
1480 if Has_Ctrl_Objs then
1482 -- Create entities for the counter, its type, the local exception
1483 -- and the raised flag.
1485 Counter_Id := Make_Temporary (Loc, 'C');
1486 Counter_Typ := Make_Temporary (Loc, 'T');
1488 Finalizer_Decls := New_List;
1490 Build_Object_Declarations
1491 (Finalizer_Data, Finalizer_Decls, Loc, For_Package);
1493 -- Since the total number of controlled objects is always known,
1494 -- build a subtype of Natural with precise bounds. This allows
1495 -- the backend to optimize the case statement. Generate:
1497 -- subtype Tnn is Natural range 0 .. Counter_Val;
1499 Counter_Typ_Decl :=
1500 Make_Subtype_Declaration (Loc,
1501 Defining_Identifier => Counter_Typ,
1502 Subtype_Indication =>
1503 Make_Subtype_Indication (Loc,
1504 Subtype_Mark => New_Occurrence_Of (Standard_Natural, Loc),
1505 Constraint =>
1506 Make_Range_Constraint (Loc,
1507 Range_Expression =>
1508 Make_Range (Loc,
1509 Low_Bound =>
1510 Make_Integer_Literal (Loc, Uint_0),
1511 High_Bound =>
1512 Make_Integer_Literal (Loc, Counter_Val)))));
1514 -- Generate the declaration of the counter itself:
1516 -- Counter : Integer := 0;
1518 Counter_Decl :=
1519 Make_Object_Declaration (Loc,
1520 Defining_Identifier => Counter_Id,
1521 Object_Definition => New_Occurrence_Of (Counter_Typ, Loc),
1522 Expression => Make_Integer_Literal (Loc, 0));
1524 -- Set the type of the counter explicitly to prevent errors when
1525 -- examining object declarations later on.
1527 Set_Etype (Counter_Id, Counter_Typ);
1529 -- The counter and its type are inserted before the source
1530 -- declarations of N.
1532 Prepend_To (Decls, Counter_Decl);
1533 Prepend_To (Decls, Counter_Typ_Decl);
1535 -- The counter and its associated type must be manually analyzed
1536 -- since N has already been analyzed. Use the scope of the spec
1537 -- when inserting in a package.
1539 if For_Package then
1540 Push_Scope (Spec_Id);
1541 Analyze (Counter_Typ_Decl);
1542 Analyze (Counter_Decl);
1543 Pop_Scope;
1545 else
1546 Analyze (Counter_Typ_Decl);
1547 Analyze (Counter_Decl);
1548 end if;
1550 Jump_Alts := New_List;
1551 end if;
1553 -- If the context requires additional clean up, the finalization
1554 -- machinery is added after the clean up code.
1556 if Acts_As_Clean then
1557 Finalizer_Stmts := Clean_Stmts;
1558 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1559 else
1560 Finalizer_Stmts := New_List;
1561 end if;
1563 if Has_Tagged_Types then
1564 Tagged_Type_Stmts := New_List;
1565 end if;
1566 end Build_Components;
1568 ----------------------
1569 -- Create_Finalizer --
1570 ----------------------
1572 procedure Create_Finalizer is
1573 function New_Finalizer_Name return Name_Id;
1574 -- Create a fully qualified name of a package spec or body finalizer.
1575 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1577 ------------------------
1578 -- New_Finalizer_Name --
1579 ------------------------
1581 function New_Finalizer_Name return Name_Id is
1582 procedure New_Finalizer_Name (Id : Entity_Id);
1583 -- Place "__<name-of-Id>" in the name buffer. If the identifier
1584 -- has a non-standard scope, process the scope first.
1586 ------------------------
1587 -- New_Finalizer_Name --
1588 ------------------------
1590 procedure New_Finalizer_Name (Id : Entity_Id) is
1591 begin
1592 if Scope (Id) = Standard_Standard then
1593 Get_Name_String (Chars (Id));
1595 else
1596 New_Finalizer_Name (Scope (Id));
1597 Add_Str_To_Name_Buffer ("__");
1598 Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1599 end if;
1600 end New_Finalizer_Name;
1602 -- Start of processing for New_Finalizer_Name
1604 begin
1605 -- Create the fully qualified name of the enclosing scope
1607 New_Finalizer_Name (Spec_Id);
1609 -- Generate:
1610 -- __finalize_[spec|body]
1612 Add_Str_To_Name_Buffer ("__finalize_");
1614 if For_Package_Spec then
1615 Add_Str_To_Name_Buffer ("spec");
1616 else
1617 Add_Str_To_Name_Buffer ("body");
1618 end if;
1620 return Name_Find;
1621 end New_Finalizer_Name;
1623 -- Local variables
1625 Body_Id : Entity_Id;
1626 Fin_Body : Node_Id;
1627 Fin_Spec : Node_Id;
1628 Jump_Block : Node_Id;
1629 Label : Node_Id;
1630 Label_Id : Entity_Id;
1632 -- Start of processing for Create_Finalizer
1634 begin
1635 -- Step 1: Creation of the finalizer name
1637 -- Packages must use a distinct name for their finalizers since the
1638 -- binder will have to generate calls to them by name. The name is
1639 -- of the following form:
1641 -- xx__yy__finalize_[spec|body]
1643 if For_Package then
1644 Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1645 Set_Has_Qualified_Name (Fin_Id);
1646 Set_Has_Fully_Qualified_Name (Fin_Id);
1648 -- The default name is _finalizer
1650 else
1651 Fin_Id :=
1652 Make_Defining_Identifier (Loc,
1653 Chars => New_External_Name (Name_uFinalizer));
1655 -- The visibility semantics of AT_END handlers force a strange
1656 -- separation of spec and body for stack-related finalizers:
1658 -- declare : Enclosing_Scope
1659 -- procedure _finalizer;
1660 -- begin
1661 -- <controlled objects>
1662 -- procedure _finalizer is
1663 -- ...
1664 -- at end
1665 -- _finalizer;
1666 -- end;
1668 -- Both spec and body are within the same construct and scope, but
1669 -- the body is part of the handled sequence of statements. This
1670 -- placement confuses the elaboration mechanism on targets where
1671 -- AT_END handlers are expanded into "when all others" handlers:
1673 -- exception
1674 -- when all others =>
1675 -- _finalizer; -- appears to require elab checks
1676 -- at end
1677 -- _finalizer;
1678 -- end;
1680 -- Since the compiler guarantees that the body of a _finalizer is
1681 -- always inserted in the same construct where the AT_END handler
1682 -- resides, there is no need for elaboration checks.
1684 Set_Kill_Elaboration_Checks (Fin_Id);
1686 -- Inlining the finalizer produces a substantial speedup at -O2.
1687 -- It is inlined by default at -O3. Either way, it is called
1688 -- exactly twice (once on the normal path, and once for
1689 -- exceptions/abort), so this won't bloat the code too much.
1691 Set_Is_Inlined (Fin_Id);
1692 end if;
1694 -- Step 2: Creation of the finalizer specification
1696 -- Generate:
1697 -- procedure Fin_Id;
1699 Fin_Spec :=
1700 Make_Subprogram_Declaration (Loc,
1701 Specification =>
1702 Make_Procedure_Specification (Loc,
1703 Defining_Unit_Name => Fin_Id));
1705 -- Step 3: Creation of the finalizer body
1707 if Has_Ctrl_Objs then
1709 -- Add L0, the default destination to the jump block
1711 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1712 Set_Entity (Label_Id,
1713 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1714 Label := Make_Label (Loc, Label_Id);
1716 -- Generate:
1717 -- L0 : label;
1719 Prepend_To (Finalizer_Decls,
1720 Make_Implicit_Label_Declaration (Loc,
1721 Defining_Identifier => Entity (Label_Id),
1722 Label_Construct => Label));
1724 -- Generate:
1725 -- when others =>
1726 -- goto L0;
1728 Append_To (Jump_Alts,
1729 Make_Case_Statement_Alternative (Loc,
1730 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1731 Statements => New_List (
1732 Make_Goto_Statement (Loc,
1733 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
1735 -- Generate:
1736 -- <<L0>>
1738 Append_To (Finalizer_Stmts, Label);
1740 -- Create the jump block which controls the finalization flow
1741 -- depending on the value of the state counter.
1743 Jump_Block :=
1744 Make_Case_Statement (Loc,
1745 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
1746 Alternatives => Jump_Alts);
1748 if Acts_As_Clean and then Present (Jump_Block_Insert_Nod) then
1749 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1750 else
1751 Prepend_To (Finalizer_Stmts, Jump_Block);
1752 end if;
1753 end if;
1755 -- Add the library-level tagged type unregistration machinery before
1756 -- the jump block circuitry. This ensures that external tags will be
1757 -- removed even if a finalization exception occurs at some point.
1759 if Has_Tagged_Types then
1760 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1761 end if;
1763 -- Add a call to the previous At_End handler if it exists. The call
1764 -- must always precede the jump block.
1766 if Present (Prev_At_End) then
1767 Prepend_To (Finalizer_Stmts,
1768 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1770 -- Clear the At_End handler since we have already generated the
1771 -- proper replacement call for it.
1773 Set_At_End_Proc (HSS, Empty);
1774 end if;
1776 -- Release the secondary stack mark
1778 if Present (Mark_Id) then
1779 Append_To (Finalizer_Stmts, Build_SS_Release_Call (Loc, Mark_Id));
1780 end if;
1782 -- Protect the statements with abort defer/undefer. This is only when
1783 -- aborts are allowed and the clean up statements require deferral or
1784 -- there are controlled objects to be finalized. Note that the abort
1785 -- defer/undefer pair does not require an extra block because each
1786 -- finalization exception is caught in its corresponding finalization
1787 -- block. As a result, the call to Abort_Defer always takes place.
1789 if Abort_Allowed and then (Defer_Abort or Has_Ctrl_Objs) then
1790 Prepend_To (Finalizer_Stmts,
1791 Build_Runtime_Call (Loc, RE_Abort_Defer));
1793 Append_To (Finalizer_Stmts,
1794 Build_Runtime_Call (Loc, RE_Abort_Undefer));
1795 end if;
1797 -- The local exception does not need to be reraised for library-level
1798 -- finalizers. Note that this action must be carried out after object
1799 -- clean up, secondary stack release and abort undeferral. Generate:
1801 -- if Raised and then not Abort then
1802 -- Raise_From_Controlled_Operation (E);
1803 -- end if;
1805 if Has_Ctrl_Objs and Exceptions_OK and not For_Package then
1806 Append_To (Finalizer_Stmts,
1807 Build_Raise_Statement (Finalizer_Data));
1808 end if;
1810 -- Generate:
1811 -- procedure Fin_Id is
1812 -- Abort : constant Boolean := Triggered_By_Abort;
1813 -- <or>
1814 -- Abort : constant Boolean := False; -- no abort
1816 -- E : Exception_Occurrence; -- All added if flag
1817 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1818 -- L0 : label;
1819 -- ...
1820 -- Lnn : label;
1822 -- begin
1823 -- Abort_Defer; -- Added if abort is allowed
1824 -- <call to Prev_At_End> -- Added if exists
1825 -- <cleanup statements> -- Added if Acts_As_Clean
1826 -- <jump block> -- Added if Has_Ctrl_Objs
1827 -- <finalization statements> -- Added if Has_Ctrl_Objs
1828 -- <stack release> -- Added if Mark_Id exists
1829 -- Abort_Undefer; -- Added if abort is allowed
1830 -- <exception propagation> -- Added if Has_Ctrl_Objs
1831 -- end Fin_Id;
1833 -- Create the body of the finalizer
1835 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1837 if For_Package then
1838 Set_Has_Qualified_Name (Body_Id);
1839 Set_Has_Fully_Qualified_Name (Body_Id);
1840 end if;
1842 Fin_Body :=
1843 Make_Subprogram_Body (Loc,
1844 Specification =>
1845 Make_Procedure_Specification (Loc,
1846 Defining_Unit_Name => Body_Id),
1847 Declarations => Finalizer_Decls,
1848 Handled_Statement_Sequence =>
1849 Make_Handled_Sequence_Of_Statements (Loc,
1850 Statements => Finalizer_Stmts));
1852 -- Step 4: Spec and body insertion, analysis
1854 if For_Package then
1856 -- If the package spec has private declarations, the finalizer
1857 -- body must be added to the end of the list in order to have
1858 -- visibility of all private controlled objects.
1860 if For_Package_Spec then
1861 if Present (Priv_Decls) then
1862 Append_To (Priv_Decls, Fin_Spec);
1863 Append_To (Priv_Decls, Fin_Body);
1864 else
1865 Append_To (Decls, Fin_Spec);
1866 Append_To (Decls, Fin_Body);
1867 end if;
1869 -- For package bodies, both the finalizer spec and body are
1870 -- inserted at the end of the package declarations.
1872 else
1873 Append_To (Decls, Fin_Spec);
1874 Append_To (Decls, Fin_Body);
1875 end if;
1877 -- Push the name of the package
1879 Push_Scope (Spec_Id);
1880 Analyze (Fin_Spec);
1881 Analyze (Fin_Body);
1882 Pop_Scope;
1884 -- Non-package case
1886 else
1887 -- Create the spec for the finalizer. The At_End handler must be
1888 -- able to call the body which resides in a nested structure.
1890 -- Generate:
1891 -- declare
1892 -- procedure Fin_Id; -- Spec
1893 -- begin
1894 -- <objects and possibly statements>
1895 -- procedure Fin_Id is ... -- Body
1896 -- <statements>
1897 -- at end
1898 -- Fin_Id; -- At_End handler
1899 -- end;
1901 pragma Assert (Present (Spec_Decls));
1903 Append_To (Spec_Decls, Fin_Spec);
1904 Analyze (Fin_Spec);
1906 -- When the finalizer acts solely as a clean up routine, the body
1907 -- is inserted right after the spec.
1909 if Acts_As_Clean and not Has_Ctrl_Objs then
1910 Insert_After (Fin_Spec, Fin_Body);
1912 -- In all other cases the body is inserted after either:
1914 -- 1) The counter update statement of the last controlled object
1915 -- 2) The last top level nested controlled package
1916 -- 3) The last top level controlled instantiation
1918 else
1919 -- Manually freeze the spec. This is somewhat of a hack because
1920 -- a subprogram is frozen when its body is seen and the freeze
1921 -- node appears right before the body. However, in this case,
1922 -- the spec must be frozen earlier since the At_End handler
1923 -- must be able to call it.
1925 -- declare
1926 -- procedure Fin_Id; -- Spec
1927 -- [Fin_Id] -- Freeze node
1928 -- begin
1929 -- ...
1930 -- at end
1931 -- Fin_Id; -- At_End handler
1932 -- end;
1934 Ensure_Freeze_Node (Fin_Id);
1935 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1936 Set_Is_Frozen (Fin_Id);
1938 -- In the case where the last construct to contain a controlled
1939 -- object is either a nested package, an instantiation or a
1940 -- freeze node, the body must be inserted directly after the
1941 -- construct.
1943 if Nkind_In (Last_Top_Level_Ctrl_Construct,
1944 N_Freeze_Entity,
1945 N_Package_Declaration,
1946 N_Package_Body)
1947 then
1948 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1949 end if;
1951 Insert_After (Finalizer_Insert_Nod, Fin_Body);
1952 end if;
1954 Analyze (Fin_Body);
1955 end if;
1956 end Create_Finalizer;
1958 --------------------------
1959 -- Process_Declarations --
1960 --------------------------
1962 procedure Process_Declarations
1963 (Decls : List_Id;
1964 Preprocess : Boolean := False;
1965 Top_Level : Boolean := False)
1967 Decl : Node_Id;
1968 Expr : Node_Id;
1969 Obj_Id : Entity_Id;
1970 Obj_Typ : Entity_Id;
1971 Pack_Id : Entity_Id;
1972 Spec : Node_Id;
1973 Typ : Entity_Id;
1975 Old_Counter_Val : Nat;
1976 -- This variable is used to determine whether a nested package or
1977 -- instance contains at least one controlled object.
1979 procedure Processing_Actions
1980 (Has_No_Init : Boolean := False;
1981 Is_Protected : Boolean := False);
1982 -- Depending on the mode of operation of Process_Declarations, either
1983 -- increment the controlled object counter, set the controlled object
1984 -- flag and store the last top level construct or process the current
1985 -- declaration. Flag Has_No_Init is used to propagate scenarios where
1986 -- the current declaration may not have initialization proc(s). Flag
1987 -- Is_Protected should be set when the current declaration denotes a
1988 -- simple protected object.
1990 ------------------------
1991 -- Processing_Actions --
1992 ------------------------
1994 procedure Processing_Actions
1995 (Has_No_Init : Boolean := False;
1996 Is_Protected : Boolean := False)
1998 begin
1999 -- Library-level tagged type
2001 if Nkind (Decl) = N_Full_Type_Declaration then
2002 if Preprocess then
2003 Has_Tagged_Types := True;
2005 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
2006 Last_Top_Level_Ctrl_Construct := Decl;
2007 end if;
2009 else
2010 Process_Tagged_Type_Declaration (Decl);
2011 end if;
2013 -- Controlled object declaration
2015 else
2016 if Preprocess then
2017 Counter_Val := Counter_Val + 1;
2018 Has_Ctrl_Objs := True;
2020 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
2021 Last_Top_Level_Ctrl_Construct := Decl;
2022 end if;
2024 else
2025 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
2026 end if;
2027 end if;
2028 end Processing_Actions;
2030 -- Start of processing for Process_Declarations
2032 begin
2033 if No (Decls) or else Is_Empty_List (Decls) then
2034 return;
2035 end if;
2037 -- Process all declarations in reverse order
2039 Decl := Last_Non_Pragma (Decls);
2040 while Present (Decl) loop
2042 -- Library-level tagged types
2044 if Nkind (Decl) = N_Full_Type_Declaration then
2045 Typ := Defining_Identifier (Decl);
2047 -- Ignored Ghost types do not need any cleanup actions because
2048 -- they will not appear in the final tree.
2050 if Is_Ignored_Ghost_Entity (Typ) then
2051 null;
2053 elsif Is_Tagged_Type (Typ)
2054 and then Is_Library_Level_Entity (Typ)
2055 and then Convention (Typ) = Convention_Ada
2056 and then Present (Access_Disp_Table (Typ))
2057 and then RTE_Available (RE_Register_Tag)
2058 and then not Is_Abstract_Type (Typ)
2059 and then not No_Run_Time_Mode
2060 then
2061 Processing_Actions;
2062 end if;
2064 -- Regular object declarations
2066 elsif Nkind (Decl) = N_Object_Declaration then
2067 Obj_Id := Defining_Identifier (Decl);
2068 Obj_Typ := Base_Type (Etype (Obj_Id));
2069 Expr := Expression (Decl);
2071 -- Bypass any form of processing for objects which have their
2072 -- finalization disabled. This applies only to objects at the
2073 -- library level.
2075 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
2076 null;
2078 -- Finalization of transient objects are treated separately in
2079 -- order to handle sensitive cases. These include:
2081 -- * Aggregate expansion
2082 -- * If, case, and expression with actions expansion
2083 -- * Transient scopes
2085 -- If one of those contexts has marked the transient object as
2086 -- ignored, do not generate finalization actions for it.
2088 elsif Is_Finalized_Transient (Obj_Id)
2089 or else Is_Ignored_Transient (Obj_Id)
2090 then
2091 null;
2093 -- Ignored Ghost objects do not need any cleanup actions
2094 -- because they will not appear in the final tree.
2096 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2097 null;
2099 -- The expansion of iterator loops generates an object
2100 -- declaration where the Ekind is explicitly set to loop
2101 -- parameter. This is to ensure that the loop parameter behaves
2102 -- as a constant from user code point of view. Such object are
2103 -- never controlled and do not require finalization.
2105 elsif Ekind (Obj_Id) = E_Loop_Parameter then
2106 null;
2108 -- The object is of the form:
2109 -- Obj : [constant] Typ [:= Expr];
2111 -- Do not process tag-to-class-wide conversions because they do
2112 -- not yield an object. Do not process the incomplete view of a
2113 -- deferred constant. Note that an object initialized by means
2114 -- of a build-in-place function call may appear as a deferred
2115 -- constant after expansion activities. These kinds of objects
2116 -- must be finalized.
2118 elsif not Is_Imported (Obj_Id)
2119 and then Needs_Finalization (Obj_Typ)
2120 and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id)
2121 and then not (Ekind (Obj_Id) = E_Constant
2122 and then not Has_Completion (Obj_Id)
2123 and then No (BIP_Initialization_Call (Obj_Id)))
2124 then
2125 Processing_Actions;
2127 -- The object is of the form:
2128 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
2130 -- Obj : Access_Typ :=
2131 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
2133 elsif Is_Access_Type (Obj_Typ)
2134 and then Needs_Finalization
2135 (Available_View (Designated_Type (Obj_Typ)))
2136 and then Present (Expr)
2137 and then
2138 (Is_Secondary_Stack_BIP_Func_Call (Expr)
2139 or else
2140 (Is_Non_BIP_Func_Call (Expr)
2141 and then not Is_Related_To_Func_Return (Obj_Id)))
2142 then
2143 Processing_Actions (Has_No_Init => True);
2145 -- Processing for "hook" objects generated for transient
2146 -- objects declared inside an Expression_With_Actions.
2148 elsif Is_Access_Type (Obj_Typ)
2149 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2150 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
2151 N_Object_Declaration
2152 then
2153 Processing_Actions (Has_No_Init => True);
2155 -- Process intermediate results of an if expression with one
2156 -- of the alternatives using a controlled function call.
2158 elsif Is_Access_Type (Obj_Typ)
2159 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2160 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
2161 N_Defining_Identifier
2162 and then Present (Expr)
2163 and then Nkind (Expr) = N_Null
2164 then
2165 Processing_Actions (Has_No_Init => True);
2167 -- Simple protected objects which use type System.Tasking.
2168 -- Protected_Objects.Protection to manage their locks should
2169 -- be treated as controlled since they require manual cleanup.
2170 -- The only exception is illustrated in the following example:
2172 -- package Pkg is
2173 -- type Ctrl is new Controlled ...
2174 -- procedure Finalize (Obj : in out Ctrl);
2175 -- Lib_Obj : Ctrl;
2176 -- end Pkg;
2178 -- package body Pkg is
2179 -- protected Prot is
2180 -- procedure Do_Something (Obj : in out Ctrl);
2181 -- end Prot;
2183 -- protected body Prot is
2184 -- procedure Do_Something (Obj : in out Ctrl) is ...
2185 -- end Prot;
2187 -- procedure Finalize (Obj : in out Ctrl) is
2188 -- begin
2189 -- Prot.Do_Something (Obj);
2190 -- end Finalize;
2191 -- end Pkg;
2193 -- Since for the most part entities in package bodies depend on
2194 -- those in package specs, Prot's lock should be cleaned up
2195 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
2196 -- This act however attempts to invoke Do_Something and fails
2197 -- because the lock has disappeared.
2199 elsif Ekind (Obj_Id) = E_Variable
2200 and then not In_Library_Level_Package_Body (Obj_Id)
2201 and then (Is_Simple_Protected_Type (Obj_Typ)
2202 or else Has_Simple_Protected_Object (Obj_Typ))
2203 then
2204 Processing_Actions (Is_Protected => True);
2205 end if;
2207 -- Specific cases of object renamings
2209 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
2210 Obj_Id := Defining_Identifier (Decl);
2211 Obj_Typ := Base_Type (Etype (Obj_Id));
2213 -- Bypass any form of processing for objects which have their
2214 -- finalization disabled. This applies only to objects at the
2215 -- library level.
2217 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
2218 null;
2220 -- Ignored Ghost object renamings do not need any cleanup
2221 -- actions because they will not appear in the final tree.
2223 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2224 null;
2226 -- Return object of a build-in-place function. This case is
2227 -- recognized and marked by the expansion of an extended return
2228 -- statement (see Expand_N_Extended_Return_Statement).
2230 elsif Needs_Finalization (Obj_Typ)
2231 and then Is_Return_Object (Obj_Id)
2232 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2233 then
2234 Processing_Actions (Has_No_Init => True);
2236 -- Detect a case where a source object has been initialized by
2237 -- a controlled function call or another object which was later
2238 -- rewritten as a class-wide conversion of Ada.Tags.Displace.
2240 -- Obj1 : CW_Type := Src_Obj;
2241 -- Obj2 : CW_Type := Function_Call (...);
2243 -- Obj1 : CW_Type renames (... Ada.Tags.Displace (Src_Obj));
2244 -- Tmp : ... := Function_Call (...)'reference;
2245 -- Obj2 : CW_Type renames (... Ada.Tags.Displace (Tmp));
2247 elsif Is_Displacement_Of_Object_Or_Function_Result (Obj_Id) then
2248 Processing_Actions (Has_No_Init => True);
2249 end if;
2251 -- Inspect the freeze node of an access-to-controlled type and
2252 -- look for a delayed finalization master. This case arises when
2253 -- the freeze actions are inserted at a later time than the
2254 -- expansion of the context. Since Build_Finalizer is never called
2255 -- on a single construct twice, the master will be ultimately
2256 -- left out and never finalized. This is also needed for freeze
2257 -- actions of designated types themselves, since in some cases the
2258 -- finalization master is associated with a designated type's
2259 -- freeze node rather than that of the access type (see handling
2260 -- for freeze actions in Build_Finalization_Master).
2262 elsif Nkind (Decl) = N_Freeze_Entity
2263 and then Present (Actions (Decl))
2264 then
2265 Typ := Entity (Decl);
2267 -- Freeze nodes for ignored Ghost types do not need cleanup
2268 -- actions because they will never appear in the final tree.
2270 if Is_Ignored_Ghost_Entity (Typ) then
2271 null;
2273 elsif (Is_Access_Type (Typ)
2274 and then not Is_Access_Subprogram_Type (Typ)
2275 and then Needs_Finalization
2276 (Available_View (Designated_Type (Typ))))
2277 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
2278 then
2279 Old_Counter_Val := Counter_Val;
2281 -- Freeze nodes are considered to be identical to packages
2282 -- and blocks in terms of nesting. The difference is that
2283 -- a finalization master created inside the freeze node is
2284 -- at the same nesting level as the node itself.
2286 Process_Declarations (Actions (Decl), Preprocess);
2288 -- The freeze node contains a finalization master
2290 if Preprocess
2291 and then Top_Level
2292 and then No (Last_Top_Level_Ctrl_Construct)
2293 and then Counter_Val > Old_Counter_Val
2294 then
2295 Last_Top_Level_Ctrl_Construct := Decl;
2296 end if;
2297 end if;
2299 -- Nested package declarations, avoid generics
2301 elsif Nkind (Decl) = N_Package_Declaration then
2302 Pack_Id := Defining_Entity (Decl);
2303 Spec := Specification (Decl);
2305 -- Do not inspect an ignored Ghost package because all code
2306 -- found within will not appear in the final tree.
2308 if Is_Ignored_Ghost_Entity (Pack_Id) then
2309 null;
2311 elsif Ekind (Pack_Id) /= E_Generic_Package then
2312 Old_Counter_Val := Counter_Val;
2313 Process_Declarations
2314 (Private_Declarations (Spec), Preprocess);
2315 Process_Declarations
2316 (Visible_Declarations (Spec), Preprocess);
2318 -- Either the visible or the private declarations contain a
2319 -- controlled object. The nested package declaration is the
2320 -- last such construct.
2322 if Preprocess
2323 and then Top_Level
2324 and then No (Last_Top_Level_Ctrl_Construct)
2325 and then Counter_Val > Old_Counter_Val
2326 then
2327 Last_Top_Level_Ctrl_Construct := Decl;
2328 end if;
2329 end if;
2331 -- Nested package bodies, avoid generics
2333 elsif Nkind (Decl) = N_Package_Body then
2335 -- Do not inspect an ignored Ghost package body because all
2336 -- code found within will not appear in the final tree.
2338 if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then
2339 null;
2341 elsif Ekind (Corresponding_Spec (Decl)) /=
2342 E_Generic_Package
2343 then
2344 Old_Counter_Val := Counter_Val;
2345 Process_Declarations (Declarations (Decl), Preprocess);
2347 -- The nested package body is the last construct to contain
2348 -- a controlled object.
2350 if Preprocess
2351 and then Top_Level
2352 and then No (Last_Top_Level_Ctrl_Construct)
2353 and then Counter_Val > Old_Counter_Val
2354 then
2355 Last_Top_Level_Ctrl_Construct := Decl;
2356 end if;
2357 end if;
2359 -- Handle a rare case caused by a controlled transient object
2360 -- created as part of a record init proc. The variable is wrapped
2361 -- in a block, but the block is not associated with a transient
2362 -- scope.
2364 elsif Nkind (Decl) = N_Block_Statement
2365 and then Inside_Init_Proc
2366 then
2367 Old_Counter_Val := Counter_Val;
2369 if Present (Handled_Statement_Sequence (Decl)) then
2370 Process_Declarations
2371 (Statements (Handled_Statement_Sequence (Decl)),
2372 Preprocess);
2373 end if;
2375 Process_Declarations (Declarations (Decl), Preprocess);
2377 -- Either the declaration or statement list of the block has a
2378 -- controlled object.
2380 if Preprocess
2381 and then Top_Level
2382 and then No (Last_Top_Level_Ctrl_Construct)
2383 and then Counter_Val > Old_Counter_Val
2384 then
2385 Last_Top_Level_Ctrl_Construct := Decl;
2386 end if;
2388 -- Handle the case where the original context has been wrapped in
2389 -- a block to avoid interference between exception handlers and
2390 -- At_End handlers. Treat the block as transparent and process its
2391 -- contents.
2393 elsif Nkind (Decl) = N_Block_Statement
2394 and then Is_Finalization_Wrapper (Decl)
2395 then
2396 if Present (Handled_Statement_Sequence (Decl)) then
2397 Process_Declarations
2398 (Statements (Handled_Statement_Sequence (Decl)),
2399 Preprocess);
2400 end if;
2402 Process_Declarations (Declarations (Decl), Preprocess);
2403 end if;
2405 Prev_Non_Pragma (Decl);
2406 end loop;
2407 end Process_Declarations;
2409 --------------------------------
2410 -- Process_Object_Declaration --
2411 --------------------------------
2413 procedure Process_Object_Declaration
2414 (Decl : Node_Id;
2415 Has_No_Init : Boolean := False;
2416 Is_Protected : Boolean := False)
2418 Loc : constant Source_Ptr := Sloc (Decl);
2419 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
2421 Init_Typ : Entity_Id;
2422 -- The initialization type of the related object declaration. Note
2423 -- that this is not necessarily the same type as Obj_Typ because of
2424 -- possible type derivations.
2426 Obj_Typ : Entity_Id;
2427 -- The type of the related object declaration
2429 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2430 -- Func_Id denotes a build-in-place function. Generate the following
2431 -- cleanup code:
2433 -- if BIPallocfrom > Secondary_Stack'Pos
2434 -- and then BIPfinalizationmaster /= null
2435 -- then
2436 -- declare
2437 -- type Ptr_Typ is access Obj_Typ;
2438 -- for Ptr_Typ'Storage_Pool
2439 -- use Base_Pool (BIPfinalizationmaster);
2440 -- begin
2441 -- Free (Ptr_Typ (Temp));
2442 -- end;
2443 -- end if;
2445 -- Obj_Typ is the type of the current object, Temp is the original
2446 -- allocation which Obj_Id renames.
2448 procedure Find_Last_Init
2449 (Last_Init : out Node_Id;
2450 Body_Insert : out Node_Id);
2451 -- Find the last initialization call related to object declaration
2452 -- Decl. Last_Init denotes the last initialization call which follows
2453 -- Decl. Body_Insert denotes a node where the finalizer body could be
2454 -- potentially inserted after (if blocks are involved).
2456 -----------------------------
2457 -- Build_BIP_Cleanup_Stmts --
2458 -----------------------------
2460 function Build_BIP_Cleanup_Stmts
2461 (Func_Id : Entity_Id) return Node_Id
2463 Decls : constant List_Id := New_List;
2464 Fin_Mas_Id : constant Entity_Id :=
2465 Build_In_Place_Formal
2466 (Func_Id, BIP_Finalization_Master);
2467 Func_Typ : constant Entity_Id := Etype (Func_Id);
2468 Temp_Id : constant Entity_Id :=
2469 Entity (Prefix (Name (Parent (Obj_Id))));
2471 Cond : Node_Id;
2472 Free_Blk : Node_Id;
2473 Free_Stmt : Node_Id;
2474 Pool_Id : Entity_Id;
2475 Ptr_Typ : Entity_Id;
2477 begin
2478 -- Generate:
2479 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2481 Pool_Id := Make_Temporary (Loc, 'P');
2483 Append_To (Decls,
2484 Make_Object_Renaming_Declaration (Loc,
2485 Defining_Identifier => Pool_Id,
2486 Subtype_Mark =>
2487 New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
2488 Name =>
2489 Make_Explicit_Dereference (Loc,
2490 Prefix =>
2491 Make_Function_Call (Loc,
2492 Name =>
2493 New_Occurrence_Of (RTE (RE_Base_Pool), Loc),
2494 Parameter_Associations => New_List (
2495 Make_Explicit_Dereference (Loc,
2496 Prefix =>
2497 New_Occurrence_Of (Fin_Mas_Id, Loc)))))));
2499 -- Create an access type which uses the storage pool of the
2500 -- caller's finalization master.
2502 -- Generate:
2503 -- type Ptr_Typ is access Func_Typ;
2505 Ptr_Typ := Make_Temporary (Loc, 'P');
2507 Append_To (Decls,
2508 Make_Full_Type_Declaration (Loc,
2509 Defining_Identifier => Ptr_Typ,
2510 Type_Definition =>
2511 Make_Access_To_Object_Definition (Loc,
2512 Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
2514 -- Perform minor decoration in order to set the master and the
2515 -- storage pool attributes.
2517 Set_Ekind (Ptr_Typ, E_Access_Type);
2518 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
2519 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2521 -- Create an explicit free statement. Note that the free uses the
2522 -- caller's pool expressed as a renaming.
2524 Free_Stmt :=
2525 Make_Free_Statement (Loc,
2526 Expression =>
2527 Unchecked_Convert_To (Ptr_Typ,
2528 New_Occurrence_Of (Temp_Id, Loc)));
2530 Set_Storage_Pool (Free_Stmt, Pool_Id);
2532 -- Create a block to house the dummy type and the instantiation as
2533 -- well as to perform the cleanup the temporary.
2535 -- Generate:
2536 -- declare
2537 -- <Decls>
2538 -- begin
2539 -- Free (Ptr_Typ (Temp_Id));
2540 -- end;
2542 Free_Blk :=
2543 Make_Block_Statement (Loc,
2544 Declarations => Decls,
2545 Handled_Statement_Sequence =>
2546 Make_Handled_Sequence_Of_Statements (Loc,
2547 Statements => New_List (Free_Stmt)));
2549 -- Generate:
2550 -- if BIPfinalizationmaster /= null then
2552 Cond :=
2553 Make_Op_Ne (Loc,
2554 Left_Opnd => New_Occurrence_Of (Fin_Mas_Id, Loc),
2555 Right_Opnd => Make_Null (Loc));
2557 -- For constrained or tagged results escalate the condition to
2558 -- include the allocation format. Generate:
2560 -- if BIPallocform > Secondary_Stack'Pos
2561 -- and then BIPfinalizationmaster /= null
2562 -- then
2564 if not Is_Constrained (Func_Typ)
2565 or else Is_Tagged_Type (Func_Typ)
2566 then
2567 declare
2568 Alloc : constant Entity_Id :=
2569 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2570 begin
2571 Cond :=
2572 Make_And_Then (Loc,
2573 Left_Opnd =>
2574 Make_Op_Gt (Loc,
2575 Left_Opnd => New_Occurrence_Of (Alloc, Loc),
2576 Right_Opnd =>
2577 Make_Integer_Literal (Loc,
2578 UI_From_Int
2579 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2581 Right_Opnd => Cond);
2582 end;
2583 end if;
2585 -- Generate:
2586 -- if <Cond> then
2587 -- <Free_Blk>
2588 -- end if;
2590 return
2591 Make_If_Statement (Loc,
2592 Condition => Cond,
2593 Then_Statements => New_List (Free_Blk));
2594 end Build_BIP_Cleanup_Stmts;
2596 --------------------
2597 -- Find_Last_Init --
2598 --------------------
2600 procedure Find_Last_Init
2601 (Last_Init : out Node_Id;
2602 Body_Insert : out Node_Id)
2604 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id;
2605 -- Find the last initialization call within the statements of
2606 -- block Blk.
2608 function Is_Init_Call (N : Node_Id) return Boolean;
2609 -- Determine whether node N denotes one of the initialization
2610 -- procedures of types Init_Typ or Obj_Typ.
2612 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
2613 -- Given a statement which is part of a list, return the next
2614 -- statement while skipping over dynamic elab checks.
2616 -----------------------------
2617 -- Find_Last_Init_In_Block --
2618 -----------------------------
2620 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id is
2621 HSS : constant Node_Id := Handled_Statement_Sequence (Blk);
2622 Stmt : Node_Id;
2624 begin
2625 -- Examine the individual statements of the block in reverse to
2626 -- locate the last initialization call.
2628 if Present (HSS) and then Present (Statements (HSS)) then
2629 Stmt := Last (Statements (HSS));
2630 while Present (Stmt) loop
2632 -- Peek inside nested blocks in case aborts are allowed
2634 if Nkind (Stmt) = N_Block_Statement then
2635 return Find_Last_Init_In_Block (Stmt);
2637 elsif Is_Init_Call (Stmt) then
2638 return Stmt;
2639 end if;
2641 Prev (Stmt);
2642 end loop;
2643 end if;
2645 return Empty;
2646 end Find_Last_Init_In_Block;
2648 ------------------
2649 -- Is_Init_Call --
2650 ------------------
2652 function Is_Init_Call (N : Node_Id) return Boolean is
2653 function Is_Init_Proc_Of
2654 (Subp_Id : Entity_Id;
2655 Typ : Entity_Id) return Boolean;
2656 -- Determine whether subprogram Subp_Id is a valid init proc of
2657 -- type Typ.
2659 ---------------------
2660 -- Is_Init_Proc_Of --
2661 ---------------------
2663 function Is_Init_Proc_Of
2664 (Subp_Id : Entity_Id;
2665 Typ : Entity_Id) return Boolean
2667 Deep_Init : Entity_Id := Empty;
2668 Prim_Init : Entity_Id := Empty;
2669 Type_Init : Entity_Id := Empty;
2671 begin
2672 -- Obtain all possible initialization routines of the
2673 -- related type and try to match the subprogram entity
2674 -- against one of them.
2676 -- Deep_Initialize
2678 Deep_Init := TSS (Typ, TSS_Deep_Initialize);
2680 -- Primitive Initialize
2682 if Is_Controlled (Typ) then
2683 Prim_Init := Find_Optional_Prim_Op (Typ, Name_Initialize);
2685 if Present (Prim_Init) then
2686 Prim_Init := Ultimate_Alias (Prim_Init);
2687 end if;
2688 end if;
2690 -- Type initialization routine
2692 if Has_Non_Null_Base_Init_Proc (Typ) then
2693 Type_Init := Base_Init_Proc (Typ);
2694 end if;
2696 return
2697 (Present (Deep_Init) and then Subp_Id = Deep_Init)
2698 or else
2699 (Present (Prim_Init) and then Subp_Id = Prim_Init)
2700 or else
2701 (Present (Type_Init) and then Subp_Id = Type_Init);
2702 end Is_Init_Proc_Of;
2704 -- Local variables
2706 Call_Id : Entity_Id;
2708 -- Start of processing for Is_Init_Call
2710 begin
2711 if Nkind (N) = N_Procedure_Call_Statement
2712 and then Nkind (Name (N)) = N_Identifier
2713 then
2714 Call_Id := Entity (Name (N));
2716 -- Consider both the type of the object declaration and its
2717 -- related initialization type.
2719 return
2720 Is_Init_Proc_Of (Call_Id, Init_Typ)
2721 or else
2722 Is_Init_Proc_Of (Call_Id, Obj_Typ);
2723 end if;
2725 return False;
2726 end Is_Init_Call;
2728 -----------------------------
2729 -- Next_Suitable_Statement --
2730 -----------------------------
2732 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
2733 Result : Node_Id := Next (Stmt);
2735 begin
2736 -- Skip over access-before-elaboration checks
2738 if Dynamic_Elaboration_Checks
2739 and then Nkind (Result) = N_Raise_Program_Error
2740 then
2741 Result := Next (Result);
2742 end if;
2744 return Result;
2745 end Next_Suitable_Statement;
2747 -- Local variables
2749 Call : Node_Id;
2750 Stmt : Node_Id;
2751 Stmt_2 : Node_Id;
2753 Deep_Init_Found : Boolean := False;
2754 -- A flag set when a call to [Deep_]Initialize has been found
2756 -- Start of processing for Find_Last_Init
2758 begin
2759 Last_Init := Decl;
2760 Body_Insert := Empty;
2762 -- Object renamings and objects associated with controlled
2763 -- function results do not require initialization.
2765 if Has_No_Init then
2766 return;
2767 end if;
2769 Stmt := Next_Suitable_Statement (Decl);
2771 -- Nothing to do for an object with suppressed initialization
2773 if No_Initialization (Decl) then
2774 return;
2776 -- In all other cases the initialization calls follow the related
2777 -- object. The general structure of object initialization built by
2778 -- routine Default_Initialize_Object is as follows:
2780 -- [begin -- aborts allowed
2781 -- Abort_Defer;]
2782 -- Type_Init_Proc (Obj);
2783 -- [begin] -- exceptions allowed
2784 -- Deep_Initialize (Obj);
2785 -- [exception -- exceptions allowed
2786 -- when others =>
2787 -- Deep_Finalize (Obj, Self => False);
2788 -- raise;
2789 -- end;]
2790 -- [at end -- aborts allowed
2791 -- Abort_Undefer;
2792 -- end;]
2794 -- When aborts are allowed, the initialization calls are housed
2795 -- within a block.
2797 elsif Nkind (Stmt) = N_Block_Statement then
2798 Last_Init := Find_Last_Init_In_Block (Stmt);
2799 Body_Insert := Stmt;
2801 -- Otherwise the initialization calls follow the related object
2803 else
2804 Stmt_2 := Next_Suitable_Statement (Stmt);
2806 -- Check for an optional call to Deep_Initialize which may
2807 -- appear within a block depending on whether the object has
2808 -- controlled components.
2810 if Present (Stmt_2) then
2811 if Nkind (Stmt_2) = N_Block_Statement then
2812 Call := Find_Last_Init_In_Block (Stmt_2);
2814 if Present (Call) then
2815 Deep_Init_Found := True;
2816 Last_Init := Call;
2817 Body_Insert := Stmt_2;
2818 end if;
2820 elsif Is_Init_Call (Stmt_2) then
2821 Deep_Init_Found := True;
2822 Last_Init := Stmt_2;
2823 Body_Insert := Last_Init;
2824 end if;
2825 end if;
2827 -- If the object lacks a call to Deep_Initialize, then it must
2828 -- have a call to its related type init proc.
2830 if not Deep_Init_Found and then Is_Init_Call (Stmt) then
2831 Last_Init := Stmt;
2832 Body_Insert := Last_Init;
2833 end if;
2834 end if;
2835 end Find_Last_Init;
2837 -- Local variables
2839 Body_Ins : Node_Id;
2840 Count_Ins : Node_Id;
2841 Fin_Call : Node_Id;
2842 Fin_Stmts : List_Id;
2843 Inc_Decl : Node_Id;
2844 Label : Node_Id;
2845 Label_Id : Entity_Id;
2846 Obj_Ref : Node_Id;
2848 -- Start of processing for Process_Object_Declaration
2850 begin
2851 -- Handle the object type and the reference to the object
2853 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
2854 Obj_Typ := Base_Type (Etype (Obj_Id));
2856 loop
2857 if Is_Access_Type (Obj_Typ) then
2858 Obj_Typ := Directly_Designated_Type (Obj_Typ);
2859 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2861 elsif Is_Concurrent_Type (Obj_Typ)
2862 and then Present (Corresponding_Record_Type (Obj_Typ))
2863 then
2864 Obj_Typ := Corresponding_Record_Type (Obj_Typ);
2865 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2867 elsif Is_Private_Type (Obj_Typ)
2868 and then Present (Full_View (Obj_Typ))
2869 then
2870 Obj_Typ := Full_View (Obj_Typ);
2871 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2873 elsif Obj_Typ /= Base_Type (Obj_Typ) then
2874 Obj_Typ := Base_Type (Obj_Typ);
2875 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
2877 else
2878 exit;
2879 end if;
2880 end loop;
2882 Set_Etype (Obj_Ref, Obj_Typ);
2884 -- Handle the initialization type of the object declaration
2886 Init_Typ := Obj_Typ;
2887 loop
2888 if Is_Private_Type (Init_Typ)
2889 and then Present (Full_View (Init_Typ))
2890 then
2891 Init_Typ := Full_View (Init_Typ);
2893 elsif Is_Untagged_Derivation (Init_Typ) then
2894 Init_Typ := Root_Type (Init_Typ);
2896 else
2897 exit;
2898 end if;
2899 end loop;
2901 -- Set a new value for the state counter and insert the statement
2902 -- after the object declaration. Generate:
2904 -- Counter := <value>;
2906 Inc_Decl :=
2907 Make_Assignment_Statement (Loc,
2908 Name => New_Occurrence_Of (Counter_Id, Loc),
2909 Expression => Make_Integer_Literal (Loc, Counter_Val));
2911 -- Insert the counter after all initialization has been done. The
2912 -- place of insertion depends on the context.
2914 if Ekind_In (Obj_Id, E_Constant, E_Variable) then
2916 -- The object is initialized by a build-in-place function call.
2917 -- The counter insertion point is after the function call.
2919 if Present (BIP_Initialization_Call (Obj_Id)) then
2920 Count_Ins := BIP_Initialization_Call (Obj_Id);
2921 Body_Ins := Empty;
2923 -- The object is initialized by an aggregate. Insert the counter
2924 -- after the last aggregate assignment.
2926 elsif Present (Last_Aggregate_Assignment (Obj_Id)) then
2927 Count_Ins := Last_Aggregate_Assignment (Obj_Id);
2928 Body_Ins := Empty;
2930 -- In all other cases the counter is inserted after the last call
2931 -- to either [Deep_]Initialize or the type-specific init proc.
2933 else
2934 Find_Last_Init (Count_Ins, Body_Ins);
2935 end if;
2937 -- In all other cases the counter is inserted after the last call to
2938 -- either [Deep_]Initialize or the type-specific init proc.
2940 else
2941 Find_Last_Init (Count_Ins, Body_Ins);
2942 end if;
2944 Insert_After (Count_Ins, Inc_Decl);
2945 Analyze (Inc_Decl);
2947 -- If the current declaration is the last in the list, the finalizer
2948 -- body needs to be inserted after the set counter statement for the
2949 -- current object declaration. This is complicated by the fact that
2950 -- the set counter statement may appear in abort deferred block. In
2951 -- that case, the proper insertion place is after the block.
2953 if No (Finalizer_Insert_Nod) then
2955 -- Insertion after an abort deffered block
2957 if Present (Body_Ins) then
2958 Finalizer_Insert_Nod := Body_Ins;
2959 else
2960 Finalizer_Insert_Nod := Inc_Decl;
2961 end if;
2962 end if;
2964 -- Create the associated label with this object, generate:
2966 -- L<counter> : label;
2968 Label_Id :=
2969 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2970 Set_Entity
2971 (Label_Id, Make_Defining_Identifier (Loc, Chars (Label_Id)));
2972 Label := Make_Label (Loc, Label_Id);
2974 Prepend_To (Finalizer_Decls,
2975 Make_Implicit_Label_Declaration (Loc,
2976 Defining_Identifier => Entity (Label_Id),
2977 Label_Construct => Label));
2979 -- Create the associated jump with this object, generate:
2981 -- when <counter> =>
2982 -- goto L<counter>;
2984 Prepend_To (Jump_Alts,
2985 Make_Case_Statement_Alternative (Loc,
2986 Discrete_Choices => New_List (
2987 Make_Integer_Literal (Loc, Counter_Val)),
2988 Statements => New_List (
2989 Make_Goto_Statement (Loc,
2990 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
2992 -- Insert the jump destination, generate:
2994 -- <<L<counter>>>
2996 Append_To (Finalizer_Stmts, Label);
2998 -- Processing for simple protected objects. Such objects require
2999 -- manual finalization of their lock managers.
3001 if Is_Protected then
3002 Fin_Stmts := No_List;
3004 if Is_Simple_Protected_Type (Obj_Typ) then
3005 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
3007 if Present (Fin_Call) then
3008 Fin_Stmts := New_List (Fin_Call);
3009 end if;
3011 elsif Has_Simple_Protected_Object (Obj_Typ) then
3012 if Is_Record_Type (Obj_Typ) then
3013 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
3014 elsif Is_Array_Type (Obj_Typ) then
3015 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
3016 end if;
3017 end if;
3019 -- Generate:
3020 -- begin
3021 -- System.Tasking.Protected_Objects.Finalize_Protection
3022 -- (Obj._object);
3024 -- exception
3025 -- when others =>
3026 -- null;
3027 -- end;
3029 if Present (Fin_Stmts) then
3030 Append_To (Finalizer_Stmts,
3031 Make_Block_Statement (Loc,
3032 Handled_Statement_Sequence =>
3033 Make_Handled_Sequence_Of_Statements (Loc,
3034 Statements => Fin_Stmts,
3036 Exception_Handlers => New_List (
3037 Make_Exception_Handler (Loc,
3038 Exception_Choices => New_List (
3039 Make_Others_Choice (Loc)),
3041 Statements => New_List (
3042 Make_Null_Statement (Loc)))))));
3043 end if;
3045 -- Processing for regular controlled objects
3047 else
3048 -- Generate:
3049 -- begin
3050 -- [Deep_]Finalize (Obj);
3052 -- exception
3053 -- when Id : others =>
3054 -- if not Raised then
3055 -- Raised := True;
3056 -- Save_Occurrence (E, Id);
3057 -- end if;
3058 -- end;
3060 Fin_Call :=
3061 Make_Final_Call (
3062 Obj_Ref => Obj_Ref,
3063 Typ => Obj_Typ);
3065 -- Guard against a missing [Deep_]Finalize when the object type
3066 -- was not properly frozen.
3068 if No (Fin_Call) then
3069 Fin_Call := Make_Null_Statement (Loc);
3070 end if;
3072 -- For CodePeer, the exception handlers normally generated here
3073 -- generate complex flowgraphs which result in capacity problems.
3074 -- Omitting these handlers for CodePeer is justified as follows:
3076 -- If a handler is dead, then omitting it is surely ok
3078 -- If a handler is live, then CodePeer should flag the
3079 -- potentially-exception-raising construct that causes it
3080 -- to be live. That is what we are interested in, not what
3081 -- happens after the exception is raised.
3083 if Exceptions_OK and not CodePeer_Mode then
3084 Fin_Stmts := New_List (
3085 Make_Block_Statement (Loc,
3086 Handled_Statement_Sequence =>
3087 Make_Handled_Sequence_Of_Statements (Loc,
3088 Statements => New_List (Fin_Call),
3090 Exception_Handlers => New_List (
3091 Build_Exception_Handler
3092 (Finalizer_Data, For_Package)))));
3094 -- When exception handlers are prohibited, the finalization call
3095 -- appears unprotected. Any exception raised during finalization
3096 -- will bypass the circuitry which ensures the cleanup of all
3097 -- remaining objects.
3099 else
3100 Fin_Stmts := New_List (Fin_Call);
3101 end if;
3103 -- If we are dealing with a return object of a build-in-place
3104 -- function, generate the following cleanup statements:
3106 -- if BIPallocfrom > Secondary_Stack'Pos
3107 -- and then BIPfinalizationmaster /= null
3108 -- then
3109 -- declare
3110 -- type Ptr_Typ is access Obj_Typ;
3111 -- for Ptr_Typ'Storage_Pool use
3112 -- Base_Pool (BIPfinalizationmaster.all).all;
3113 -- begin
3114 -- Free (Ptr_Typ (Temp));
3115 -- end;
3116 -- end if;
3118 -- The generated code effectively detaches the temporary from the
3119 -- caller finalization master and deallocates the object.
3121 if Is_Return_Object (Obj_Id) then
3122 declare
3123 Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
3124 begin
3125 if Is_Build_In_Place_Function (Func_Id)
3126 and then Needs_BIP_Finalization_Master (Func_Id)
3127 then
3128 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
3129 end if;
3130 end;
3131 end if;
3133 if Ekind_In (Obj_Id, E_Constant, E_Variable)
3134 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
3135 then
3136 -- Temporaries created for the purpose of "exporting" a
3137 -- transient object out of an Expression_With_Actions (EWA)
3138 -- need guards. The following illustrates the usage of such
3139 -- temporaries.
3141 -- Access_Typ : access [all] Obj_Typ;
3142 -- Temp : Access_Typ := null;
3143 -- <Counter> := ...;
3145 -- do
3146 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
3147 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
3148 -- <or>
3149 -- Temp := Ctrl_Trans'Unchecked_Access;
3150 -- in ... end;
3152 -- The finalization machinery does not process EWA nodes as
3153 -- this may lead to premature finalization of expressions. Note
3154 -- that Temp is marked as being properly initialized regardless
3155 -- of whether the initialization of Ctrl_Trans succeeded. Since
3156 -- a failed initialization may leave Temp with a value of null,
3157 -- add a guard to handle this case:
3159 -- if Obj /= null then
3160 -- <object finalization statements>
3161 -- end if;
3163 if Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
3164 N_Object_Declaration
3165 then
3166 Fin_Stmts := New_List (
3167 Make_If_Statement (Loc,
3168 Condition =>
3169 Make_Op_Ne (Loc,
3170 Left_Opnd => New_Occurrence_Of (Obj_Id, Loc),
3171 Right_Opnd => Make_Null (Loc)),
3172 Then_Statements => Fin_Stmts));
3174 -- Return objects use a flag to aid in processing their
3175 -- potential finalization when the enclosing function fails
3176 -- to return properly. Generate:
3178 -- if not Flag then
3179 -- <object finalization statements>
3180 -- end if;
3182 else
3183 Fin_Stmts := New_List (
3184 Make_If_Statement (Loc,
3185 Condition =>
3186 Make_Op_Not (Loc,
3187 Right_Opnd =>
3188 New_Occurrence_Of
3189 (Status_Flag_Or_Transient_Decl (Obj_Id), Loc)),
3191 Then_Statements => Fin_Stmts));
3192 end if;
3193 end if;
3194 end if;
3196 Append_List_To (Finalizer_Stmts, Fin_Stmts);
3198 -- Since the declarations are examined in reverse, the state counter
3199 -- must be decremented in order to keep with the true position of
3200 -- objects.
3202 Counter_Val := Counter_Val - 1;
3203 end Process_Object_Declaration;
3205 -------------------------------------
3206 -- Process_Tagged_Type_Declaration --
3207 -------------------------------------
3209 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
3210 Typ : constant Entity_Id := Defining_Identifier (Decl);
3211 DT_Ptr : constant Entity_Id :=
3212 Node (First_Elmt (Access_Disp_Table (Typ)));
3213 begin
3214 -- Generate:
3215 -- Ada.Tags.Unregister_Tag (<Typ>P);
3217 Append_To (Tagged_Type_Stmts,
3218 Make_Procedure_Call_Statement (Loc,
3219 Name =>
3220 New_Occurrence_Of (RTE (RE_Unregister_Tag), Loc),
3221 Parameter_Associations => New_List (
3222 New_Occurrence_Of (DT_Ptr, Loc))));
3223 end Process_Tagged_Type_Declaration;
3225 -- Start of processing for Build_Finalizer
3227 begin
3228 Fin_Id := Empty;
3230 -- Do not perform this expansion in SPARK mode because it is not
3231 -- necessary.
3233 if GNATprove_Mode then
3234 return;
3235 end if;
3237 -- Step 1: Extract all lists which may contain controlled objects or
3238 -- library-level tagged types.
3240 if For_Package_Spec then
3241 Decls := Visible_Declarations (Specification (N));
3242 Priv_Decls := Private_Declarations (Specification (N));
3244 -- Retrieve the package spec id
3246 Spec_Id := Defining_Unit_Name (Specification (N));
3248 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
3249 Spec_Id := Defining_Identifier (Spec_Id);
3250 end if;
3252 -- Accept statement, block, entry body, package body, protected body,
3253 -- subprogram body or task body.
3255 else
3256 Decls := Declarations (N);
3257 HSS := Handled_Statement_Sequence (N);
3259 if Present (HSS) then
3260 if Present (Statements (HSS)) then
3261 Stmts := Statements (HSS);
3262 end if;
3264 if Present (At_End_Proc (HSS)) then
3265 Prev_At_End := At_End_Proc (HSS);
3266 end if;
3267 end if;
3269 -- Retrieve the package spec id for package bodies
3271 if For_Package_Body then
3272 Spec_Id := Corresponding_Spec (N);
3273 end if;
3274 end if;
3276 -- Do not process nested packages since those are handled by the
3277 -- enclosing scope's finalizer. Do not process non-expanded package
3278 -- instantiations since those will be re-analyzed and re-expanded.
3280 if For_Package
3281 and then
3282 (not Is_Library_Level_Entity (Spec_Id)
3284 -- Nested packages are considered to be library level entities,
3285 -- but do not need to be processed separately. True library level
3286 -- packages have a scope value of 1.
3288 or else Scope_Depth_Value (Spec_Id) /= Uint_1
3289 or else (Is_Generic_Instance (Spec_Id)
3290 and then Package_Instantiation (Spec_Id) /= N))
3291 then
3292 return;
3293 end if;
3295 -- Step 2: Object [pre]processing
3297 if For_Package then
3299 -- Preprocess the visible declarations now in order to obtain the
3300 -- correct number of controlled object by the time the private
3301 -- declarations are processed.
3303 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3305 -- From all the possible contexts, only package specifications may
3306 -- have private declarations.
3308 if For_Package_Spec then
3309 Process_Declarations
3310 (Priv_Decls, Preprocess => True, Top_Level => True);
3311 end if;
3313 -- The current context may lack controlled objects, but require some
3314 -- other form of completion (task termination for instance). In such
3315 -- cases, the finalizer must be created and carry the additional
3316 -- statements.
3318 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3319 Build_Components;
3320 end if;
3322 -- The preprocessing has determined that the context has controlled
3323 -- objects or library-level tagged types.
3325 if Has_Ctrl_Objs or Has_Tagged_Types then
3327 -- Private declarations are processed first in order to preserve
3328 -- possible dependencies between public and private objects.
3330 if For_Package_Spec then
3331 Process_Declarations (Priv_Decls);
3332 end if;
3334 Process_Declarations (Decls);
3335 end if;
3337 -- Non-package case
3339 else
3340 -- Preprocess both declarations and statements
3342 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3343 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
3345 -- At this point it is known that N has controlled objects. Ensure
3346 -- that N has a declarative list since the finalizer spec will be
3347 -- attached to it.
3349 if Has_Ctrl_Objs and then No (Decls) then
3350 Set_Declarations (N, New_List);
3351 Decls := Declarations (N);
3352 Spec_Decls := Decls;
3353 end if;
3355 -- The current context may lack controlled objects, but require some
3356 -- other form of completion (task termination for instance). In such
3357 -- cases, the finalizer must be created and carry the additional
3358 -- statements.
3360 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3361 Build_Components;
3362 end if;
3364 if Has_Ctrl_Objs or Has_Tagged_Types then
3365 Process_Declarations (Stmts);
3366 Process_Declarations (Decls);
3367 end if;
3368 end if;
3370 -- Step 3: Finalizer creation
3372 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
3373 Create_Finalizer;
3374 end if;
3375 end Build_Finalizer;
3377 --------------------------
3378 -- Build_Finalizer_Call --
3379 --------------------------
3381 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
3382 Is_Prot_Body : constant Boolean :=
3383 Nkind (N) = N_Subprogram_Body
3384 and then Is_Protected_Subprogram_Body (N);
3385 -- Determine whether N denotes the protected version of a subprogram
3386 -- which belongs to a protected type.
3388 Loc : constant Source_Ptr := Sloc (N);
3389 HSS : Node_Id;
3391 begin
3392 -- Do not perform this expansion in SPARK mode because we do not create
3393 -- finalizers in the first place.
3395 if GNATprove_Mode then
3396 return;
3397 end if;
3399 -- The At_End handler should have been assimilated by the finalizer
3401 HSS := Handled_Statement_Sequence (N);
3402 pragma Assert (No (At_End_Proc (HSS)));
3404 -- If the construct to be cleaned up is a protected subprogram body, the
3405 -- finalizer call needs to be associated with the block which wraps the
3406 -- unprotected version of the subprogram. The following illustrates this
3407 -- scenario:
3409 -- procedure Prot_SubpP is
3410 -- procedure finalizer is
3411 -- begin
3412 -- Service_Entries (Prot_Obj);
3413 -- Abort_Undefer;
3414 -- end finalizer;
3416 -- begin
3417 -- . . .
3418 -- begin
3419 -- Prot_SubpN (Prot_Obj);
3420 -- at end
3421 -- finalizer;
3422 -- end;
3423 -- end Prot_SubpP;
3425 if Is_Prot_Body then
3426 HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
3428 -- An At_End handler and regular exception handlers cannot coexist in
3429 -- the same statement sequence. Wrap the original statements in a block.
3431 elsif Present (Exception_Handlers (HSS)) then
3432 declare
3433 End_Lab : constant Node_Id := End_Label (HSS);
3434 Block : Node_Id;
3436 begin
3437 Block :=
3438 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
3440 Set_Handled_Statement_Sequence (N,
3441 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3443 HSS := Handled_Statement_Sequence (N);
3444 Set_End_Label (HSS, End_Lab);
3445 end;
3446 end if;
3448 Set_At_End_Proc (HSS, New_Occurrence_Of (Fin_Id, Loc));
3450 Analyze (At_End_Proc (HSS));
3451 Expand_At_End_Handler (HSS, Empty);
3452 end Build_Finalizer_Call;
3454 ------------------------------------
3455 -- Build_Invariant_Procedure_Body --
3456 ------------------------------------
3458 -- WARNING: This routine manages Ghost regions. Return statements must be
3459 -- replaced by gotos which jump to the end of the routine and restore the
3460 -- Ghost mode.
3462 procedure Build_Invariant_Procedure_Body
3463 (Typ : Entity_Id;
3464 Partial_Invariant : Boolean := False)
3466 Loc : constant Source_Ptr := Sloc (Typ);
3468 Pragmas_Seen : Elist_Id := No_Elist;
3469 -- This list contains all invariant pragmas processed so far. The list
3470 -- is used to avoid generating redundant invariant checks.
3472 Produced_Check : Boolean := False;
3473 -- This flag tracks whether the type has produced at least one invariant
3474 -- check. The flag is used as a sanity check at the end of the routine.
3476 -- NOTE: most of the routines in Build_Invariant_Procedure_Body are
3477 -- intentionally unnested to avoid deep indentation of code.
3479 -- NOTE: all Add_xxx_Invariants routines are reactive. In other words
3480 -- they emit checks, loops (for arrays) and case statements (for record
3481 -- variant parts) only when there are invariants to verify. This keeps
3482 -- the body of the invariant procedure free from useless code.
3484 procedure Add_Array_Component_Invariants
3485 (T : Entity_Id;
3486 Obj_Id : Entity_Id;
3487 Checks : in out List_Id);
3488 -- Generate an invariant check for each component of array type T.
3489 -- Obj_Id denotes the entity of the _object formal parameter of the
3490 -- invariant procedure. All created checks are added to list Checks.
3492 procedure Add_Interface_Invariants
3493 (T : Entity_Id;
3494 Obj_Id : Entity_Id;
3495 Checks : in out List_Id);
3496 -- Generate an invariant check for each inherited class-wide invariant
3497 -- coming from all interfaces implemented by type T. Obj_Id denotes the
3498 -- entity of the _object formal parameter of the invariant procedure.
3499 -- All created checks are added to list Checks.
3501 procedure Add_Parent_Invariants
3502 (T : Entity_Id;
3503 Obj_Id : Entity_Id;
3504 Checks : in out List_Id);
3505 -- Generate an invariant check for each inherited class-wide invariant
3506 -- coming from all parent types of type T. Obj_Id denotes the entity of
3507 -- the _object formal parameter of the invariant procedure. All created
3508 -- checks are added to list Checks.
3510 procedure Add_Record_Component_Invariants
3511 (T : Entity_Id;
3512 Obj_Id : Entity_Id;
3513 Checks : in out List_Id);
3514 -- Generate an invariant check for each component of record type T.
3515 -- Obj_Id denotes the entity of the _object formal parameter of the
3516 -- invariant procedure. All created checks are added to list Checks.
3518 procedure Add_Type_Invariants
3519 (Priv_Typ : Entity_Id;
3520 Full_Typ : Entity_Id;
3521 CRec_Typ : Entity_Id;
3522 Obj_Id : Entity_Id;
3523 Checks : in out List_Id;
3524 Inherit : Boolean := False;
3525 Priv_Item : Node_Id := Empty);
3526 -- Generate an invariant check for each invariant found in one of the
3527 -- following types (if available):
3529 -- Priv_Typ - the partial view of a type
3530 -- Full_Typ - the full view of a type
3531 -- CRec_Typ - the corresponding record of a protected or a task type
3533 -- Obj_Id denotes the entity of the _object formal parameter of the
3534 -- invariant procedure. All created checks are added to list Checks.
3535 -- Flag Inherit should be set when generating invariant checks for
3536 -- inherited class-wide invariants. Priv_Item denotes the first rep
3537 -- item of the private type.
3539 function Is_Untagged_Private_Derivation
3540 (Priv_Typ : Entity_Id;
3541 Full_Typ : Entity_Id) return Boolean;
3542 -- Determine whether private type Priv_Typ and its full view Full_Typ
3543 -- represent an untagged derivation from a private parent.
3545 ------------------------------------
3546 -- Add_Array_Component_Invariants --
3547 ------------------------------------
3549 procedure Add_Array_Component_Invariants
3550 (T : Entity_Id;
3551 Obj_Id : Entity_Id;
3552 Checks : in out List_Id)
3554 Comp_Typ : constant Entity_Id := Component_Type (T);
3555 Dims : constant Pos := Number_Dimensions (T);
3557 procedure Process_Array_Component
3558 (Indices : List_Id;
3559 Comp_Checks : in out List_Id);
3560 -- Generate an invariant check for an array component identified by
3561 -- the indices in list Indices. All created checks are added to list
3562 -- Comp_Checks.
3564 procedure Process_One_Dimension
3565 (Dim : Pos;
3566 Indices : List_Id;
3567 Dim_Checks : in out List_Id);
3568 -- Generate a loop over the Nth dimension Dim of an array type. List
3569 -- Indices contains all array indices for the dimension. All created
3570 -- checks are added to list Dim_Checks.
3572 -----------------------------
3573 -- Process_Array_Component --
3574 -----------------------------
3576 procedure Process_Array_Component
3577 (Indices : List_Id;
3578 Comp_Checks : in out List_Id)
3580 Proc_Id : Entity_Id;
3582 begin
3583 if Has_Invariants (Comp_Typ) then
3585 -- In GNATprove mode, the component invariants are checked by
3586 -- other means. They should not be added to the array type
3587 -- invariant procedure, so that the procedure can be used to
3588 -- check the array type invariants if any.
3590 if GNATprove_Mode then
3591 null;
3593 else
3594 Proc_Id := Invariant_Procedure (Base_Type (Comp_Typ));
3596 -- The component type should have an invariant procedure
3597 -- if it has invariants of its own or inherits class-wide
3598 -- invariants from parent or interface types.
3600 pragma Assert (Present (Proc_Id));
3602 -- Generate:
3603 -- <Comp_Typ>Invariant (_object (<Indices>));
3605 -- Note that the invariant procedure may have a null body if
3606 -- assertions are disabled or Assertion_Policy Ignore is in
3607 -- effect.
3609 if not Has_Null_Body (Proc_Id) then
3610 Append_New_To (Comp_Checks,
3611 Make_Procedure_Call_Statement (Loc,
3612 Name =>
3613 New_Occurrence_Of (Proc_Id, Loc),
3614 Parameter_Associations => New_List (
3615 Make_Indexed_Component (Loc,
3616 Prefix => New_Occurrence_Of (Obj_Id, Loc),
3617 Expressions => New_Copy_List (Indices)))));
3618 end if;
3619 end if;
3621 Produced_Check := True;
3622 end if;
3623 end Process_Array_Component;
3625 ---------------------------
3626 -- Process_One_Dimension --
3627 ---------------------------
3629 procedure Process_One_Dimension
3630 (Dim : Pos;
3631 Indices : List_Id;
3632 Dim_Checks : in out List_Id)
3634 Comp_Checks : List_Id := No_List;
3635 Index : Entity_Id;
3637 begin
3638 -- Generate the invariant checks for the array component after all
3639 -- dimensions have produced their respective loops.
3641 if Dim > Dims then
3642 Process_Array_Component
3643 (Indices => Indices,
3644 Comp_Checks => Dim_Checks);
3646 -- Otherwise create a loop for the current dimension
3648 else
3649 -- Create a new loop variable for each dimension
3651 Index :=
3652 Make_Defining_Identifier (Loc,
3653 Chars => New_External_Name ('I', Dim));
3654 Append_To (Indices, New_Occurrence_Of (Index, Loc));
3656 Process_One_Dimension
3657 (Dim => Dim + 1,
3658 Indices => Indices,
3659 Dim_Checks => Comp_Checks);
3661 -- Generate:
3662 -- for I<Dim> in _object'Range (<Dim>) loop
3663 -- <Comp_Checks>
3664 -- end loop;
3666 -- Note that the invariant procedure may have a null body if
3667 -- assertions are disabled or Assertion_Policy Ignore is in
3668 -- effect.
3670 if Present (Comp_Checks) then
3671 Append_New_To (Dim_Checks,
3672 Make_Implicit_Loop_Statement (T,
3673 Identifier => Empty,
3674 Iteration_Scheme =>
3675 Make_Iteration_Scheme (Loc,
3676 Loop_Parameter_Specification =>
3677 Make_Loop_Parameter_Specification (Loc,
3678 Defining_Identifier => Index,
3679 Discrete_Subtype_Definition =>
3680 Make_Attribute_Reference (Loc,
3681 Prefix =>
3682 New_Occurrence_Of (Obj_Id, Loc),
3683 Attribute_Name => Name_Range,
3684 Expressions => New_List (
3685 Make_Integer_Literal (Loc, Dim))))),
3687 Statements => Comp_Checks));
3688 end if;
3689 end if;
3690 end Process_One_Dimension;
3692 -- Start of processing for Add_Array_Component_Invariants
3694 begin
3695 Process_One_Dimension
3696 (Dim => 1,
3697 Indices => New_List,
3698 Dim_Checks => Checks);
3699 end Add_Array_Component_Invariants;
3701 ------------------------------
3702 -- Add_Interface_Invariants --
3703 ------------------------------
3705 procedure Add_Interface_Invariants
3706 (T : Entity_Id;
3707 Obj_Id : Entity_Id;
3708 Checks : in out List_Id)
3710 Iface_Elmt : Elmt_Id;
3711 Ifaces : Elist_Id;
3713 begin
3714 if Is_Tagged_Type (T) then
3715 Collect_Interfaces (T, Ifaces);
3717 -- Process the class-wide invariants of all implemented interfaces
3719 Iface_Elmt := First_Elmt (Ifaces);
3720 while Present (Iface_Elmt) loop
3721 Add_Type_Invariants
3722 (Priv_Typ => Empty,
3723 Full_Typ => Node (Iface_Elmt),
3724 CRec_Typ => Empty,
3725 Obj_Id => Obj_Id,
3726 Checks => Checks,
3727 Inherit => True);
3729 Next_Elmt (Iface_Elmt);
3730 end loop;
3731 end if;
3732 end Add_Interface_Invariants;
3734 ---------------------------
3735 -- Add_Parent_Invariants --
3736 ---------------------------
3738 procedure Add_Parent_Invariants
3739 (T : Entity_Id;
3740 Obj_Id : Entity_Id;
3741 Checks : in out List_Id)
3743 Dummy_1 : Entity_Id;
3744 Dummy_2 : Entity_Id;
3746 Curr_Typ : Entity_Id;
3747 -- The entity of the current type being examined
3749 Full_Typ : Entity_Id;
3750 -- The full view of Par_Typ
3752 Par_Typ : Entity_Id;
3753 -- The entity of the parent type
3755 Priv_Typ : Entity_Id;
3756 -- The partial view of Par_Typ
3758 begin
3759 -- Do not process array types because they cannot have true parent
3760 -- types. This also prevents the generation of a duplicate invariant
3761 -- check when the input type is an array base type because its Etype
3762 -- denotes the first subtype, both of which share the same component
3763 -- type.
3765 if Is_Array_Type (T) then
3766 return;
3767 end if;
3769 -- Climb the parent type chain
3771 Curr_Typ := T;
3772 loop
3773 -- Do not consider subtypes as they inherit the invariants from
3774 -- their base types.
3776 Par_Typ := Base_Type (Etype (Curr_Typ));
3778 -- Stop the climb once the root of the parent chain is reached
3780 exit when Curr_Typ = Par_Typ;
3782 -- Process the class-wide invariants of the parent type
3784 Get_Views (Par_Typ, Priv_Typ, Full_Typ, Dummy_1, Dummy_2);
3786 Add_Type_Invariants
3787 (Priv_Typ => Priv_Typ,
3788 Full_Typ => Full_Typ,
3789 CRec_Typ => Empty,
3790 Obj_Id => Obj_Id,
3791 Checks => Checks,
3792 Inherit => True);
3794 Curr_Typ := Par_Typ;
3795 end loop;
3796 end Add_Parent_Invariants;
3798 -------------------------------------
3799 -- Add_Record_Component_Invariants --
3800 -------------------------------------
3802 procedure Add_Record_Component_Invariants
3803 (T : Entity_Id;
3804 Obj_Id : Entity_Id;
3805 Checks : in out List_Id)
3807 procedure Process_Component_List
3808 (Comp_List : Node_Id;
3809 CL_Checks : in out List_Id);
3810 -- Generate invariant checks for all record components found in
3811 -- component list Comp_List, including variant parts. All created
3812 -- checks are added to list CL_Checks.
3814 procedure Process_Record_Component
3815 (Comp_Id : Entity_Id;
3816 Comp_Checks : in out List_Id);
3817 -- Generate an invariant check for a record component identified by
3818 -- Comp_Id. All created checks are added to list Comp_Checks.
3820 ----------------------------
3821 -- Process_Component_List --
3822 ----------------------------
3824 procedure Process_Component_List
3825 (Comp_List : Node_Id;
3826 CL_Checks : in out List_Id)
3828 Comp : Node_Id;
3829 Var : Node_Id;
3830 Var_Alts : List_Id := No_List;
3831 Var_Checks : List_Id := No_List;
3832 Var_Stmts : List_Id;
3834 Produced_Variant_Check : Boolean := False;
3835 -- This flag tracks whether the component has produced at least
3836 -- one invariant check.
3838 begin
3839 -- Traverse the component items
3841 Comp := First (Component_Items (Comp_List));
3842 while Present (Comp) loop
3843 if Nkind (Comp) = N_Component_Declaration then
3845 -- Generate the component invariant check
3847 Process_Record_Component
3848 (Comp_Id => Defining_Entity (Comp),
3849 Comp_Checks => CL_Checks);
3850 end if;
3852 Next (Comp);
3853 end loop;
3855 -- Traverse the variant part
3857 if Present (Variant_Part (Comp_List)) then
3858 Var := First (Variants (Variant_Part (Comp_List)));
3859 while Present (Var) loop
3860 Var_Checks := No_List;
3862 -- Generate invariant checks for all components and variant
3863 -- parts that qualify.
3865 Process_Component_List
3866 (Comp_List => Component_List (Var),
3867 CL_Checks => Var_Checks);
3869 -- The components of the current variant produced at least
3870 -- one invariant check.
3872 if Present (Var_Checks) then
3873 Var_Stmts := Var_Checks;
3874 Produced_Variant_Check := True;
3876 -- Otherwise there are either no components with invariants,
3877 -- assertions are disabled, or Assertion_Policy Ignore is in
3878 -- effect.
3880 else
3881 Var_Stmts := New_List (Make_Null_Statement (Loc));
3882 end if;
3884 Append_New_To (Var_Alts,
3885 Make_Case_Statement_Alternative (Loc,
3886 Discrete_Choices =>
3887 New_Copy_List (Discrete_Choices (Var)),
3888 Statements => Var_Stmts));
3890 Next (Var);
3891 end loop;
3893 -- Create a case statement which verifies the invariant checks
3894 -- of a particular component list depending on the discriminant
3895 -- values only when there is at least one real invariant check.
3897 if Produced_Variant_Check then
3898 Append_New_To (CL_Checks,
3899 Make_Case_Statement (Loc,
3900 Expression =>
3901 Make_Selected_Component (Loc,
3902 Prefix => New_Occurrence_Of (Obj_Id, Loc),
3903 Selector_Name =>
3904 New_Occurrence_Of
3905 (Entity (Name (Variant_Part (Comp_List))), Loc)),
3906 Alternatives => Var_Alts));
3907 end if;
3908 end if;
3909 end Process_Component_List;
3911 ------------------------------
3912 -- Process_Record_Component --
3913 ------------------------------
3915 procedure Process_Record_Component
3916 (Comp_Id : Entity_Id;
3917 Comp_Checks : in out List_Id)
3919 Comp_Typ : constant Entity_Id := Etype (Comp_Id);
3920 Proc_Id : Entity_Id;
3922 Produced_Component_Check : Boolean := False;
3923 -- This flag tracks whether the component has produced at least
3924 -- one invariant check.
3926 begin
3927 -- Nothing to do for internal component _parent. Note that it is
3928 -- not desirable to check whether the component comes from source
3929 -- because protected type components are relocated to an internal
3930 -- corresponding record, but still need processing.
3932 if Chars (Comp_Id) = Name_uParent then
3933 return;
3934 end if;
3936 -- Verify the invariant of the component. Note that an access
3937 -- type may have an invariant when it acts as the full view of a
3938 -- private type and the invariant appears on the partial view. In
3939 -- this case verify the access value itself.
3941 if Has_Invariants (Comp_Typ) then
3943 -- In GNATprove mode, the component invariants are checked by
3944 -- other means. They should not be added to the record type
3945 -- invariant procedure, so that the procedure can be used to
3946 -- check the record type invariants if any.
3948 if GNATprove_Mode then
3949 null;
3951 else
3952 Proc_Id := Invariant_Procedure (Base_Type (Comp_Typ));
3954 -- The component type should have an invariant procedure
3955 -- if it has invariants of its own or inherits class-wide
3956 -- invariants from parent or interface types.
3958 pragma Assert (Present (Proc_Id));
3960 -- Generate:
3961 -- <Comp_Typ>Invariant (T (_object).<Comp_Id>);
3963 -- Note that the invariant procedure may have a null body if
3964 -- assertions are disabled or Assertion_Policy Ignore is in
3965 -- effect.
3967 if not Has_Null_Body (Proc_Id) then
3968 Append_New_To (Comp_Checks,
3969 Make_Procedure_Call_Statement (Loc,
3970 Name =>
3971 New_Occurrence_Of (Proc_Id, Loc),
3972 Parameter_Associations => New_List (
3973 Make_Selected_Component (Loc,
3974 Prefix =>
3975 Unchecked_Convert_To
3976 (T, New_Occurrence_Of (Obj_Id, Loc)),
3977 Selector_Name =>
3978 New_Occurrence_Of (Comp_Id, Loc)))));
3979 end if;
3980 end if;
3982 Produced_Check := True;
3983 Produced_Component_Check := True;
3984 end if;
3986 if Produced_Component_Check and then Has_Unchecked_Union (T) then
3987 Error_Msg_NE
3988 ("invariants cannot be checked on components of "
3989 & "unchecked_union type &?", Comp_Id, T);
3990 end if;
3991 end Process_Record_Component;
3993 -- Local variables
3995 Comps : Node_Id;
3996 Def : Node_Id;
3998 -- Start of processing for Add_Record_Component_Invariants
4000 begin
4001 -- An untagged derived type inherits the components of its parent
4002 -- type. In order to avoid creating redundant invariant checks, do
4003 -- not process the components now. Instead wait until the ultimate
4004 -- parent of the untagged derivation chain is reached.
4006 if not Is_Untagged_Derivation (T) then
4007 Def := Type_Definition (Parent (T));
4009 if Nkind (Def) = N_Derived_Type_Definition then
4010 Def := Record_Extension_Part (Def);
4011 end if;
4013 pragma Assert (Nkind (Def) = N_Record_Definition);
4014 Comps := Component_List (Def);
4016 if Present (Comps) then
4017 Process_Component_List
4018 (Comp_List => Comps,
4019 CL_Checks => Checks);
4020 end if;
4021 end if;
4022 end Add_Record_Component_Invariants;
4024 -------------------------
4025 -- Add_Type_Invariants --
4026 -------------------------
4028 procedure Add_Type_Invariants
4029 (Priv_Typ : Entity_Id;
4030 Full_Typ : Entity_Id;
4031 CRec_Typ : Entity_Id;
4032 Obj_Id : Entity_Id;
4033 Checks : in out List_Id;
4034 Inherit : Boolean := False;
4035 Priv_Item : Node_Id := Empty)
4037 procedure Add_Invariant (Prag : Node_Id);
4038 -- Create a runtime check to verify the invariant exression of pragma
4039 -- Prag. All generated code is added to list Checks.
4041 procedure Process_Type (T : Entity_Id; Stop_Item : Node_Id := Empty);
4042 -- Generate invariant checks for type T by inspecting the rep item
4043 -- chain of the type. Stop_Item denotes a rep item which once seen
4044 -- will stop the inspection.
4046 -------------------
4047 -- Add_Invariant --
4048 -------------------
4050 procedure Add_Invariant (Prag : Node_Id) is
4051 Rep_Typ : Entity_Id;
4052 -- The replacement type used in the substitution of the current
4053 -- instance of a type with the _object formal parameter.
4055 procedure Replace_Type_Ref (N : Node_Id);
4056 -- Substitute the occurrence of a type name denoted by N with a
4057 -- reference to the _object formal parameter.
4059 ----------------------
4060 -- Replace_Type_Ref --
4061 ----------------------
4063 procedure Replace_Type_Ref (N : Node_Id) is
4064 Nloc : constant Source_Ptr := Sloc (N);
4065 Ref : Node_Id;
4067 begin
4068 -- Decorate the reference to Ref_Typ even though it may be
4069 -- rewritten further down. This is done for two reasons:
4071 -- 1) ASIS has all necessary semantic information in the
4072 -- original tree.
4074 -- 2) Routines which examine properties of the Original_Node
4075 -- have some semantic information.
4077 if Nkind (N) = N_Identifier then
4078 Set_Entity (N, Rep_Typ);
4079 Set_Etype (N, Rep_Typ);
4081 elsif Nkind (N) = N_Selected_Component then
4082 Analyze (Prefix (N));
4083 Set_Entity (Selector_Name (N), Rep_Typ);
4084 Set_Etype (Selector_Name (N), Rep_Typ);
4085 end if;
4087 -- Perform the following substitution:
4089 -- Ref_Typ --> _object
4091 Ref := Make_Identifier (Nloc, Chars (Obj_Id));
4092 Set_Entity (Ref, Obj_Id);
4093 Set_Etype (Ref, Rep_Typ);
4095 -- When the pragma denotes a class-wide invariant, perform the
4096 -- following substitution:
4098 -- Rep_Typ --> Rep_Typ'Class (_object)
4100 if Class_Present (Prag) then
4101 Ref :=
4102 Make_Type_Conversion (Nloc,
4103 Subtype_Mark =>
4104 Make_Attribute_Reference (Nloc,
4105 Prefix =>
4106 New_Occurrence_Of (Rep_Typ, Nloc),
4107 Attribute_Name => Name_Class),
4108 Expression => Ref);
4109 end if;
4111 Rewrite (N, Ref);
4112 Set_Comes_From_Source (N, True);
4113 end Replace_Type_Ref;
4115 procedure Replace_Type_Refs is
4116 new Replace_Type_References_Generic (Replace_Type_Ref);
4118 -- Local variables
4120 Asp : constant Node_Id := Corresponding_Aspect (Prag);
4121 Nam : constant Name_Id := Original_Aspect_Pragma_Name (Prag);
4122 Ploc : constant Source_Ptr := Sloc (Prag);
4124 Arg1 : Node_Id;
4125 Arg2 : Node_Id;
4126 Arg3 : Node_Id;
4127 ASIS_Expr : Node_Id;
4128 Assoc : List_Id;
4129 Expr : Node_Id;
4130 Str : String_Id;
4132 -- Start of processing for Add_Invariant
4134 begin
4135 -- Nothing to do if the pragma was already processed
4137 if Contains (Pragmas_Seen, Prag) then
4138 return;
4139 end if;
4141 -- Extract the arguments of the invariant pragma
4143 Arg1 := First (Pragma_Argument_Associations (Prag));
4144 Arg2 := Next (Arg1);
4145 Arg3 := Next (Arg2);
4147 Arg1 := Get_Pragma_Arg (Arg1);
4148 Arg2 := Get_Pragma_Arg (Arg2);
4150 -- The pragma applies to the partial view
4152 if Present (Priv_Typ) and then Entity (Arg1) = Priv_Typ then
4153 Rep_Typ := Priv_Typ;
4155 -- The pragma applies to the full view
4157 elsif Present (Full_Typ) and then Entity (Arg1) = Full_Typ then
4158 Rep_Typ := Full_Typ;
4160 -- Otherwise the pragma applies to a parent type in which case it
4161 -- will be processed at a later stage by Add_Parent_Invariants or
4162 -- Add_Interface_Invariants.
4164 else
4165 return;
4166 end if;
4168 -- Nothing to do when the caller requests the processing of all
4169 -- inherited class-wide invariants, but the pragma does not fall
4170 -- in this category.
4172 if Inherit and then not Class_Present (Prag) then
4173 return;
4174 end if;
4176 Expr := New_Copy_Tree (Arg2);
4178 -- Substitute all references to type Rep_Typ with references to
4179 -- the _object formal parameter.
4181 Replace_Type_Refs (Expr, Rep_Typ);
4183 -- Additional processing for non-class-wide invariants
4185 if not Inherit then
4187 -- Preanalyze the invariant expression to detect errors and at
4188 -- the same time capture the visibility of the proper package
4189 -- part.
4191 -- Historical note: the old implementation of invariants used
4192 -- node N as the parent, but a package specification as parent
4193 -- of an expression is bizarre.
4195 Set_Parent (Expr, Parent (Arg2));
4196 Preanalyze_Assert_Expression (Expr, Any_Boolean);
4198 -- If the pragma comes from an aspect specification, replace
4199 -- the saved expression because all type references must be
4200 -- substituted for the call to Preanalyze_Spec_Expression in
4201 -- Check_Aspect_At_xxx routines.
4203 if Present (Asp) then
4204 Set_Entity (Identifier (Asp), New_Copy_Tree (Expr));
4205 end if;
4207 -- Analyze the original invariant expression for ASIS
4209 if ASIS_Mode then
4210 ASIS_Expr := Empty;
4212 if Comes_From_Source (Prag) then
4213 ASIS_Expr := Arg2;
4214 elsif Present (Asp) then
4215 ASIS_Expr := Expression (Asp);
4216 end if;
4218 if Present (ASIS_Expr) then
4219 Replace_Type_Refs (ASIS_Expr, Rep_Typ);
4220 Preanalyze_Assert_Expression (ASIS_Expr, Any_Boolean);
4221 end if;
4222 end if;
4224 -- A class-wide invariant may be inherited in a separate unit,
4225 -- where the corresponding expression cannot be resolved by
4226 -- visibility, because it refers to a local function. Propagate
4227 -- semantic information to the original representation item, to
4228 -- be used when an invariant procedure for a derived type is
4229 -- constructed.
4231 -- ??? Unclear how to handle class-wide invariants that are not
4232 -- function calls.
4234 if Class_Present (Prag)
4235 and then Nkind (Expr) = N_Function_Call
4236 and then Nkind (Arg2) = N_Indexed_Component
4237 then
4238 Rewrite (Arg2,
4239 Make_Function_Call (Ploc,
4240 Name =>
4241 New_Occurrence_Of (Entity (Name (Expr)), Ploc),
4242 Parameter_Associations => Expressions (Arg2)));
4243 end if;
4244 end if;
4246 -- The invariant is ignored, nothing left to do
4248 if Is_Ignored (Prag) then
4249 null;
4251 -- Otherwise the invariant is checked. Build a Check pragma to
4252 -- verify the expression at runtime.
4254 else
4255 Assoc := New_List (
4256 Make_Pragma_Argument_Association (Ploc,
4257 Expression => Make_Identifier (Ploc, Nam)),
4258 Make_Pragma_Argument_Association (Ploc,
4259 Expression => Expr));
4261 -- Handle the String argument (if any)
4263 if Present (Arg3) then
4264 Str := Strval (Get_Pragma_Arg (Arg3));
4266 -- When inheriting an invariant, modify the message from
4267 -- "failed invariant" to "failed inherited invariant".
4269 if Inherit then
4270 String_To_Name_Buffer (Str);
4272 if Name_Buffer (1 .. 16) = "failed invariant" then
4273 Insert_Str_In_Name_Buffer ("inherited ", 8);
4274 Str := String_From_Name_Buffer;
4275 end if;
4276 end if;
4278 Append_To (Assoc,
4279 Make_Pragma_Argument_Association (Ploc,
4280 Expression => Make_String_Literal (Ploc, Str)));
4281 end if;
4283 -- Generate:
4284 -- pragma Check (<Nam>, <Expr>, <Str>);
4286 Append_New_To (Checks,
4287 Make_Pragma (Ploc,
4288 Chars => Name_Check,
4289 Pragma_Argument_Associations => Assoc));
4290 end if;
4292 -- Output an info message when inheriting an invariant and the
4293 -- listing option is enabled.
4295 if Inherit and Opt.List_Inherited_Aspects then
4296 Error_Msg_Sloc := Sloc (Prag);
4297 Error_Msg_N
4298 ("info: & inherits `Invariant''Class` aspect from #?L?", Typ);
4299 end if;
4301 -- Add the pragma to the list of processed pragmas
4303 Append_New_Elmt (Prag, Pragmas_Seen);
4304 Produced_Check := True;
4305 end Add_Invariant;
4307 ------------------
4308 -- Process_Type --
4309 ------------------
4311 procedure Process_Type
4312 (T : Entity_Id;
4313 Stop_Item : Node_Id := Empty)
4315 Rep_Item : Node_Id;
4317 begin
4318 Rep_Item := First_Rep_Item (T);
4319 while Present (Rep_Item) loop
4320 if Nkind (Rep_Item) = N_Pragma
4321 and then Pragma_Name (Rep_Item) = Name_Invariant
4322 then
4323 -- Stop the traversal of the rep item chain once a specific
4324 -- item is encountered.
4326 if Present (Stop_Item) and then Rep_Item = Stop_Item then
4327 exit;
4329 -- Otherwise generate an invariant check
4331 else
4332 Add_Invariant (Rep_Item);
4333 end if;
4334 end if;
4336 Next_Rep_Item (Rep_Item);
4337 end loop;
4338 end Process_Type;
4340 -- Start of processing for Add_Type_Invariants
4342 begin
4343 -- Process the invariants of the partial view
4345 if Present (Priv_Typ) then
4346 Process_Type (Priv_Typ);
4347 end if;
4349 -- Process the invariants of the full view
4351 if Present (Full_Typ) then
4352 Process_Type (Full_Typ, Stop_Item => Priv_Item);
4354 -- Process the elements of an array type
4356 if Is_Array_Type (Full_Typ) then
4357 Add_Array_Component_Invariants (Full_Typ, Obj_Id, Checks);
4359 -- Process the components of a record type
4361 elsif Ekind (Full_Typ) = E_Record_Type then
4362 Add_Record_Component_Invariants (Full_Typ, Obj_Id, Checks);
4363 end if;
4364 end if;
4366 -- Process the components of a corresponding record type
4368 if Present (CRec_Typ) then
4369 Add_Record_Component_Invariants (CRec_Typ, Obj_Id, Checks);
4370 end if;
4371 end Add_Type_Invariants;
4373 ------------------------------------
4374 -- Is_Untagged_Private_Derivation --
4375 ------------------------------------
4377 function Is_Untagged_Private_Derivation
4378 (Priv_Typ : Entity_Id;
4379 Full_Typ : Entity_Id) return Boolean
4381 begin
4382 return
4383 Present (Priv_Typ)
4384 and then Is_Untagged_Derivation (Priv_Typ)
4385 and then Is_Private_Type (Etype (Priv_Typ))
4386 and then Present (Full_Typ)
4387 and then Is_Itype (Full_Typ);
4388 end Is_Untagged_Private_Derivation;
4390 -- Local variables
4392 Dummy : Entity_Id;
4393 Mode : Ghost_Mode_Type;
4394 Priv_Item : Node_Id;
4395 Proc_Body : Node_Id;
4396 Proc_Body_Id : Entity_Id;
4397 Proc_Decl : Node_Id;
4398 Proc_Id : Entity_Id;
4399 Stmts : List_Id := No_List;
4401 CRec_Typ : Entity_Id;
4402 -- The corresponding record type of Full_Typ
4404 Full_Proc : Entity_Id;
4405 -- The entity of the "full" invariant procedure
4407 Full_Typ : Entity_Id;
4408 -- The full view of the working type
4410 Obj_Id : Entity_Id;
4411 -- The _object formal parameter of the invariant procedure
4413 Part_Proc : Entity_Id;
4414 -- The entity of the "partial" invariant procedure
4416 Priv_Typ : Entity_Id;
4417 -- The partial view of the working type
4419 Work_Typ : Entity_Id;
4420 -- The working type
4422 -- Start of processing for Build_Invariant_Procedure_Body
4424 begin
4425 Work_Typ := Typ;
4427 -- The input type denotes the implementation base type of a constrained
4428 -- array type. Work with the first subtype as all invariant pragmas are
4429 -- on its rep item chain.
4431 if Ekind (Work_Typ) = E_Array_Type and then Is_Itype (Work_Typ) then
4432 Work_Typ := First_Subtype (Work_Typ);
4434 -- The input type denotes the corresponding record type of a protected
4435 -- or task type. Work with the concurrent type because the corresponding
4436 -- record type may not be visible to clients of the type.
4438 elsif Ekind (Work_Typ) = E_Record_Type
4439 and then Is_Concurrent_Record_Type (Work_Typ)
4440 then
4441 Work_Typ := Corresponding_Concurrent_Type (Work_Typ);
4442 end if;
4444 -- The working type may be subject to pragma Ghost. Set the mode now to
4445 -- ensure that the invariant procedure is properly marked as Ghost.
4447 Set_Ghost_Mode (Work_Typ, Mode);
4449 -- The type must either have invariants of its own, inherit class-wide
4450 -- invariants from parent types or interfaces, or be an array or record
4451 -- type whose components have invariants.
4453 pragma Assert (Has_Invariants (Work_Typ));
4455 -- Nothing to do for interface types as their class-wide invariants are
4456 -- inherited by implementing types.
4458 if Is_Interface (Work_Typ) then
4459 goto Leave;
4460 end if;
4462 -- Obtain both views of the type
4464 Get_Views (Work_Typ, Priv_Typ, Full_Typ, Dummy, CRec_Typ);
4466 -- The caller requests a body for the partial invariant procedure
4468 if Partial_Invariant then
4469 Full_Proc := Invariant_Procedure (Work_Typ);
4470 Proc_Id := Partial_Invariant_Procedure (Work_Typ);
4472 -- The "full" invariant procedure body was already created
4474 if Present (Full_Proc)
4475 and then Present
4476 (Corresponding_Body (Unit_Declaration_Node (Full_Proc)))
4477 then
4478 -- This scenario happens only when the type is an untagged
4479 -- derivation from a private parent and the underlying full
4480 -- view was processed before the partial view.
4482 pragma Assert
4483 (Is_Untagged_Private_Derivation (Priv_Typ, Full_Typ));
4485 -- Nothing to do because the processing of the underlying full
4486 -- view already checked the invariants of the partial view.
4488 goto Leave;
4489 end if;
4491 -- Create a declaration for the "partial" invariant procedure if it
4492 -- is not available.
4494 if No (Proc_Id) then
4495 Build_Invariant_Procedure_Declaration
4496 (Typ => Work_Typ,
4497 Partial_Invariant => True);
4499 Proc_Id := Partial_Invariant_Procedure (Work_Typ);
4500 end if;
4502 -- The caller requests a body for the "full" invariant procedure
4504 else
4505 Proc_Id := Invariant_Procedure (Work_Typ);
4506 Part_Proc := Partial_Invariant_Procedure (Work_Typ);
4508 -- Create a declaration for the "full" invariant procedure if it is
4509 -- not available.
4511 if No (Proc_Id) then
4512 Build_Invariant_Procedure_Declaration (Work_Typ);
4513 Proc_Id := Invariant_Procedure (Work_Typ);
4514 end if;
4515 end if;
4517 -- At this point there should be an invariant procedure declaration
4519 pragma Assert (Present (Proc_Id));
4520 Proc_Decl := Unit_Declaration_Node (Proc_Id);
4522 -- Nothing to do if the invariant procedure already has a body
4524 if Present (Corresponding_Body (Proc_Decl)) then
4525 goto Leave;
4526 end if;
4528 -- Emulate the environment of the invariant procedure by installing
4529 -- its scope and formal parameters. Note that this is not needed, but
4530 -- having the scope of the invariant procedure installed helps with
4531 -- the detection of invariant-related errors.
4533 Push_Scope (Proc_Id);
4534 Install_Formals (Proc_Id);
4536 Obj_Id := First_Formal (Proc_Id);
4537 pragma Assert (Present (Obj_Id));
4539 -- The "partial" invariant procedure verifies the invariants of the
4540 -- partial view only.
4542 if Partial_Invariant then
4543 pragma Assert (Present (Priv_Typ));
4545 Add_Type_Invariants
4546 (Priv_Typ => Priv_Typ,
4547 Full_Typ => Empty,
4548 CRec_Typ => Empty,
4549 Obj_Id => Obj_Id,
4550 Checks => Stmts);
4552 -- Otherwise the "full" invariant procedure verifies the invariants of
4553 -- the full view, all array or record components, as well as class-wide
4554 -- invariants inherited from parent types or interfaces. In addition, it
4555 -- indirectly verifies the invariants of the partial view by calling the
4556 -- "partial" invariant procedure.
4558 else
4559 pragma Assert (Present (Full_Typ));
4561 -- Check the invariants of the partial view by calling the "partial"
4562 -- invariant procedure. Generate:
4564 -- <Work_Typ>Partial_Invariant (_object);
4566 if Present (Part_Proc) then
4567 Append_New_To (Stmts,
4568 Make_Procedure_Call_Statement (Loc,
4569 Name => New_Occurrence_Of (Part_Proc, Loc),
4570 Parameter_Associations => New_List (
4571 New_Occurrence_Of (Obj_Id, Loc))));
4573 Produced_Check := True;
4574 end if;
4576 Priv_Item := Empty;
4578 -- Derived subtypes do not have a partial view
4580 if Present (Priv_Typ) then
4582 -- The processing of the "full" invariant procedure intentionally
4583 -- skips the partial view because a) this may result in changes of
4584 -- visibility and b) lead to duplicate checks. However, when the
4585 -- full view is the underlying full view of an untagged derived
4586 -- type whose parent type is private, partial invariants appear on
4587 -- the rep item chain of the partial view only.
4589 -- package Pack_1 is
4590 -- type Root ... is private;
4591 -- private
4592 -- <full view of Root>
4593 -- end Pack_1;
4595 -- with Pack_1;
4596 -- package Pack_2 is
4597 -- type Child is new Pack_1.Root with Type_Invariant => ...;
4598 -- <underlying full view of Child>
4599 -- end Pack_2;
4601 -- As a result, the processing of the full view must also consider
4602 -- all invariants of the partial view.
4604 if Is_Untagged_Private_Derivation (Priv_Typ, Full_Typ) then
4605 null;
4607 -- Otherwise the invariants of the partial view are ignored
4609 else
4610 -- Note that the rep item chain is shared between the partial
4611 -- and full views of a type. To avoid processing the invariants
4612 -- of the partial view, signal the logic to stop when the first
4613 -- rep item of the partial view has been reached.
4615 Priv_Item := First_Rep_Item (Priv_Typ);
4617 -- Ignore the invariants of the partial view by eliminating the
4618 -- view.
4620 Priv_Typ := Empty;
4621 end if;
4622 end if;
4624 -- Process the invariants of the full view and in certain cases those
4625 -- of the partial view. This also handles any invariants on array or
4626 -- record components.
4628 Add_Type_Invariants
4629 (Priv_Typ => Priv_Typ,
4630 Full_Typ => Full_Typ,
4631 CRec_Typ => CRec_Typ,
4632 Obj_Id => Obj_Id,
4633 Checks => Stmts,
4634 Priv_Item => Priv_Item);
4636 -- Process the inherited class-wide invariants of all parent types.
4637 -- This also handles any invariants on record components.
4639 Add_Parent_Invariants (Full_Typ, Obj_Id, Stmts);
4641 -- Process the inherited class-wide invariants of all implemented
4642 -- interface types.
4644 Add_Interface_Invariants (Full_Typ, Obj_Id, Stmts);
4645 end if;
4647 End_Scope;
4649 -- At this point there should be at least one invariant check. If this
4650 -- is not the case, then the invariant-related flags were not properly
4651 -- set, or there is a missing invariant procedure on one of the array
4652 -- or record components.
4654 pragma Assert (Produced_Check);
4656 -- Account for the case where assertions are disabled or all invariant
4657 -- checks are subject to Assertion_Policy Ignore. Produce a completing
4658 -- empty body.
4660 if No (Stmts) then
4661 Stmts := New_List (Make_Null_Statement (Loc));
4662 end if;
4664 -- Generate:
4665 -- procedure <Work_Typ>[Partial_]Invariant (_object : <Work_Typ>) is
4666 -- begin
4667 -- <Stmts>
4668 -- end <Work_Typ>[Partial_]Invariant;
4670 Proc_Body :=
4671 Make_Subprogram_Body (Loc,
4672 Specification =>
4673 Copy_Subprogram_Spec (Parent (Proc_Id)),
4674 Declarations => Empty_List,
4675 Handled_Statement_Sequence =>
4676 Make_Handled_Sequence_Of_Statements (Loc,
4677 Statements => Stmts));
4678 Proc_Body_Id := Defining_Entity (Proc_Body);
4680 -- Perform minor decoration in case the body is not analyzed
4682 Set_Ekind (Proc_Body_Id, E_Subprogram_Body);
4683 Set_Etype (Proc_Body_Id, Standard_Void_Type);
4684 Set_Scope (Proc_Body_Id, Current_Scope);
4686 -- Link both spec and body to avoid generating duplicates
4688 Set_Corresponding_Body (Proc_Decl, Proc_Body_Id);
4689 Set_Corresponding_Spec (Proc_Body, Proc_Id);
4691 -- The body should not be inserted into the tree when the context is
4692 -- ASIS or a generic unit because it is not part of the template. Note
4693 -- that the body must still be generated in order to resolve the
4694 -- invariants.
4696 if ASIS_Mode or Inside_A_Generic then
4697 null;
4699 -- Semi-insert the body into the tree for GNATprove by setting its
4700 -- Parent field. This allows for proper upstream tree traversals.
4702 elsif GNATprove_Mode then
4703 Set_Parent (Proc_Body, Parent (Declaration_Node (Work_Typ)));
4705 -- Otherwise the body is part of the freezing actions of the type
4707 else
4708 Append_Freeze_Action (Work_Typ, Proc_Body);
4709 end if;
4711 <<Leave>>
4712 Restore_Ghost_Mode (Mode);
4713 end Build_Invariant_Procedure_Body;
4715 -------------------------------------------
4716 -- Build_Invariant_Procedure_Declaration --
4717 -------------------------------------------
4719 -- WARNING: This routine manages Ghost regions. Return statements must be
4720 -- replaced by gotos which jump to the end of the routine and restore the
4721 -- Ghost mode.
4723 procedure Build_Invariant_Procedure_Declaration
4724 (Typ : Entity_Id;
4725 Partial_Invariant : Boolean := False)
4727 Loc : constant Source_Ptr := Sloc (Typ);
4729 Mode : Ghost_Mode_Type;
4730 Proc_Decl : Node_Id;
4731 Proc_Id : Entity_Id;
4732 Proc_Nam : Name_Id;
4733 Typ_Decl : Node_Id;
4735 CRec_Typ : Entity_Id;
4736 -- The corresponding record type of Full_Typ
4738 Full_Base : Entity_Id;
4739 -- The base type of Full_Typ
4741 Full_Typ : Entity_Id;
4742 -- The full view of working type
4744 Obj_Id : Entity_Id;
4745 -- The _object formal parameter of the invariant procedure
4747 Priv_Typ : Entity_Id;
4748 -- The partial view of working type
4750 Work_Typ : Entity_Id;
4751 -- The working type
4753 begin
4754 Work_Typ := Typ;
4756 -- The input type denotes the implementation base type of a constrained
4757 -- array type. Work with the first subtype as all invariant pragmas are
4758 -- on its rep item chain.
4760 if Ekind (Work_Typ) = E_Array_Type and then Is_Itype (Work_Typ) then
4761 Work_Typ := First_Subtype (Work_Typ);
4763 -- The input denotes the corresponding record type of a protected or a
4764 -- task type. Work with the concurrent type because the corresponding
4765 -- record type may not be visible to clients of the type.
4767 elsif Ekind (Work_Typ) = E_Record_Type
4768 and then Is_Concurrent_Record_Type (Work_Typ)
4769 then
4770 Work_Typ := Corresponding_Concurrent_Type (Work_Typ);
4771 end if;
4773 -- The working type may be subject to pragma Ghost. Set the mode now to
4774 -- ensure that the invariant procedure is properly marked as Ghost.
4776 Set_Ghost_Mode (Work_Typ, Mode);
4778 -- The type must either have invariants of its own, inherit class-wide
4779 -- invariants from parent or interface types, or be an array or record
4780 -- type whose components have invariants.
4782 pragma Assert (Has_Invariants (Work_Typ));
4784 -- Nothing to do for interface types as their class-wide invariants are
4785 -- inherited by implementing types.
4787 if Is_Interface (Work_Typ) then
4788 goto Leave;
4790 -- Nothing to do if the type already has a "partial" invariant procedure
4792 elsif Partial_Invariant then
4793 if Present (Partial_Invariant_Procedure (Work_Typ)) then
4794 goto Leave;
4795 end if;
4797 -- Nothing to do if the type already has a "full" invariant procedure
4799 elsif Present (Invariant_Procedure (Work_Typ)) then
4800 goto Leave;
4801 end if;
4803 -- The caller requests the declaration of the "partial" invariant
4804 -- procedure.
4806 if Partial_Invariant then
4807 Proc_Nam := New_External_Name (Chars (Work_Typ), "Partial_Invariant");
4809 -- Otherwise the caller requests the declaration of the "full" invariant
4810 -- procedure.
4812 else
4813 Proc_Nam := New_External_Name (Chars (Work_Typ), "Invariant");
4814 end if;
4816 Proc_Id := Make_Defining_Identifier (Loc, Chars => Proc_Nam);
4818 -- Perform minor decoration in case the declaration is not analyzed
4820 Set_Ekind (Proc_Id, E_Procedure);
4821 Set_Etype (Proc_Id, Standard_Void_Type);
4822 Set_Scope (Proc_Id, Current_Scope);
4824 if Partial_Invariant then
4825 Set_Is_Partial_Invariant_Procedure (Proc_Id);
4826 Set_Partial_Invariant_Procedure (Work_Typ, Proc_Id);
4827 else
4828 Set_Is_Invariant_Procedure (Proc_Id);
4829 Set_Invariant_Procedure (Work_Typ, Proc_Id);
4830 end if;
4832 -- The invariant procedure requires debug info when the invariants are
4833 -- subject to Source Coverage Obligations.
4835 if Opt.Generate_SCO then
4836 Set_Needs_Debug_Info (Proc_Id);
4837 end if;
4839 -- Obtain all views of the input type
4841 Get_Views (Work_Typ, Priv_Typ, Full_Typ, Full_Base, CRec_Typ);
4843 -- Associate the invariant procedure with all views
4845 Propagate_Invariant_Attributes (Priv_Typ, From_Typ => Work_Typ);
4846 Propagate_Invariant_Attributes (Full_Typ, From_Typ => Work_Typ);
4847 Propagate_Invariant_Attributes (Full_Base, From_Typ => Work_Typ);
4848 Propagate_Invariant_Attributes (CRec_Typ, From_Typ => Work_Typ);
4850 -- The declaration of the invariant procedure is inserted after the
4851 -- declaration of the partial view as this allows for proper external
4852 -- visibility.
4854 if Present (Priv_Typ) then
4855 Typ_Decl := Declaration_Node (Priv_Typ);
4857 -- Derived types with the full view as parent do not have a partial
4858 -- view. Insert the invariant procedure after the derived type.
4860 else
4861 Typ_Decl := Declaration_Node (Full_Typ);
4862 end if;
4864 -- The type should have a declarative node
4866 pragma Assert (Present (Typ_Decl));
4868 -- Create the formal parameter which emulates the variable-like behavior
4869 -- of the current type instance.
4871 Obj_Id := Make_Defining_Identifier (Loc, Chars => Name_uObject);
4873 -- Perform minor decoration in case the declaration is not analyzed
4875 Set_Ekind (Obj_Id, E_In_Parameter);
4876 Set_Etype (Obj_Id, Work_Typ);
4877 Set_Scope (Obj_Id, Proc_Id);
4879 Set_First_Entity (Proc_Id, Obj_Id);
4881 -- Generate:
4882 -- procedure <Work_Typ>[Partial_]Invariant (_object : <Work_Typ>);
4884 Proc_Decl :=
4885 Make_Subprogram_Declaration (Loc,
4886 Specification =>
4887 Make_Procedure_Specification (Loc,
4888 Defining_Unit_Name => Proc_Id,
4889 Parameter_Specifications => New_List (
4890 Make_Parameter_Specification (Loc,
4891 Defining_Identifier => Obj_Id,
4892 Parameter_Type =>
4893 New_Occurrence_Of (Work_Typ, Loc)))));
4895 -- The declaration should not be inserted into the tree when the context
4896 -- is ASIS or a generic unit because it is not part of the template.
4898 if ASIS_Mode or Inside_A_Generic then
4899 null;
4901 -- Semi-insert the declaration into the tree for GNATprove by setting
4902 -- its Parent field. This allows for proper upstream tree traversals.
4904 elsif GNATprove_Mode then
4905 Set_Parent (Proc_Decl, Parent (Typ_Decl));
4907 -- Otherwise insert the declaration
4909 else
4910 pragma Assert (Present (Typ_Decl));
4911 Insert_After_And_Analyze (Typ_Decl, Proc_Decl);
4912 end if;
4914 <<Leave>>
4915 Restore_Ghost_Mode (Mode);
4916 end Build_Invariant_Procedure_Declaration;
4918 ---------------------
4919 -- Build_Late_Proc --
4920 ---------------------
4922 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
4923 begin
4924 for Final_Prim in Name_Of'Range loop
4925 if Name_Of (Final_Prim) = Nam then
4926 Set_TSS (Typ,
4927 Make_Deep_Proc
4928 (Prim => Final_Prim,
4929 Typ => Typ,
4930 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
4931 end if;
4932 end loop;
4933 end Build_Late_Proc;
4935 -------------------------------
4936 -- Build_Object_Declarations --
4937 -------------------------------
4939 procedure Build_Object_Declarations
4940 (Data : out Finalization_Exception_Data;
4941 Decls : List_Id;
4942 Loc : Source_Ptr;
4943 For_Package : Boolean := False)
4945 Decl : Node_Id;
4947 Dummy : Entity_Id;
4948 -- This variable captures an unused dummy internal entity, see the
4949 -- comment associated with its use.
4951 begin
4952 pragma Assert (Decls /= No_List);
4954 -- Always set the proper location as it may be needed even when
4955 -- exception propagation is forbidden.
4957 Data.Loc := Loc;
4959 if Restriction_Active (No_Exception_Propagation) then
4960 Data.Abort_Id := Empty;
4961 Data.E_Id := Empty;
4962 Data.Raised_Id := Empty;
4963 return;
4964 end if;
4966 Data.Raised_Id := Make_Temporary (Loc, 'R');
4968 -- In certain scenarios, finalization can be triggered by an abort. If
4969 -- the finalization itself fails and raises an exception, the resulting
4970 -- Program_Error must be supressed and replaced by an abort signal. In
4971 -- order to detect this scenario, save the state of entry into the
4972 -- finalization code.
4974 -- This is not needed for library-level finalizers as they are called by
4975 -- the environment task and cannot be aborted.
4977 if not For_Package then
4978 if Abort_Allowed then
4979 Data.Abort_Id := Make_Temporary (Loc, 'A');
4981 -- Generate:
4982 -- Abort_Id : constant Boolean := <A_Expr>;
4984 Append_To (Decls,
4985 Make_Object_Declaration (Loc,
4986 Defining_Identifier => Data.Abort_Id,
4987 Constant_Present => True,
4988 Object_Definition =>
4989 New_Occurrence_Of (Standard_Boolean, Loc),
4990 Expression =>
4991 New_Occurrence_Of (RTE (RE_Triggered_By_Abort), Loc)));
4993 -- Abort is not required
4995 else
4996 -- Generate a dummy entity to ensure that the internal symbols are
4997 -- in sync when a unit is compiled with and without aborts.
4999 Dummy := Make_Temporary (Loc, 'A');
5000 Data.Abort_Id := Empty;
5001 end if;
5003 -- Library-level finalizers
5005 else
5006 Data.Abort_Id := Empty;
5007 end if;
5009 if Exception_Extra_Info then
5010 Data.E_Id := Make_Temporary (Loc, 'E');
5012 -- Generate:
5013 -- E_Id : Exception_Occurrence;
5015 Decl :=
5016 Make_Object_Declaration (Loc,
5017 Defining_Identifier => Data.E_Id,
5018 Object_Definition =>
5019 New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc));
5020 Set_No_Initialization (Decl);
5022 Append_To (Decls, Decl);
5024 else
5025 Data.E_Id := Empty;
5026 end if;
5028 -- Generate:
5029 -- Raised_Id : Boolean := False;
5031 Append_To (Decls,
5032 Make_Object_Declaration (Loc,
5033 Defining_Identifier => Data.Raised_Id,
5034 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
5035 Expression => New_Occurrence_Of (Standard_False, Loc)));
5036 end Build_Object_Declarations;
5038 ---------------------------
5039 -- Build_Raise_Statement --
5040 ---------------------------
5042 function Build_Raise_Statement
5043 (Data : Finalization_Exception_Data) return Node_Id
5045 Stmt : Node_Id;
5046 Expr : Node_Id;
5048 begin
5049 -- Standard run-time use the specialized routine
5050 -- Raise_From_Controlled_Operation.
5052 if Exception_Extra_Info
5053 and then RTE_Available (RE_Raise_From_Controlled_Operation)
5054 then
5055 Stmt :=
5056 Make_Procedure_Call_Statement (Data.Loc,
5057 Name =>
5058 New_Occurrence_Of
5059 (RTE (RE_Raise_From_Controlled_Operation), Data.Loc),
5060 Parameter_Associations =>
5061 New_List (New_Occurrence_Of (Data.E_Id, Data.Loc)));
5063 -- Restricted run-time: exception messages are not supported and hence
5064 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
5065 -- instead.
5067 else
5068 Stmt :=
5069 Make_Raise_Program_Error (Data.Loc,
5070 Reason => PE_Finalize_Raised_Exception);
5071 end if;
5073 -- Generate:
5075 -- Raised_Id and then not Abort_Id
5076 -- <or>
5077 -- Raised_Id
5079 Expr := New_Occurrence_Of (Data.Raised_Id, Data.Loc);
5081 if Present (Data.Abort_Id) then
5082 Expr := Make_And_Then (Data.Loc,
5083 Left_Opnd => Expr,
5084 Right_Opnd =>
5085 Make_Op_Not (Data.Loc,
5086 Right_Opnd => New_Occurrence_Of (Data.Abort_Id, Data.Loc)));
5087 end if;
5089 -- Generate:
5091 -- if Raised_Id and then not Abort_Id then
5092 -- Raise_From_Controlled_Operation (E_Id);
5093 -- <or>
5094 -- raise Program_Error; -- restricted runtime
5095 -- end if;
5097 return
5098 Make_If_Statement (Data.Loc,
5099 Condition => Expr,
5100 Then_Statements => New_List (Stmt));
5101 end Build_Raise_Statement;
5103 -----------------------------
5104 -- Build_Record_Deep_Procs --
5105 -----------------------------
5107 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
5108 begin
5109 Set_TSS (Typ,
5110 Make_Deep_Proc
5111 (Prim => Initialize_Case,
5112 Typ => Typ,
5113 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
5115 if not Is_Limited_View (Typ) then
5116 Set_TSS (Typ,
5117 Make_Deep_Proc
5118 (Prim => Adjust_Case,
5119 Typ => Typ,
5120 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
5121 end if;
5123 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
5124 -- suppressed since these routine will not be used.
5126 if not Restriction_Active (No_Finalization) then
5127 Set_TSS (Typ,
5128 Make_Deep_Proc
5129 (Prim => Finalize_Case,
5130 Typ => Typ,
5131 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
5133 -- Create TSS primitive Finalize_Address
5135 Set_TSS (Typ,
5136 Make_Deep_Proc
5137 (Prim => Address_Case,
5138 Typ => Typ,
5139 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
5140 end if;
5141 end Build_Record_Deep_Procs;
5143 -------------------
5144 -- Cleanup_Array --
5145 -------------------
5147 function Cleanup_Array
5148 (N : Node_Id;
5149 Obj : Node_Id;
5150 Typ : Entity_Id) return List_Id
5152 Loc : constant Source_Ptr := Sloc (N);
5153 Index_List : constant List_Id := New_List;
5155 function Free_Component return List_Id;
5156 -- Generate the code to finalize the task or protected subcomponents
5157 -- of a single component of the array.
5159 function Free_One_Dimension (Dim : Int) return List_Id;
5160 -- Generate a loop over one dimension of the array
5162 --------------------
5163 -- Free_Component --
5164 --------------------
5166 function Free_Component return List_Id is
5167 Stmts : List_Id := New_List;
5168 Tsk : Node_Id;
5169 C_Typ : constant Entity_Id := Component_Type (Typ);
5171 begin
5172 -- Component type is known to contain tasks or protected objects
5174 Tsk :=
5175 Make_Indexed_Component (Loc,
5176 Prefix => Duplicate_Subexpr_No_Checks (Obj),
5177 Expressions => Index_List);
5179 Set_Etype (Tsk, C_Typ);
5181 if Is_Task_Type (C_Typ) then
5182 Append_To (Stmts, Cleanup_Task (N, Tsk));
5184 elsif Is_Simple_Protected_Type (C_Typ) then
5185 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
5187 elsif Is_Record_Type (C_Typ) then
5188 Stmts := Cleanup_Record (N, Tsk, C_Typ);
5190 elsif Is_Array_Type (C_Typ) then
5191 Stmts := Cleanup_Array (N, Tsk, C_Typ);
5192 end if;
5194 return Stmts;
5195 end Free_Component;
5197 ------------------------
5198 -- Free_One_Dimension --
5199 ------------------------
5201 function Free_One_Dimension (Dim : Int) return List_Id is
5202 Index : Entity_Id;
5204 begin
5205 if Dim > Number_Dimensions (Typ) then
5206 return Free_Component;
5208 -- Here we generate the required loop
5210 else
5211 Index := Make_Temporary (Loc, 'J');
5212 Append (New_Occurrence_Of (Index, Loc), Index_List);
5214 return New_List (
5215 Make_Implicit_Loop_Statement (N,
5216 Identifier => Empty,
5217 Iteration_Scheme =>
5218 Make_Iteration_Scheme (Loc,
5219 Loop_Parameter_Specification =>
5220 Make_Loop_Parameter_Specification (Loc,
5221 Defining_Identifier => Index,
5222 Discrete_Subtype_Definition =>
5223 Make_Attribute_Reference (Loc,
5224 Prefix => Duplicate_Subexpr (Obj),
5225 Attribute_Name => Name_Range,
5226 Expressions => New_List (
5227 Make_Integer_Literal (Loc, Dim))))),
5228 Statements => Free_One_Dimension (Dim + 1)));
5229 end if;
5230 end Free_One_Dimension;
5232 -- Start of processing for Cleanup_Array
5234 begin
5235 return Free_One_Dimension (1);
5236 end Cleanup_Array;
5238 --------------------
5239 -- Cleanup_Record --
5240 --------------------
5242 function Cleanup_Record
5243 (N : Node_Id;
5244 Obj : Node_Id;
5245 Typ : Entity_Id) return List_Id
5247 Loc : constant Source_Ptr := Sloc (N);
5248 Tsk : Node_Id;
5249 Comp : Entity_Id;
5250 Stmts : constant List_Id := New_List;
5251 U_Typ : constant Entity_Id := Underlying_Type (Typ);
5253 begin
5254 if Has_Discriminants (U_Typ)
5255 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
5256 and then Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
5257 and then
5258 Present
5259 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
5260 then
5261 -- For now, do not attempt to free a component that may appear in a
5262 -- variant, and instead issue a warning. Doing this "properly" would
5263 -- require building a case statement and would be quite a mess. Note
5264 -- that the RM only requires that free "work" for the case of a task
5265 -- access value, so already we go way beyond this in that we deal
5266 -- with the array case and non-discriminated record cases.
5268 Error_Msg_N
5269 ("task/protected object in variant record will not be freed??", N);
5270 return New_List (Make_Null_Statement (Loc));
5271 end if;
5273 Comp := First_Component (Typ);
5274 while Present (Comp) loop
5275 if Has_Task (Etype (Comp))
5276 or else Has_Simple_Protected_Object (Etype (Comp))
5277 then
5278 Tsk :=
5279 Make_Selected_Component (Loc,
5280 Prefix => Duplicate_Subexpr_No_Checks (Obj),
5281 Selector_Name => New_Occurrence_Of (Comp, Loc));
5282 Set_Etype (Tsk, Etype (Comp));
5284 if Is_Task_Type (Etype (Comp)) then
5285 Append_To (Stmts, Cleanup_Task (N, Tsk));
5287 elsif Is_Simple_Protected_Type (Etype (Comp)) then
5288 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
5290 elsif Is_Record_Type (Etype (Comp)) then
5292 -- Recurse, by generating the prefix of the argument to
5293 -- the eventual cleanup call.
5295 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
5297 elsif Is_Array_Type (Etype (Comp)) then
5298 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
5299 end if;
5300 end if;
5302 Next_Component (Comp);
5303 end loop;
5305 return Stmts;
5306 end Cleanup_Record;
5308 ------------------------------
5309 -- Cleanup_Protected_Object --
5310 ------------------------------
5312 function Cleanup_Protected_Object
5313 (N : Node_Id;
5314 Ref : Node_Id) return Node_Id
5316 Loc : constant Source_Ptr := Sloc (N);
5318 begin
5319 -- For restricted run-time libraries (Ravenscar), tasks are
5320 -- non-terminating, and protected objects can only appear at library
5321 -- level, so we do not want finalization of protected objects.
5323 if Restricted_Profile then
5324 return Empty;
5326 else
5327 return
5328 Make_Procedure_Call_Statement (Loc,
5329 Name =>
5330 New_Occurrence_Of (RTE (RE_Finalize_Protection), Loc),
5331 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
5332 end if;
5333 end Cleanup_Protected_Object;
5335 ------------------
5336 -- Cleanup_Task --
5337 ------------------
5339 function Cleanup_Task
5340 (N : Node_Id;
5341 Ref : Node_Id) return Node_Id
5343 Loc : constant Source_Ptr := Sloc (N);
5345 begin
5346 -- For restricted run-time libraries (Ravenscar), tasks are
5347 -- non-terminating and they can only appear at library level, so we do
5348 -- not want finalization of task objects.
5350 if Restricted_Profile then
5351 return Empty;
5353 else
5354 return
5355 Make_Procedure_Call_Statement (Loc,
5356 Name =>
5357 New_Occurrence_Of (RTE (RE_Free_Task), Loc),
5358 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
5359 end if;
5360 end Cleanup_Task;
5362 ------------------------------
5363 -- Check_Visibly_Controlled --
5364 ------------------------------
5366 procedure Check_Visibly_Controlled
5367 (Prim : Final_Primitives;
5368 Typ : Entity_Id;
5369 E : in out Entity_Id;
5370 Cref : in out Node_Id)
5372 Parent_Type : Entity_Id;
5373 Op : Entity_Id;
5375 begin
5376 if Is_Derived_Type (Typ)
5377 and then Comes_From_Source (E)
5378 and then not Present (Overridden_Operation (E))
5379 then
5380 -- We know that the explicit operation on the type does not override
5381 -- the inherited operation of the parent, and that the derivation
5382 -- is from a private type that is not visibly controlled.
5384 Parent_Type := Etype (Typ);
5385 Op := Find_Optional_Prim_Op (Parent_Type, Name_Of (Prim));
5387 if Present (Op) then
5388 E := Op;
5390 -- Wrap the object to be initialized into the proper
5391 -- unchecked conversion, to be compatible with the operation
5392 -- to be called.
5394 if Nkind (Cref) = N_Unchecked_Type_Conversion then
5395 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
5396 else
5397 Cref := Unchecked_Convert_To (Parent_Type, Cref);
5398 end if;
5399 end if;
5400 end if;
5401 end Check_Visibly_Controlled;
5403 ------------------
5404 -- Convert_View --
5405 ------------------
5407 function Convert_View
5408 (Proc : Entity_Id;
5409 Arg : Node_Id;
5410 Ind : Pos := 1) return Node_Id
5412 Fent : Entity_Id := First_Entity (Proc);
5413 Ftyp : Entity_Id;
5414 Atyp : Entity_Id;
5416 begin
5417 for J in 2 .. Ind loop
5418 Next_Entity (Fent);
5419 end loop;
5421 Ftyp := Etype (Fent);
5423 if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
5424 Atyp := Entity (Subtype_Mark (Arg));
5425 else
5426 Atyp := Etype (Arg);
5427 end if;
5429 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
5430 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
5432 elsif Ftyp /= Atyp
5433 and then Present (Atyp)
5434 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
5435 and then Base_Type (Underlying_Type (Atyp)) =
5436 Base_Type (Underlying_Type (Ftyp))
5437 then
5438 return Unchecked_Convert_To (Ftyp, Arg);
5440 -- If the argument is already a conversion, as generated by
5441 -- Make_Init_Call, set the target type to the type of the formal
5442 -- directly, to avoid spurious typing problems.
5444 elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
5445 and then not Is_Class_Wide_Type (Atyp)
5446 then
5447 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
5448 Set_Etype (Arg, Ftyp);
5449 return Arg;
5451 -- Otherwise, introduce a conversion when the designated object
5452 -- has a type derived from the formal of the controlled routine.
5454 elsif Is_Private_Type (Ftyp)
5455 and then Present (Atyp)
5456 and then Is_Derived_Type (Underlying_Type (Base_Type (Atyp)))
5457 then
5458 return Unchecked_Convert_To (Ftyp, Arg);
5460 else
5461 return Arg;
5462 end if;
5463 end Convert_View;
5465 -------------------------------
5466 -- CW_Or_Has_Controlled_Part --
5467 -------------------------------
5469 function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
5470 begin
5471 return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
5472 end CW_Or_Has_Controlled_Part;
5474 ------------------------
5475 -- Enclosing_Function --
5476 ------------------------
5478 function Enclosing_Function (E : Entity_Id) return Entity_Id is
5479 Func_Id : Entity_Id;
5481 begin
5482 Func_Id := E;
5483 while Present (Func_Id) and then Func_Id /= Standard_Standard loop
5484 if Ekind (Func_Id) = E_Function then
5485 return Func_Id;
5486 end if;
5488 Func_Id := Scope (Func_Id);
5489 end loop;
5491 return Empty;
5492 end Enclosing_Function;
5494 -------------------------------
5495 -- Establish_Transient_Scope --
5496 -------------------------------
5498 -- This procedure is called each time a transient block has to be inserted
5499 -- that is to say for each call to a function with unconstrained or tagged
5500 -- result. It creates a new scope on the stack scope in order to enclose
5501 -- all transient variables generated.
5503 procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
5504 Loc : constant Source_Ptr := Sloc (N);
5505 Iter_Loop : Entity_Id;
5506 Wrap_Node : Node_Id;
5508 begin
5509 -- Do not create a transient scope if we are already inside one
5511 for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
5512 if Scope_Stack.Table (S).Is_Transient then
5513 if Sec_Stack then
5514 Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
5515 end if;
5517 return;
5519 -- If we encounter Standard there are no enclosing transient scopes
5521 elsif Scope_Stack.Table (S).Entity = Standard_Standard then
5522 exit;
5523 end if;
5524 end loop;
5526 Wrap_Node := Find_Node_To_Be_Wrapped (N);
5528 -- The context does not contain a node that requires a transient scope,
5529 -- nothing to do.
5531 if No (Wrap_Node) then
5532 null;
5534 -- If the node to wrap is an iteration_scheme, the expression is one of
5535 -- the bounds, and the expansion will make an explicit declaration for
5536 -- it (see Analyze_Iteration_Scheme, sem_ch5.adb), so do not apply any
5537 -- transformations here. Same for an Ada 2012 iterator specification,
5538 -- where a block is created for the expression that build the container.
5540 elsif Nkind_In (Wrap_Node, N_Iteration_Scheme,
5541 N_Iterator_Specification)
5542 then
5543 null;
5545 -- In formal verification mode, if the node to wrap is a pragma check,
5546 -- this node and enclosed expression are not expanded, so do not apply
5547 -- any transformations here.
5549 elsif GNATprove_Mode
5550 and then Nkind (Wrap_Node) = N_Pragma
5551 and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
5552 then
5553 null;
5555 -- Create a block entity to act as a transient scope. Note that when the
5556 -- node to be wrapped is an expression or a statement, a real physical
5557 -- block is constructed (see routines Wrap_Transient_Expression and
5558 -- Wrap_Transient_Statement) and inserted into the tree.
5560 else
5561 Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
5562 Set_Scope_Is_Transient;
5564 -- The transient scope must also take care of the secondary stack
5565 -- management.
5567 if Sec_Stack then
5568 Set_Uses_Sec_Stack (Current_Scope);
5569 Check_Restriction (No_Secondary_Stack, N);
5571 -- The expansion of iterator loops generates references to objects
5572 -- in order to extract elements from a container:
5574 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
5575 -- Obj : <object type> renames Ref.all.Element.all;
5577 -- These references are controlled and returned on the secondary
5578 -- stack. A new reference is created at each iteration of the loop
5579 -- and as a result it must be finalized and the space occupied by
5580 -- it on the secondary stack reclaimed at the end of the current
5581 -- iteration.
5583 -- When the context that requires a transient scope is a call to
5584 -- routine Reference, the node to be wrapped is the source object:
5586 -- for Obj of Container loop
5588 -- Routine Wrap_Transient_Declaration however does not generate a
5589 -- physical block as wrapping a declaration will kill it too ealy.
5590 -- To handle this peculiar case, mark the related iterator loop as
5591 -- requiring the secondary stack. This signals the finalization
5592 -- machinery to manage the secondary stack (see routine
5593 -- Process_Statements_For_Controlled_Objects).
5595 Iter_Loop := Find_Enclosing_Iterator_Loop (Current_Scope);
5597 if Present (Iter_Loop) then
5598 Set_Uses_Sec_Stack (Iter_Loop);
5599 end if;
5600 end if;
5602 Set_Etype (Current_Scope, Standard_Void_Type);
5603 Set_Node_To_Be_Wrapped (Wrap_Node);
5605 if Debug_Flag_W then
5606 Write_Str (" <Transient>");
5607 Write_Eol;
5608 end if;
5609 end if;
5610 end Establish_Transient_Scope;
5612 ----------------------------
5613 -- Expand_Cleanup_Actions --
5614 ----------------------------
5616 procedure Expand_Cleanup_Actions (N : Node_Id) is
5617 Scop : constant Entity_Id := Current_Scope;
5619 Is_Asynchronous_Call : constant Boolean :=
5620 Nkind (N) = N_Block_Statement
5621 and then Is_Asynchronous_Call_Block (N);
5622 Is_Master : constant Boolean :=
5623 Nkind (N) /= N_Entry_Body
5624 and then Is_Task_Master (N);
5625 Is_Protected_Body : constant Boolean :=
5626 Nkind (N) = N_Subprogram_Body
5627 and then Is_Protected_Subprogram_Body (N);
5628 Is_Task_Allocation : constant Boolean :=
5629 Nkind (N) = N_Block_Statement
5630 and then Is_Task_Allocation_Block (N);
5631 Is_Task_Body : constant Boolean :=
5632 Nkind (Original_Node (N)) = N_Task_Body;
5633 Needs_Sec_Stack_Mark : constant Boolean :=
5634 Uses_Sec_Stack (Scop)
5635 and then
5636 not Sec_Stack_Needed_For_Return (Scop);
5637 Needs_Custom_Cleanup : constant Boolean :=
5638 Nkind (N) = N_Block_Statement
5639 and then Present (Cleanup_Actions (N));
5641 Actions_Required : constant Boolean :=
5642 Requires_Cleanup_Actions (N, True)
5643 or else Is_Asynchronous_Call
5644 or else Is_Master
5645 or else Is_Protected_Body
5646 or else Is_Task_Allocation
5647 or else Is_Task_Body
5648 or else Needs_Sec_Stack_Mark
5649 or else Needs_Custom_Cleanup;
5651 HSS : Node_Id := Handled_Statement_Sequence (N);
5652 Loc : Source_Ptr;
5653 Cln : List_Id;
5655 procedure Wrap_HSS_In_Block;
5656 -- Move HSS inside a new block along with the original exception
5657 -- handlers. Make the newly generated block the sole statement of HSS.
5659 -----------------------
5660 -- Wrap_HSS_In_Block --
5661 -----------------------
5663 procedure Wrap_HSS_In_Block is
5664 Block : Node_Id;
5665 Block_Id : Entity_Id;
5666 End_Lab : Node_Id;
5668 begin
5669 -- Preserve end label to provide proper cross-reference information
5671 End_Lab := End_Label (HSS);
5672 Block :=
5673 Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
5675 Block_Id := New_Internal_Entity (E_Block, Current_Scope, Loc, 'B');
5676 Set_Identifier (Block, New_Occurrence_Of (Block_Id, Loc));
5677 Set_Etype (Block_Id, Standard_Void_Type);
5678 Set_Block_Node (Block_Id, Identifier (Block));
5680 -- Signal the finalization machinery that this particular block
5681 -- contains the original context.
5683 Set_Is_Finalization_Wrapper (Block);
5685 Set_Handled_Statement_Sequence (N,
5686 Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
5687 HSS := Handled_Statement_Sequence (N);
5689 Set_First_Real_Statement (HSS, Block);
5690 Set_End_Label (HSS, End_Lab);
5692 -- Comment needed here, see RH for 1.306 ???
5694 if Nkind (N) = N_Subprogram_Body then
5695 Set_Has_Nested_Block_With_Handler (Scop);
5696 end if;
5697 end Wrap_HSS_In_Block;
5699 -- Start of processing for Expand_Cleanup_Actions
5701 begin
5702 -- The current construct does not need any form of servicing
5704 if not Actions_Required then
5705 return;
5707 -- If the current node is a rewritten task body and the descriptors have
5708 -- not been delayed (due to some nested instantiations), do not generate
5709 -- redundant cleanup actions.
5711 elsif Is_Task_Body
5712 and then Nkind (N) = N_Subprogram_Body
5713 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
5714 then
5715 return;
5716 end if;
5718 if Needs_Custom_Cleanup then
5719 Cln := Cleanup_Actions (N);
5720 else
5721 Cln := No_List;
5722 end if;
5724 declare
5725 Decls : List_Id := Declarations (N);
5726 Fin_Id : Entity_Id;
5727 Mark : Entity_Id := Empty;
5728 New_Decls : List_Id;
5729 Old_Poll : Boolean;
5731 begin
5732 -- If we are generating expanded code for debugging purposes, use the
5733 -- Sloc of the point of insertion for the cleanup code. The Sloc will
5734 -- be updated subsequently to reference the proper line in .dg files.
5735 -- If we are not debugging generated code, use No_Location instead,
5736 -- so that no debug information is generated for the cleanup code.
5737 -- This makes the behavior of the NEXT command in GDB monotonic, and
5738 -- makes the placement of breakpoints more accurate.
5740 if Debug_Generated_Code then
5741 Loc := Sloc (Scop);
5742 else
5743 Loc := No_Location;
5744 end if;
5746 -- Set polling off. The finalization and cleanup code is executed
5747 -- with aborts deferred.
5749 Old_Poll := Polling_Required;
5750 Polling_Required := False;
5752 -- A task activation call has already been built for a task
5753 -- allocation block.
5755 if not Is_Task_Allocation then
5756 Build_Task_Activation_Call (N);
5757 end if;
5759 if Is_Master then
5760 Establish_Task_Master (N);
5761 end if;
5763 New_Decls := New_List;
5765 -- If secondary stack is in use, generate:
5767 -- Mnn : constant Mark_Id := SS_Mark;
5769 if Needs_Sec_Stack_Mark then
5770 Mark := Make_Temporary (Loc, 'M');
5772 Append_To (New_Decls, Build_SS_Mark_Call (Loc, Mark));
5773 Set_Uses_Sec_Stack (Scop, False);
5774 end if;
5776 -- If exception handlers are present, wrap the sequence of statements
5777 -- in a block since it is not possible to have exception handlers and
5778 -- an At_End handler in the same construct.
5780 if Present (Exception_Handlers (HSS)) then
5781 Wrap_HSS_In_Block;
5783 -- Ensure that the First_Real_Statement field is set
5785 elsif No (First_Real_Statement (HSS)) then
5786 Set_First_Real_Statement (HSS, First (Statements (HSS)));
5787 end if;
5789 -- Do not move the Activation_Chain declaration in the context of
5790 -- task allocation blocks. Task allocation blocks use _chain in their
5791 -- cleanup handlers and gigi complains if it is declared in the
5792 -- sequence of statements of the scope that declares the handler.
5794 if Is_Task_Allocation then
5795 declare
5796 Chain : constant Entity_Id := Activation_Chain_Entity (N);
5797 Decl : Node_Id;
5799 begin
5800 Decl := First (Decls);
5801 while Nkind (Decl) /= N_Object_Declaration
5802 or else Defining_Identifier (Decl) /= Chain
5803 loop
5804 Next (Decl);
5806 -- A task allocation block should always include a _chain
5807 -- declaration.
5809 pragma Assert (Present (Decl));
5810 end loop;
5812 Remove (Decl);
5813 Prepend_To (New_Decls, Decl);
5814 end;
5815 end if;
5817 -- Ensure the presence of a declaration list in order to successfully
5818 -- append all original statements to it.
5820 if No (Decls) then
5821 Set_Declarations (N, New_List);
5822 Decls := Declarations (N);
5823 end if;
5825 -- Move the declarations into the sequence of statements in order to
5826 -- have them protected by the At_End handler. It may seem weird to
5827 -- put declarations in the sequence of statement but in fact nothing
5828 -- forbids that at the tree level.
5830 Append_List_To (Decls, Statements (HSS));
5831 Set_Statements (HSS, Decls);
5833 -- Reset the Sloc of the handled statement sequence to properly
5834 -- reflect the new initial "statement" in the sequence.
5836 Set_Sloc (HSS, Sloc (First (Decls)));
5838 -- The declarations of finalizer spec and auxiliary variables replace
5839 -- the old declarations that have been moved inward.
5841 Set_Declarations (N, New_Decls);
5842 Analyze_Declarations (New_Decls);
5844 -- Generate finalization calls for all controlled objects appearing
5845 -- in the statements of N. Add context specific cleanup for various
5846 -- constructs.
5848 Build_Finalizer
5849 (N => N,
5850 Clean_Stmts => Build_Cleanup_Statements (N, Cln),
5851 Mark_Id => Mark,
5852 Top_Decls => New_Decls,
5853 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
5854 or else Is_Master,
5855 Fin_Id => Fin_Id);
5857 if Present (Fin_Id) then
5858 Build_Finalizer_Call (N, Fin_Id);
5859 end if;
5861 -- Restore saved polling mode
5863 Polling_Required := Old_Poll;
5864 end;
5865 end Expand_Cleanup_Actions;
5867 ---------------------------
5868 -- Expand_N_Package_Body --
5869 ---------------------------
5871 -- Add call to Activate_Tasks if body is an activator (actual processing
5872 -- is in chapter 9).
5874 -- Generate subprogram descriptor for elaboration routine
5876 -- Encode entity names in package body
5878 procedure Expand_N_Package_Body (N : Node_Id) is
5879 Spec_Id : constant Entity_Id := Corresponding_Spec (N);
5880 Fin_Id : Entity_Id;
5882 begin
5883 -- This is done only for non-generic packages
5885 if Ekind (Spec_Id) = E_Package then
5886 Push_Scope (Corresponding_Spec (N));
5888 -- Build dispatch tables of library level tagged types
5890 if Tagged_Type_Expansion
5891 and then Is_Library_Level_Entity (Spec_Id)
5892 then
5893 Build_Static_Dispatch_Tables (N);
5894 end if;
5896 Build_Task_Activation_Call (N);
5898 -- When the package is subject to pragma Initial_Condition, the
5899 -- assertion expression must be verified at the end of the body
5900 -- statements.
5902 if Present (Get_Pragma (Spec_Id, Pragma_Initial_Condition)) then
5903 Expand_Pragma_Initial_Condition (N);
5904 end if;
5906 Pop_Scope;
5907 end if;
5909 Set_Elaboration_Flag (N, Corresponding_Spec (N));
5910 Set_In_Package_Body (Spec_Id, False);
5912 -- Set to encode entity names in package body before gigi is called
5914 Qualify_Entity_Names (N);
5916 if Ekind (Spec_Id) /= E_Generic_Package then
5917 Build_Finalizer
5918 (N => N,
5919 Clean_Stmts => No_List,
5920 Mark_Id => Empty,
5921 Top_Decls => No_List,
5922 Defer_Abort => False,
5923 Fin_Id => Fin_Id);
5925 if Present (Fin_Id) then
5926 declare
5927 Body_Ent : Node_Id := Defining_Unit_Name (N);
5929 begin
5930 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
5931 Body_Ent := Defining_Identifier (Body_Ent);
5932 end if;
5934 Set_Finalizer (Body_Ent, Fin_Id);
5935 end;
5936 end if;
5937 end if;
5938 end Expand_N_Package_Body;
5940 ----------------------------------
5941 -- Expand_N_Package_Declaration --
5942 ----------------------------------
5944 -- Add call to Activate_Tasks if there are tasks declared and the package
5945 -- has no body. Note that in Ada 83 this may result in premature activation
5946 -- of some tasks, given that we cannot tell whether a body will eventually
5947 -- appear.
5949 procedure Expand_N_Package_Declaration (N : Node_Id) is
5950 Id : constant Entity_Id := Defining_Entity (N);
5951 Spec : constant Node_Id := Specification (N);
5952 Decls : List_Id;
5953 Fin_Id : Entity_Id;
5955 No_Body : Boolean := False;
5956 -- True in the case of a package declaration that is a compilation
5957 -- unit and for which no associated body will be compiled in this
5958 -- compilation.
5960 begin
5961 -- Case of a package declaration other than a compilation unit
5963 if Nkind (Parent (N)) /= N_Compilation_Unit then
5964 null;
5966 -- Case of a compilation unit that does not require a body
5968 elsif not Body_Required (Parent (N))
5969 and then not Unit_Requires_Body (Id)
5970 then
5971 No_Body := True;
5973 -- Special case of generating calling stubs for a remote call interface
5974 -- package: even though the package declaration requires one, the body
5975 -- won't be processed in this compilation (so any stubs for RACWs
5976 -- declared in the package must be generated here, along with the spec).
5978 elsif Parent (N) = Cunit (Main_Unit)
5979 and then Is_Remote_Call_Interface (Id)
5980 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
5981 then
5982 No_Body := True;
5983 end if;
5985 -- For a nested instance, delay processing until freeze point
5987 if Has_Delayed_Freeze (Id)
5988 and then Nkind (Parent (N)) /= N_Compilation_Unit
5989 then
5990 return;
5991 end if;
5993 -- For a package declaration that implies no associated body, generate
5994 -- task activation call and RACW supporting bodies now (since we won't
5995 -- have a specific separate compilation unit for that).
5997 if No_Body then
5998 Push_Scope (Id);
6000 -- Generate RACW subprogram bodies
6002 if Has_RACW (Id) then
6003 Decls := Private_Declarations (Spec);
6005 if No (Decls) then
6006 Decls := Visible_Declarations (Spec);
6007 end if;
6009 if No (Decls) then
6010 Decls := New_List;
6011 Set_Visible_Declarations (Spec, Decls);
6012 end if;
6014 Append_RACW_Bodies (Decls, Id);
6015 Analyze_List (Decls);
6016 end if;
6018 -- Generate task activation call as last step of elaboration
6020 if Present (Activation_Chain_Entity (N)) then
6021 Build_Task_Activation_Call (N);
6022 end if;
6024 -- When the package is subject to pragma Initial_Condition and lacks
6025 -- a body, the assertion expression must be verified at the end of
6026 -- the visible declarations. Otherwise the check is performed at the
6027 -- end of the body statements (see Expand_N_Package_Body).
6029 if Present (Get_Pragma (Id, Pragma_Initial_Condition)) then
6030 Expand_Pragma_Initial_Condition (N);
6031 end if;
6033 Pop_Scope;
6034 end if;
6036 -- Build dispatch tables of library level tagged types
6038 if Tagged_Type_Expansion
6039 and then (Is_Compilation_Unit (Id)
6040 or else (Is_Generic_Instance (Id)
6041 and then Is_Library_Level_Entity (Id)))
6042 then
6043 Build_Static_Dispatch_Tables (N);
6044 end if;
6046 -- Note: it is not necessary to worry about generating a subprogram
6047 -- descriptor, since the only way to get exception handlers into a
6048 -- package spec is to include instantiations, and that would cause
6049 -- generation of subprogram descriptors to be delayed in any case.
6051 -- Set to encode entity names in package spec before gigi is called
6053 Qualify_Entity_Names (N);
6055 if Ekind (Id) /= E_Generic_Package then
6056 Build_Finalizer
6057 (N => N,
6058 Clean_Stmts => No_List,
6059 Mark_Id => Empty,
6060 Top_Decls => No_List,
6061 Defer_Abort => False,
6062 Fin_Id => Fin_Id);
6064 Set_Finalizer (Id, Fin_Id);
6065 end if;
6066 end Expand_N_Package_Declaration;
6068 -----------------------------
6069 -- Find_Node_To_Be_Wrapped --
6070 -----------------------------
6072 function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
6073 P : Node_Id;
6074 The_Parent : Node_Id;
6076 begin
6077 The_Parent := N;
6078 P := Empty;
6079 loop
6080 case Nkind (The_Parent) is
6082 -- Simple statement can be wrapped
6084 when N_Pragma =>
6085 return The_Parent;
6087 -- Usually assignments are good candidate for wrapping except
6088 -- when they have been generated as part of a controlled aggregate
6089 -- where the wrapping should take place more globally. Note that
6090 -- No_Ctrl_Actions may be set also for non-controlled assignements
6091 -- in order to disable the use of dispatching _assign, so we need
6092 -- to test explicitly for a controlled type here.
6094 when N_Assignment_Statement =>
6095 if No_Ctrl_Actions (The_Parent)
6096 and then Needs_Finalization (Etype (Name (The_Parent)))
6097 then
6098 null;
6099 else
6100 return The_Parent;
6101 end if;
6103 -- An entry call statement is a special case if it occurs in the
6104 -- context of a Timed_Entry_Call. In this case we wrap the entire
6105 -- timed entry call.
6107 when N_Entry_Call_Statement
6108 | N_Procedure_Call_Statement
6110 if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
6111 and then Nkind_In (Parent (Parent (The_Parent)),
6112 N_Timed_Entry_Call,
6113 N_Conditional_Entry_Call)
6114 then
6115 return Parent (Parent (The_Parent));
6116 else
6117 return The_Parent;
6118 end if;
6120 -- Object declarations are also a boundary for the transient scope
6121 -- even if they are not really wrapped. For further details, see
6122 -- Wrap_Transient_Declaration.
6124 when N_Object_Declaration
6125 | N_Object_Renaming_Declaration
6126 | N_Subtype_Declaration
6128 return The_Parent;
6130 -- The expression itself is to be wrapped if its parent is a
6131 -- compound statement or any other statement where the expression
6132 -- is known to be scalar.
6134 when N_Accept_Alternative
6135 | N_Attribute_Definition_Clause
6136 | N_Case_Statement
6137 | N_Code_Statement
6138 | N_Delay_Alternative
6139 | N_Delay_Until_Statement
6140 | N_Delay_Relative_Statement
6141 | N_Discriminant_Association
6142 | N_Elsif_Part
6143 | N_Entry_Body_Formal_Part
6144 | N_Exit_Statement
6145 | N_If_Statement
6146 | N_Iteration_Scheme
6147 | N_Terminate_Alternative
6149 pragma Assert (Present (P));
6150 return P;
6152 when N_Attribute_Reference =>
6153 if Is_Procedure_Attribute_Name
6154 (Attribute_Name (The_Parent))
6155 then
6156 return The_Parent;
6157 end if;
6159 -- A raise statement can be wrapped. This will arise when the
6160 -- expression in a raise_with_expression uses the secondary
6161 -- stack, for example.
6163 when N_Raise_Statement =>
6164 return The_Parent;
6166 -- If the expression is within the iteration scheme of a loop,
6167 -- we must create a declaration for it, followed by an assignment
6168 -- in order to have a usable statement to wrap.
6170 when N_Loop_Parameter_Specification =>
6171 return Parent (The_Parent);
6173 -- The following nodes contains "dummy calls" which don't need to
6174 -- be wrapped.
6176 when N_Component_Declaration
6177 | N_Discriminant_Specification
6178 | N_Parameter_Specification
6180 return Empty;
6182 -- The return statement is not to be wrapped when the function
6183 -- itself needs wrapping at the outer-level
6185 when N_Simple_Return_Statement =>
6186 declare
6187 Applies_To : constant Entity_Id :=
6188 Return_Applies_To
6189 (Return_Statement_Entity (The_Parent));
6190 Return_Type : constant Entity_Id := Etype (Applies_To);
6191 begin
6192 if Requires_Transient_Scope (Return_Type) then
6193 return Empty;
6194 else
6195 return The_Parent;
6196 end if;
6197 end;
6199 -- If we leave a scope without having been able to find a node to
6200 -- wrap, something is going wrong but this can happen in error
6201 -- situation that are not detected yet (such as a dynamic string
6202 -- in a pragma export)
6204 when N_Block_Statement
6205 | N_Package_Body
6206 | N_Package_Declaration
6207 | N_Subprogram_Body
6209 return Empty;
6211 -- Otherwise continue the search
6213 when others =>
6214 null;
6215 end case;
6217 P := The_Parent;
6218 The_Parent := Parent (P);
6219 end loop;
6220 end Find_Node_To_Be_Wrapped;
6222 ----------------------------------
6223 -- Has_New_Controlled_Component --
6224 ----------------------------------
6226 function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
6227 Comp : Entity_Id;
6229 begin
6230 if not Is_Tagged_Type (E) then
6231 return Has_Controlled_Component (E);
6232 elsif not Is_Derived_Type (E) then
6233 return Has_Controlled_Component (E);
6234 end if;
6236 Comp := First_Component (E);
6237 while Present (Comp) loop
6238 if Chars (Comp) = Name_uParent then
6239 null;
6241 elsif Scope (Original_Record_Component (Comp)) = E
6242 and then Needs_Finalization (Etype (Comp))
6243 then
6244 return True;
6245 end if;
6247 Next_Component (Comp);
6248 end loop;
6250 return False;
6251 end Has_New_Controlled_Component;
6253 ---------------------------------
6254 -- Has_Simple_Protected_Object --
6255 ---------------------------------
6257 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
6258 begin
6259 if Has_Task (T) then
6260 return False;
6262 elsif Is_Simple_Protected_Type (T) then
6263 return True;
6265 elsif Is_Array_Type (T) then
6266 return Has_Simple_Protected_Object (Component_Type (T));
6268 elsif Is_Record_Type (T) then
6269 declare
6270 Comp : Entity_Id;
6272 begin
6273 Comp := First_Component (T);
6274 while Present (Comp) loop
6275 if Has_Simple_Protected_Object (Etype (Comp)) then
6276 return True;
6277 end if;
6279 Next_Component (Comp);
6280 end loop;
6282 return False;
6283 end;
6285 else
6286 return False;
6287 end if;
6288 end Has_Simple_Protected_Object;
6290 ------------------------------------
6291 -- Insert_Actions_In_Scope_Around --
6292 ------------------------------------
6294 procedure Insert_Actions_In_Scope_Around
6295 (N : Node_Id;
6296 Clean : Boolean;
6297 Manage_SS : Boolean)
6299 Act_Before : constant List_Id :=
6300 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Before);
6301 Act_After : constant List_Id :=
6302 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (After);
6303 Act_Cleanup : constant List_Id :=
6304 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup);
6305 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
6306 -- Last), but this was incorrect as Process_Transients_In_Scope may
6307 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
6309 procedure Process_Transients_In_Scope
6310 (First_Object : Node_Id;
6311 Last_Object : Node_Id;
6312 Related_Node : Node_Id);
6313 -- Find all transient objects in the list First_Object .. Last_Object
6314 -- and generate finalization actions for them. Related_Node denotes the
6315 -- node which created all transient objects.
6317 ---------------------------------
6318 -- Process_Transients_In_Scope --
6319 ---------------------------------
6321 procedure Process_Transients_In_Scope
6322 (First_Object : Node_Id;
6323 Last_Object : Node_Id;
6324 Related_Node : Node_Id)
6326 Exceptions_OK : constant Boolean :=
6327 not Restriction_Active (No_Exception_Propagation);
6329 Must_Hook : Boolean := False;
6330 -- Flag denoting whether the context requires transient object
6331 -- export to the outer finalizer.
6333 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result;
6334 -- Determine whether an arbitrary node denotes a subprogram call
6336 procedure Detect_Subprogram_Call is
6337 new Traverse_Proc (Is_Subprogram_Call);
6339 procedure Process_Transient_In_Scope
6340 (Obj_Decl : Node_Id;
6341 Blk_Data : Finalization_Exception_Data;
6342 Blk_Stmts : List_Id);
6343 -- Generate finalization actions for a single transient object
6344 -- denoted by object declaration Obj_Decl. Blk_Data is the
6345 -- exception data of the enclosing block. Blk_Stmts denotes the
6346 -- statements of the enclosing block.
6348 ------------------------
6349 -- Is_Subprogram_Call --
6350 ------------------------
6352 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result is
6353 begin
6354 -- A regular procedure or function call
6356 if Nkind (N) in N_Subprogram_Call then
6357 Must_Hook := True;
6358 return Abandon;
6360 -- Special cases
6362 -- Heavy expansion may relocate function calls outside the related
6363 -- node. Inspect the original node to detect the initial placement
6364 -- of the call.
6366 elsif Original_Node (N) /= N then
6367 Detect_Subprogram_Call (Original_Node (N));
6369 if Must_Hook then
6370 return Abandon;
6371 else
6372 return OK;
6373 end if;
6375 -- Generalized indexing always involves a function call
6377 elsif Nkind (N) = N_Indexed_Component
6378 and then Present (Generalized_Indexing (N))
6379 then
6380 Must_Hook := True;
6381 return Abandon;
6383 -- Keep searching
6385 else
6386 return OK;
6387 end if;
6388 end Is_Subprogram_Call;
6390 --------------------------------
6391 -- Process_Transient_In_Scope --
6392 --------------------------------
6394 procedure Process_Transient_In_Scope
6395 (Obj_Decl : Node_Id;
6396 Blk_Data : Finalization_Exception_Data;
6397 Blk_Stmts : List_Id)
6399 Loc : constant Source_Ptr := Sloc (Obj_Decl);
6400 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
6401 Fin_Call : Node_Id;
6402 Fin_Stmts : List_Id;
6403 Hook_Assign : Node_Id;
6404 Hook_Clear : Node_Id;
6405 Hook_Decl : Node_Id;
6406 Hook_Insert : Node_Id;
6407 Ptr_Decl : Node_Id;
6409 begin
6410 -- Mark the transient object as successfully processed to avoid
6411 -- double finalization.
6413 Set_Is_Finalized_Transient (Obj_Id);
6415 -- Construct all the pieces necessary to hook and finalize the
6416 -- transient object.
6418 Build_Transient_Object_Statements
6419 (Obj_Decl => Obj_Decl,
6420 Fin_Call => Fin_Call,
6421 Hook_Assign => Hook_Assign,
6422 Hook_Clear => Hook_Clear,
6423 Hook_Decl => Hook_Decl,
6424 Ptr_Decl => Ptr_Decl);
6426 -- The context contains at least one subprogram call which may
6427 -- raise an exception. This scenario employs "hooking" to pass
6428 -- transient objects to the enclosing finalizer in case of an
6429 -- exception.
6431 if Must_Hook then
6433 -- Add the access type which provides a reference to the
6434 -- transient object. Generate:
6436 -- type Ptr_Typ is access all Desig_Typ;
6438 Insert_Action (Obj_Decl, Ptr_Decl);
6440 -- Add the temporary which acts as a hook to the transient
6441 -- object. Generate:
6443 -- Hook : Ptr_Typ := null;
6445 Insert_Action (Obj_Decl, Hook_Decl);
6447 -- When the transient object is initialized by an aggregate,
6448 -- the hook must capture the object after the last aggregate
6449 -- assignment takes place. Only then is the object considered
6450 -- fully initialized. Generate:
6452 -- Hook := Ptr_Typ (Obj_Id);
6453 -- <or>
6454 -- Hook := Obj_Id'Unrestricted_Access;
6456 if Ekind_In (Obj_Id, E_Constant, E_Variable)
6457 and then Present (Last_Aggregate_Assignment (Obj_Id))
6458 then
6459 Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
6461 -- Otherwise the hook seizes the related object immediately
6463 else
6464 Hook_Insert := Obj_Decl;
6465 end if;
6467 Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
6468 end if;
6470 -- When exception propagation is enabled wrap the hook clear
6471 -- statement and the finalization call into a block to catch
6472 -- potential exceptions raised during finalization. Generate:
6474 -- begin
6475 -- [Hook := null;]
6476 -- [Deep_]Finalize (Obj_Ref);
6478 -- exception
6479 -- when others =>
6480 -- if not Raised then
6481 -- Raised := True;
6482 -- Save_Occurrence
6483 -- (Enn, Get_Current_Excep.all.all);
6484 -- end if;
6485 -- end;
6487 if Exceptions_OK then
6488 Fin_Stmts := New_List;
6490 if Must_Hook then
6491 Append_To (Fin_Stmts, Hook_Clear);
6492 end if;
6494 Append_To (Fin_Stmts, Fin_Call);
6496 Prepend_To (Blk_Stmts,
6497 Make_Block_Statement (Loc,
6498 Handled_Statement_Sequence =>
6499 Make_Handled_Sequence_Of_Statements (Loc,
6500 Statements => Fin_Stmts,
6501 Exception_Handlers => New_List (
6502 Build_Exception_Handler (Blk_Data)))));
6504 -- Otherwise generate:
6506 -- [Hook := null;]
6507 -- [Deep_]Finalize (Obj_Ref);
6509 -- Note that the statements are inserted in reverse order to
6510 -- achieve the desired final order outlined above.
6512 else
6513 Prepend_To (Blk_Stmts, Fin_Call);
6515 if Must_Hook then
6516 Prepend_To (Blk_Stmts, Hook_Clear);
6517 end if;
6518 end if;
6519 end Process_Transient_In_Scope;
6521 -- Local variables
6523 Built : Boolean := False;
6524 Blk_Data : Finalization_Exception_Data;
6525 Blk_Decl : Node_Id := Empty;
6526 Blk_Decls : List_Id := No_List;
6527 Blk_Ins : Node_Id;
6528 Blk_Stmts : List_Id;
6529 Loc : Source_Ptr;
6530 Obj_Decl : Node_Id;
6532 -- Start of processing for Process_Transients_In_Scope
6534 begin
6535 -- The expansion performed by this routine is as follows:
6537 -- type Ptr_Typ_1 is access all Ctrl_Trans_Obj_1_Typ;
6538 -- Hook_1 : Ptr_Typ_1 := null;
6539 -- Ctrl_Trans_Obj_1 : ...;
6540 -- Hook_1 := Ctrl_Trans_Obj_1'Unrestricted_Access;
6541 -- . . .
6542 -- type Ptr_Typ_N is access all Ctrl_Trans_Obj_N_Typ;
6543 -- Hook_N : Ptr_Typ_N := null;
6544 -- Ctrl_Trans_Obj_N : ...;
6545 -- Hook_N := Ctrl_Trans_Obj_N'Unrestricted_Access;
6547 -- declare
6548 -- Abrt : constant Boolean := ...;
6549 -- Ex : Exception_Occurrence;
6550 -- Raised : Boolean := False;
6552 -- begin
6553 -- Abort_Defer;
6555 -- begin
6556 -- Hook_N := null;
6557 -- [Deep_]Finalize (Ctrl_Trans_Obj_N);
6559 -- exception
6560 -- when others =>
6561 -- if not Raised then
6562 -- Raised := True;
6563 -- Save_Occurrence (Ex, Get_Current_Excep.all.all);
6564 -- end;
6565 -- . . .
6566 -- begin
6567 -- Hook_1 := null;
6568 -- [Deep_]Finalize (Ctrl_Trans_Obj_1);
6570 -- exception
6571 -- when others =>
6572 -- if not Raised then
6573 -- Raised := True;
6574 -- Save_Occurrence (Ex, Get_Current_Excep.all.all);
6575 -- end;
6577 -- Abort_Undefer;
6579 -- if Raised and not Abrt then
6580 -- Raise_From_Controlled_Operation (Ex);
6581 -- end if;
6582 -- end;
6584 -- Recognize a scenario where the transient context is an object
6585 -- declaration initialized by a build-in-place function call:
6587 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
6589 -- The rough expansion of the above is:
6591 -- Temp : ... := Ctrl_Func_Call;
6592 -- Obj : ...;
6593 -- Res : ... := BIP_Func_Call (..., Obj, ...);
6595 -- The finalization of any transient object must happen after the
6596 -- build-in-place function call is executed.
6598 if Nkind (N) = N_Object_Declaration
6599 and then Present (BIP_Initialization_Call (Defining_Identifier (N)))
6600 then
6601 Must_Hook := True;
6602 Blk_Ins := BIP_Initialization_Call (Defining_Identifier (N));
6604 -- Search the context for at least one subprogram call. If found, the
6605 -- machinery exports all transient objects to the enclosing finalizer
6606 -- due to the possibility of abnormal call termination.
6608 else
6609 Detect_Subprogram_Call (N);
6610 Blk_Ins := Last_Object;
6611 end if;
6613 if Clean then
6614 Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
6615 end if;
6617 -- Examine all objects in the list First_Object .. Last_Object
6619 Obj_Decl := First_Object;
6620 while Present (Obj_Decl) loop
6621 if Nkind (Obj_Decl) = N_Object_Declaration
6622 and then Analyzed (Obj_Decl)
6623 and then Is_Finalizable_Transient (Obj_Decl, N)
6625 -- Do not process the node to be wrapped since it will be
6626 -- handled by the enclosing finalizer.
6628 and then Obj_Decl /= Related_Node
6629 then
6630 Loc := Sloc (Obj_Decl);
6632 -- Before generating the clean up code for the first transient
6633 -- object, create a wrapper block which houses all hook clear
6634 -- statements and finalization calls. This wrapper is needed by
6635 -- the back-end.
6637 if not Built then
6638 Built := True;
6639 Blk_Stmts := New_List;
6641 -- Generate:
6642 -- Abrt : constant Boolean := ...;
6643 -- Ex : Exception_Occurrence;
6644 -- Raised : Boolean := False;
6646 if Exceptions_OK then
6647 Blk_Decls := New_List;
6648 Build_Object_Declarations (Blk_Data, Blk_Decls, Loc);
6649 end if;
6651 Blk_Decl :=
6652 Make_Block_Statement (Loc,
6653 Declarations => Blk_Decls,
6654 Handled_Statement_Sequence =>
6655 Make_Handled_Sequence_Of_Statements (Loc,
6656 Statements => Blk_Stmts));
6657 end if;
6659 -- Construct all necessary circuitry to hook and finalize a
6660 -- single transient object.
6662 Process_Transient_In_Scope
6663 (Obj_Decl => Obj_Decl,
6664 Blk_Data => Blk_Data,
6665 Blk_Stmts => Blk_Stmts);
6666 end if;
6668 -- Terminate the scan after the last object has been processed to
6669 -- avoid touching unrelated code.
6671 if Obj_Decl = Last_Object then
6672 exit;
6673 end if;
6675 Next (Obj_Decl);
6676 end loop;
6678 -- Complete the decoration of the enclosing finalization block and
6679 -- insert it into the tree.
6681 if Present (Blk_Decl) then
6683 -- Note that this Abort_Undefer does not require a extra block or
6684 -- an AT_END handler because each finalization exception is caught
6685 -- in its own corresponding finalization block. As a result, the
6686 -- call to Abort_Defer always takes place.
6688 if Abort_Allowed then
6689 Prepend_To (Blk_Stmts,
6690 Build_Runtime_Call (Loc, RE_Abort_Defer));
6692 Append_To (Blk_Stmts,
6693 Build_Runtime_Call (Loc, RE_Abort_Undefer));
6694 end if;
6696 -- Generate:
6697 -- if Raised and then not Abrt then
6698 -- Raise_From_Controlled_Operation (Ex);
6699 -- end if;
6701 if Exceptions_OK then
6702 Append_To (Blk_Stmts, Build_Raise_Statement (Blk_Data));
6703 end if;
6705 Insert_After_And_Analyze (Blk_Ins, Blk_Decl);
6706 end if;
6707 end Process_Transients_In_Scope;
6709 -- Local variables
6711 Loc : constant Source_Ptr := Sloc (N);
6712 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
6713 First_Obj : Node_Id;
6714 Last_Obj : Node_Id;
6715 Mark_Id : Entity_Id;
6716 Target : Node_Id;
6718 -- Start of processing for Insert_Actions_In_Scope_Around
6720 begin
6721 if No (Act_Before) and then No (Act_After) and then No (Act_Cleanup) then
6722 return;
6723 end if;
6725 -- If the node to be wrapped is the trigger of an asynchronous select,
6726 -- it is not part of a statement list. The actions must be inserted
6727 -- before the select itself, which is part of some list of statements.
6728 -- Note that the triggering alternative includes the triggering
6729 -- statement and an optional statement list. If the node to be
6730 -- wrapped is part of that list, the normal insertion applies.
6732 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
6733 and then not Is_List_Member (Node_To_Wrap)
6734 then
6735 Target := Parent (Parent (Node_To_Wrap));
6736 else
6737 Target := N;
6738 end if;
6740 First_Obj := Target;
6741 Last_Obj := Target;
6743 -- Add all actions associated with a transient scope into the main tree.
6744 -- There are several scenarios here:
6746 -- +--- Before ----+ +----- After ---+
6747 -- 1) First_Obj ....... Target ........ Last_Obj
6749 -- 2) First_Obj ....... Target
6751 -- 3) Target ........ Last_Obj
6753 -- Flag declarations are inserted before the first object
6755 if Present (Act_Before) then
6756 First_Obj := First (Act_Before);
6757 Insert_List_Before (Target, Act_Before);
6758 end if;
6760 -- Finalization calls are inserted after the last object
6762 if Present (Act_After) then
6763 Last_Obj := Last (Act_After);
6764 Insert_List_After (Target, Act_After);
6765 end if;
6767 -- Mark and release the secondary stack when the context warrants it
6769 if Manage_SS then
6770 Mark_Id := Make_Temporary (Loc, 'M');
6772 -- Generate:
6773 -- Mnn : constant Mark_Id := SS_Mark;
6775 Insert_Before_And_Analyze
6776 (First_Obj, Build_SS_Mark_Call (Loc, Mark_Id));
6778 -- Generate:
6779 -- SS_Release (Mnn);
6781 Insert_After_And_Analyze
6782 (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
6783 end if;
6785 -- Check for transient objects associated with Target and generate the
6786 -- appropriate finalization actions for them.
6788 Process_Transients_In_Scope
6789 (First_Object => First_Obj,
6790 Last_Object => Last_Obj,
6791 Related_Node => Target);
6793 -- Reset the action lists
6795 Scope_Stack.Table
6796 (Scope_Stack.Last).Actions_To_Be_Wrapped (Before) := No_List;
6797 Scope_Stack.Table
6798 (Scope_Stack.Last).Actions_To_Be_Wrapped (After) := No_List;
6800 if Clean then
6801 Scope_Stack.Table
6802 (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup) := No_List;
6803 end if;
6804 end Insert_Actions_In_Scope_Around;
6806 ------------------------------
6807 -- Is_Simple_Protected_Type --
6808 ------------------------------
6810 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
6811 begin
6812 return
6813 Is_Protected_Type (T)
6814 and then not Uses_Lock_Free (T)
6815 and then not Has_Entries (T)
6816 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
6817 end Is_Simple_Protected_Type;
6819 -----------------------
6820 -- Make_Adjust_Call --
6821 -----------------------
6823 function Make_Adjust_Call
6824 (Obj_Ref : Node_Id;
6825 Typ : Entity_Id;
6826 Skip_Self : Boolean := False) return Node_Id
6828 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6829 Adj_Id : Entity_Id := Empty;
6830 Ref : Node_Id;
6831 Utyp : Entity_Id;
6833 begin
6834 Ref := Obj_Ref;
6836 -- Recover the proper type which contains Deep_Adjust
6838 if Is_Class_Wide_Type (Typ) then
6839 Utyp := Root_Type (Typ);
6840 else
6841 Utyp := Typ;
6842 end if;
6844 Utyp := Underlying_Type (Base_Type (Utyp));
6845 Set_Assignment_OK (Ref);
6847 -- Deal with untagged derivation of private views
6849 if Present (Utyp) and then Is_Untagged_Derivation (Typ) then
6850 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6851 Ref := Unchecked_Convert_To (Utyp, Ref);
6852 Set_Assignment_OK (Ref);
6853 end if;
6855 -- When dealing with the completion of a private type, use the base
6856 -- type instead.
6858 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
6859 pragma Assert (Is_Private_Type (Typ));
6861 Utyp := Base_Type (Utyp);
6862 Ref := Unchecked_Convert_To (Utyp, Ref);
6863 end if;
6865 -- The underlying type may not be present due to a missing full view. In
6866 -- this case freezing did not take place and there is no [Deep_]Adjust
6867 -- primitive to call.
6869 if No (Utyp) then
6870 return Empty;
6872 elsif Skip_Self then
6873 if Has_Controlled_Component (Utyp) then
6874 if Is_Tagged_Type (Utyp) then
6875 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
6876 else
6877 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
6878 end if;
6879 end if;
6881 -- Class-wide types, interfaces and types with controlled components
6883 elsif Is_Class_Wide_Type (Typ)
6884 or else Is_Interface (Typ)
6885 or else Has_Controlled_Component (Utyp)
6886 then
6887 if Is_Tagged_Type (Utyp) then
6888 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
6889 else
6890 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
6891 end if;
6893 -- Derivations from [Limited_]Controlled
6895 elsif Is_Controlled (Utyp) then
6896 if Has_Controlled_Component (Utyp) then
6897 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
6898 else
6899 Adj_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Adjust_Case));
6900 end if;
6902 -- Tagged types
6904 elsif Is_Tagged_Type (Utyp) then
6905 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
6907 else
6908 raise Program_Error;
6909 end if;
6911 if Present (Adj_Id) then
6913 -- If the object is unanalyzed, set its expected type for use in
6914 -- Convert_View in case an additional conversion is needed.
6916 if No (Etype (Ref))
6917 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
6918 then
6919 Set_Etype (Ref, Typ);
6920 end if;
6922 -- The object reference may need another conversion depending on the
6923 -- type of the formal and that of the actual.
6925 if not Is_Class_Wide_Type (Typ) then
6926 Ref := Convert_View (Adj_Id, Ref);
6927 end if;
6929 return
6930 Make_Call (Loc,
6931 Proc_Id => Adj_Id,
6932 Param => Ref,
6933 Skip_Self => Skip_Self);
6934 else
6935 return Empty;
6936 end if;
6937 end Make_Adjust_Call;
6939 ----------------------
6940 -- Make_Detach_Call --
6941 ----------------------
6943 function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
6944 Loc : constant Source_Ptr := Sloc (Obj_Ref);
6946 begin
6947 return
6948 Make_Procedure_Call_Statement (Loc,
6949 Name =>
6950 New_Occurrence_Of (RTE (RE_Detach), Loc),
6951 Parameter_Associations => New_List (
6952 Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
6953 end Make_Detach_Call;
6955 ---------------
6956 -- Make_Call --
6957 ---------------
6959 function Make_Call
6960 (Loc : Source_Ptr;
6961 Proc_Id : Entity_Id;
6962 Param : Node_Id;
6963 Skip_Self : Boolean := False) return Node_Id
6965 Params : constant List_Id := New_List (Param);
6967 begin
6968 -- Do not apply the controlled action to the object itself by signaling
6969 -- the related routine to avoid self.
6971 if Skip_Self then
6972 Append_To (Params, New_Occurrence_Of (Standard_False, Loc));
6973 end if;
6975 return
6976 Make_Procedure_Call_Statement (Loc,
6977 Name => New_Occurrence_Of (Proc_Id, Loc),
6978 Parameter_Associations => Params);
6979 end Make_Call;
6981 --------------------------
6982 -- Make_Deep_Array_Body --
6983 --------------------------
6985 function Make_Deep_Array_Body
6986 (Prim : Final_Primitives;
6987 Typ : Entity_Id) return List_Id
6989 function Build_Adjust_Or_Finalize_Statements
6990 (Typ : Entity_Id) return List_Id;
6991 -- Create the statements necessary to adjust or finalize an array of
6992 -- controlled elements. Generate:
6994 -- declare
6995 -- Abort : constant Boolean := Triggered_By_Abort;
6996 -- <or>
6997 -- Abort : constant Boolean := False; -- no abort
6999 -- E : Exception_Occurrence;
7000 -- Raised : Boolean := False;
7002 -- begin
7003 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
7004 -- ^-- in the finalization case
7005 -- ...
7006 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
7007 -- begin
7008 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
7010 -- exception
7011 -- when others =>
7012 -- if not Raised then
7013 -- Raised := True;
7014 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7015 -- end if;
7016 -- end;
7017 -- end loop;
7018 -- ...
7019 -- end loop;
7021 -- if Raised and then not Abort then
7022 -- Raise_From_Controlled_Operation (E);
7023 -- end if;
7024 -- end;
7026 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
7027 -- Create the statements necessary to initialize an array of controlled
7028 -- elements. Include a mechanism to carry out partial finalization if an
7029 -- exception occurs. Generate:
7031 -- declare
7032 -- Counter : Integer := 0;
7034 -- begin
7035 -- for J1 in V'Range (1) loop
7036 -- ...
7037 -- for JN in V'Range (N) loop
7038 -- begin
7039 -- [Deep_]Initialize (V (J1, ..., JN));
7041 -- Counter := Counter + 1;
7043 -- exception
7044 -- when others =>
7045 -- declare
7046 -- Abort : constant Boolean := Triggered_By_Abort;
7047 -- <or>
7048 -- Abort : constant Boolean := False; -- no abort
7049 -- E : Exception_Occurrence;
7050 -- Raised : Boolean := False;
7052 -- begin
7053 -- Counter :=
7054 -- V'Length (1) *
7055 -- V'Length (2) *
7056 -- ...
7057 -- V'Length (N) - Counter;
7059 -- for F1 in reverse V'Range (1) loop
7060 -- ...
7061 -- for FN in reverse V'Range (N) loop
7062 -- if Counter > 0 then
7063 -- Counter := Counter - 1;
7064 -- else
7065 -- begin
7066 -- [Deep_]Finalize (V (F1, ..., FN));
7068 -- exception
7069 -- when others =>
7070 -- if not Raised then
7071 -- Raised := True;
7072 -- Save_Occurrence (E,
7073 -- Get_Current_Excep.all.all);
7074 -- end if;
7075 -- end;
7076 -- end if;
7077 -- end loop;
7078 -- ...
7079 -- end loop;
7080 -- end;
7082 -- if Raised and then not Abort then
7083 -- Raise_From_Controlled_Operation (E);
7084 -- end if;
7086 -- raise;
7087 -- end;
7088 -- end loop;
7089 -- end loop;
7090 -- end;
7092 function New_References_To
7093 (L : List_Id;
7094 Loc : Source_Ptr) return List_Id;
7095 -- Given a list of defining identifiers, return a list of references to
7096 -- the original identifiers, in the same order as they appear.
7098 -----------------------------------------
7099 -- Build_Adjust_Or_Finalize_Statements --
7100 -----------------------------------------
7102 function Build_Adjust_Or_Finalize_Statements
7103 (Typ : Entity_Id) return List_Id
7105 Comp_Typ : constant Entity_Id := Component_Type (Typ);
7106 Exceptions_OK : constant Boolean :=
7107 not Restriction_Active (No_Exception_Propagation);
7108 Index_List : constant List_Id := New_List;
7109 Loc : constant Source_Ptr := Sloc (Typ);
7110 Num_Dims : constant Int := Number_Dimensions (Typ);
7112 procedure Build_Indexes;
7113 -- Generate the indexes used in the dimension loops
7115 -------------------
7116 -- Build_Indexes --
7117 -------------------
7119 procedure Build_Indexes is
7120 begin
7121 -- Generate the following identifiers:
7122 -- Jnn - for initialization
7124 for Dim in 1 .. Num_Dims loop
7125 Append_To (Index_List,
7126 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
7127 end loop;
7128 end Build_Indexes;
7130 -- Local variables
7132 Final_Decls : List_Id := No_List;
7133 Final_Data : Finalization_Exception_Data;
7134 Block : Node_Id;
7135 Call : Node_Id;
7136 Comp_Ref : Node_Id;
7137 Core_Loop : Node_Id;
7138 Dim : Int;
7139 J : Entity_Id;
7140 Loop_Id : Entity_Id;
7141 Stmts : List_Id;
7143 -- Start of processing for Build_Adjust_Or_Finalize_Statements
7145 begin
7146 Final_Decls := New_List;
7148 Build_Indexes;
7149 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
7151 Comp_Ref :=
7152 Make_Indexed_Component (Loc,
7153 Prefix => Make_Identifier (Loc, Name_V),
7154 Expressions => New_References_To (Index_List, Loc));
7155 Set_Etype (Comp_Ref, Comp_Typ);
7157 -- Generate:
7158 -- [Deep_]Adjust (V (J1, ..., JN))
7160 if Prim = Adjust_Case then
7161 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
7163 -- Generate:
7164 -- [Deep_]Finalize (V (J1, ..., JN))
7166 else pragma Assert (Prim = Finalize_Case);
7167 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
7168 end if;
7170 if Present (Call) then
7172 -- Generate the block which houses the adjust or finalize call:
7174 -- begin
7175 -- <adjust or finalize call>
7177 -- exception
7178 -- when others =>
7179 -- if not Raised then
7180 -- Raised := True;
7181 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7182 -- end if;
7183 -- end;
7185 if Exceptions_OK then
7186 Core_Loop :=
7187 Make_Block_Statement (Loc,
7188 Handled_Statement_Sequence =>
7189 Make_Handled_Sequence_Of_Statements (Loc,
7190 Statements => New_List (Call),
7191 Exception_Handlers => New_List (
7192 Build_Exception_Handler (Final_Data))));
7193 else
7194 Core_Loop := Call;
7195 end if;
7197 -- Generate the dimension loops starting from the innermost one
7199 -- for Jnn in [reverse] V'Range (Dim) loop
7200 -- <core loop>
7201 -- end loop;
7203 J := Last (Index_List);
7204 Dim := Num_Dims;
7205 while Present (J) and then Dim > 0 loop
7206 Loop_Id := J;
7207 Prev (J);
7208 Remove (Loop_Id);
7210 Core_Loop :=
7211 Make_Loop_Statement (Loc,
7212 Iteration_Scheme =>
7213 Make_Iteration_Scheme (Loc,
7214 Loop_Parameter_Specification =>
7215 Make_Loop_Parameter_Specification (Loc,
7216 Defining_Identifier => Loop_Id,
7217 Discrete_Subtype_Definition =>
7218 Make_Attribute_Reference (Loc,
7219 Prefix => Make_Identifier (Loc, Name_V),
7220 Attribute_Name => Name_Range,
7221 Expressions => New_List (
7222 Make_Integer_Literal (Loc, Dim))),
7224 Reverse_Present =>
7225 Prim = Finalize_Case)),
7227 Statements => New_List (Core_Loop),
7228 End_Label => Empty);
7230 Dim := Dim - 1;
7231 end loop;
7233 -- Generate the block which contains the core loop, declarations
7234 -- of the abort flag, the exception occurrence, the raised flag
7235 -- and the conditional raise:
7237 -- declare
7238 -- Abort : constant Boolean := Triggered_By_Abort;
7239 -- <or>
7240 -- Abort : constant Boolean := False; -- no abort
7242 -- E : Exception_Occurrence;
7243 -- Raised : Boolean := False;
7245 -- begin
7246 -- <core loop>
7248 -- if Raised and then not Abort then
7249 -- Raise_From_Controlled_Operation (E);
7250 -- end if;
7251 -- end;
7253 Stmts := New_List (Core_Loop);
7255 if Exceptions_OK then
7256 Append_To (Stmts, Build_Raise_Statement (Final_Data));
7257 end if;
7259 Block :=
7260 Make_Block_Statement (Loc,
7261 Declarations => Final_Decls,
7262 Handled_Statement_Sequence =>
7263 Make_Handled_Sequence_Of_Statements (Loc,
7264 Statements => Stmts));
7266 -- Otherwise previous errors or a missing full view may prevent the
7267 -- proper freezing of the component type. If this is the case, there
7268 -- is no [Deep_]Adjust or [Deep_]Finalize primitive to call.
7270 else
7271 Block := Make_Null_Statement (Loc);
7272 end if;
7274 return New_List (Block);
7275 end Build_Adjust_Or_Finalize_Statements;
7277 ---------------------------------
7278 -- Build_Initialize_Statements --
7279 ---------------------------------
7281 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
7282 Comp_Typ : constant Entity_Id := Component_Type (Typ);
7283 Exceptions_OK : constant Boolean :=
7284 not Restriction_Active (No_Exception_Propagation);
7285 Final_List : constant List_Id := New_List;
7286 Index_List : constant List_Id := New_List;
7287 Loc : constant Source_Ptr := Sloc (Typ);
7288 Num_Dims : constant Int := Number_Dimensions (Typ);
7290 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id;
7291 -- Generate the following assignment:
7292 -- Counter := V'Length (1) *
7293 -- ...
7294 -- V'Length (N) - Counter;
7296 -- Counter_Id denotes the entity of the counter.
7298 function Build_Finalization_Call return Node_Id;
7299 -- Generate a deep finalization call for an array element
7301 procedure Build_Indexes;
7302 -- Generate the initialization and finalization indexes used in the
7303 -- dimension loops.
7305 function Build_Initialization_Call return Node_Id;
7306 -- Generate a deep initialization call for an array element
7308 ----------------------
7309 -- Build_Assignment --
7310 ----------------------
7312 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id is
7313 Dim : Int;
7314 Expr : Node_Id;
7316 begin
7317 -- Start from the first dimension and generate:
7318 -- V'Length (1)
7320 Dim := 1;
7321 Expr :=
7322 Make_Attribute_Reference (Loc,
7323 Prefix => Make_Identifier (Loc, Name_V),
7324 Attribute_Name => Name_Length,
7325 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
7327 -- Process the rest of the dimensions, generate:
7328 -- Expr * V'Length (N)
7330 Dim := Dim + 1;
7331 while Dim <= Num_Dims loop
7332 Expr :=
7333 Make_Op_Multiply (Loc,
7334 Left_Opnd => Expr,
7335 Right_Opnd =>
7336 Make_Attribute_Reference (Loc,
7337 Prefix => Make_Identifier (Loc, Name_V),
7338 Attribute_Name => Name_Length,
7339 Expressions => New_List (
7340 Make_Integer_Literal (Loc, Dim))));
7342 Dim := Dim + 1;
7343 end loop;
7345 -- Generate:
7346 -- Counter := Expr - Counter;
7348 return
7349 Make_Assignment_Statement (Loc,
7350 Name => New_Occurrence_Of (Counter_Id, Loc),
7351 Expression =>
7352 Make_Op_Subtract (Loc,
7353 Left_Opnd => Expr,
7354 Right_Opnd => New_Occurrence_Of (Counter_Id, Loc)));
7355 end Build_Assignment;
7357 -----------------------------
7358 -- Build_Finalization_Call --
7359 -----------------------------
7361 function Build_Finalization_Call return Node_Id is
7362 Comp_Ref : constant Node_Id :=
7363 Make_Indexed_Component (Loc,
7364 Prefix => Make_Identifier (Loc, Name_V),
7365 Expressions => New_References_To (Final_List, Loc));
7367 begin
7368 Set_Etype (Comp_Ref, Comp_Typ);
7370 -- Generate:
7371 -- [Deep_]Finalize (V);
7373 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
7374 end Build_Finalization_Call;
7376 -------------------
7377 -- Build_Indexes --
7378 -------------------
7380 procedure Build_Indexes is
7381 begin
7382 -- Generate the following identifiers:
7383 -- Jnn - for initialization
7384 -- Fnn - for finalization
7386 for Dim in 1 .. Num_Dims loop
7387 Append_To (Index_List,
7388 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
7390 Append_To (Final_List,
7391 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
7392 end loop;
7393 end Build_Indexes;
7395 -------------------------------
7396 -- Build_Initialization_Call --
7397 -------------------------------
7399 function Build_Initialization_Call return Node_Id is
7400 Comp_Ref : constant Node_Id :=
7401 Make_Indexed_Component (Loc,
7402 Prefix => Make_Identifier (Loc, Name_V),
7403 Expressions => New_References_To (Index_List, Loc));
7405 begin
7406 Set_Etype (Comp_Ref, Comp_Typ);
7408 -- Generate:
7409 -- [Deep_]Initialize (V (J1, ..., JN));
7411 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
7412 end Build_Initialization_Call;
7414 -- Local variables
7416 Counter_Id : Entity_Id;
7417 Dim : Int;
7418 F : Node_Id;
7419 Fin_Stmt : Node_Id;
7420 Final_Block : Node_Id;
7421 Final_Data : Finalization_Exception_Data;
7422 Final_Decls : List_Id := No_List;
7423 Final_Loop : Node_Id;
7424 Init_Block : Node_Id;
7425 Init_Call : Node_Id;
7426 Init_Loop : Node_Id;
7427 J : Node_Id;
7428 Loop_Id : Node_Id;
7429 Stmts : List_Id;
7431 -- Start of processing for Build_Initialize_Statements
7433 begin
7434 Counter_Id := Make_Temporary (Loc, 'C');
7435 Final_Decls := New_List;
7437 Build_Indexes;
7438 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
7440 -- Generate the block which houses the finalization call, the index
7441 -- guard and the handler which triggers Program_Error later on.
7443 -- if Counter > 0 then
7444 -- Counter := Counter - 1;
7445 -- else
7446 -- begin
7447 -- [Deep_]Finalize (V (F1, ..., FN));
7448 -- exception
7449 -- when others =>
7450 -- if not Raised then
7451 -- Raised := True;
7452 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7453 -- end if;
7454 -- end;
7455 -- end if;
7457 Fin_Stmt := Build_Finalization_Call;
7459 if Present (Fin_Stmt) then
7460 if Exceptions_OK then
7461 Fin_Stmt :=
7462 Make_Block_Statement (Loc,
7463 Handled_Statement_Sequence =>
7464 Make_Handled_Sequence_Of_Statements (Loc,
7465 Statements => New_List (Fin_Stmt),
7466 Exception_Handlers => New_List (
7467 Build_Exception_Handler (Final_Data))));
7468 end if;
7470 -- This is the core of the loop, the dimension iterators are added
7471 -- one by one in reverse.
7473 Final_Loop :=
7474 Make_If_Statement (Loc,
7475 Condition =>
7476 Make_Op_Gt (Loc,
7477 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
7478 Right_Opnd => Make_Integer_Literal (Loc, 0)),
7480 Then_Statements => New_List (
7481 Make_Assignment_Statement (Loc,
7482 Name => New_Occurrence_Of (Counter_Id, Loc),
7483 Expression =>
7484 Make_Op_Subtract (Loc,
7485 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
7486 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
7488 Else_Statements => New_List (Fin_Stmt));
7490 -- Generate all finalization loops starting from the innermost
7491 -- dimension.
7493 -- for Fnn in reverse V'Range (Dim) loop
7494 -- <final loop>
7495 -- end loop;
7497 F := Last (Final_List);
7498 Dim := Num_Dims;
7499 while Present (F) and then Dim > 0 loop
7500 Loop_Id := F;
7501 Prev (F);
7502 Remove (Loop_Id);
7504 Final_Loop :=
7505 Make_Loop_Statement (Loc,
7506 Iteration_Scheme =>
7507 Make_Iteration_Scheme (Loc,
7508 Loop_Parameter_Specification =>
7509 Make_Loop_Parameter_Specification (Loc,
7510 Defining_Identifier => Loop_Id,
7511 Discrete_Subtype_Definition =>
7512 Make_Attribute_Reference (Loc,
7513 Prefix => Make_Identifier (Loc, Name_V),
7514 Attribute_Name => Name_Range,
7515 Expressions => New_List (
7516 Make_Integer_Literal (Loc, Dim))),
7518 Reverse_Present => True)),
7520 Statements => New_List (Final_Loop),
7521 End_Label => Empty);
7523 Dim := Dim - 1;
7524 end loop;
7526 -- Generate the block which contains the finalization loops, the
7527 -- declarations of the abort flag, the exception occurrence, the
7528 -- raised flag and the conditional raise.
7530 -- declare
7531 -- Abort : constant Boolean := Triggered_By_Abort;
7532 -- <or>
7533 -- Abort : constant Boolean := False; -- no abort
7535 -- E : Exception_Occurrence;
7536 -- Raised : Boolean := False;
7538 -- begin
7539 -- Counter :=
7540 -- V'Length (1) *
7541 -- ...
7542 -- V'Length (N) - Counter;
7544 -- <final loop>
7546 -- if Raised and then not Abort then
7547 -- Raise_From_Controlled_Operation (E);
7548 -- end if;
7550 -- raise;
7551 -- end;
7553 Stmts := New_List (Build_Assignment (Counter_Id), Final_Loop);
7555 if Exceptions_OK then
7556 Append_To (Stmts, Build_Raise_Statement (Final_Data));
7557 Append_To (Stmts, Make_Raise_Statement (Loc));
7558 end if;
7560 Final_Block :=
7561 Make_Block_Statement (Loc,
7562 Declarations => Final_Decls,
7563 Handled_Statement_Sequence =>
7564 Make_Handled_Sequence_Of_Statements (Loc,
7565 Statements => Stmts));
7567 -- Otherwise previous errors or a missing full view may prevent the
7568 -- proper freezing of the component type. If this is the case, there
7569 -- is no [Deep_]Finalize primitive to call.
7571 else
7572 Final_Block := Make_Null_Statement (Loc);
7573 end if;
7575 -- Generate the block which contains the initialization call and
7576 -- the partial finalization code.
7578 -- begin
7579 -- [Deep_]Initialize (V (J1, ..., JN));
7581 -- Counter := Counter + 1;
7583 -- exception
7584 -- when others =>
7585 -- <finalization code>
7586 -- end;
7588 Init_Call := Build_Initialization_Call;
7590 if Present (Init_Call) then
7591 Init_Loop :=
7592 Make_Block_Statement (Loc,
7593 Handled_Statement_Sequence =>
7594 Make_Handled_Sequence_Of_Statements (Loc,
7595 Statements => New_List (Init_Call),
7596 Exception_Handlers => New_List (
7597 Make_Exception_Handler (Loc,
7598 Exception_Choices => New_List (
7599 Make_Others_Choice (Loc)),
7600 Statements => New_List (Final_Block)))));
7602 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
7603 Make_Assignment_Statement (Loc,
7604 Name => New_Occurrence_Of (Counter_Id, Loc),
7605 Expression =>
7606 Make_Op_Add (Loc,
7607 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
7608 Right_Opnd => Make_Integer_Literal (Loc, 1))));
7610 -- Generate all initialization loops starting from the innermost
7611 -- dimension.
7613 -- for Jnn in V'Range (Dim) loop
7614 -- <init loop>
7615 -- end loop;
7617 J := Last (Index_List);
7618 Dim := Num_Dims;
7619 while Present (J) and then Dim > 0 loop
7620 Loop_Id := J;
7621 Prev (J);
7622 Remove (Loop_Id);
7624 Init_Loop :=
7625 Make_Loop_Statement (Loc,
7626 Iteration_Scheme =>
7627 Make_Iteration_Scheme (Loc,
7628 Loop_Parameter_Specification =>
7629 Make_Loop_Parameter_Specification (Loc,
7630 Defining_Identifier => Loop_Id,
7631 Discrete_Subtype_Definition =>
7632 Make_Attribute_Reference (Loc,
7633 Prefix => Make_Identifier (Loc, Name_V),
7634 Attribute_Name => Name_Range,
7635 Expressions => New_List (
7636 Make_Integer_Literal (Loc, Dim))))),
7638 Statements => New_List (Init_Loop),
7639 End_Label => Empty);
7641 Dim := Dim - 1;
7642 end loop;
7644 -- Generate the block which contains the counter variable and the
7645 -- initialization loops.
7647 -- declare
7648 -- Counter : Integer := 0;
7649 -- begin
7650 -- <init loop>
7651 -- end;
7653 Init_Block :=
7654 Make_Block_Statement (Loc,
7655 Declarations => New_List (
7656 Make_Object_Declaration (Loc,
7657 Defining_Identifier => Counter_Id,
7658 Object_Definition =>
7659 New_Occurrence_Of (Standard_Integer, Loc),
7660 Expression => Make_Integer_Literal (Loc, 0))),
7662 Handled_Statement_Sequence =>
7663 Make_Handled_Sequence_Of_Statements (Loc,
7664 Statements => New_List (Init_Loop)));
7666 -- Otherwise previous errors or a missing full view may prevent the
7667 -- proper freezing of the component type. If this is the case, there
7668 -- is no [Deep_]Initialize primitive to call.
7670 else
7671 Init_Block := Make_Null_Statement (Loc);
7672 end if;
7674 return New_List (Init_Block);
7675 end Build_Initialize_Statements;
7677 -----------------------
7678 -- New_References_To --
7679 -----------------------
7681 function New_References_To
7682 (L : List_Id;
7683 Loc : Source_Ptr) return List_Id
7685 Refs : constant List_Id := New_List;
7686 Id : Node_Id;
7688 begin
7689 Id := First (L);
7690 while Present (Id) loop
7691 Append_To (Refs, New_Occurrence_Of (Id, Loc));
7692 Next (Id);
7693 end loop;
7695 return Refs;
7696 end New_References_To;
7698 -- Start of processing for Make_Deep_Array_Body
7700 begin
7701 case Prim is
7702 when Address_Case =>
7703 return Make_Finalize_Address_Stmts (Typ);
7705 when Adjust_Case
7706 | Finalize_Case
7708 return Build_Adjust_Or_Finalize_Statements (Typ);
7710 when Initialize_Case =>
7711 return Build_Initialize_Statements (Typ);
7712 end case;
7713 end Make_Deep_Array_Body;
7715 --------------------
7716 -- Make_Deep_Proc --
7717 --------------------
7719 function Make_Deep_Proc
7720 (Prim : Final_Primitives;
7721 Typ : Entity_Id;
7722 Stmts : List_Id) return Entity_Id
7724 Loc : constant Source_Ptr := Sloc (Typ);
7725 Formals : List_Id;
7726 Proc_Id : Entity_Id;
7728 begin
7729 -- Create the object formal, generate:
7730 -- V : System.Address
7732 if Prim = Address_Case then
7733 Formals := New_List (
7734 Make_Parameter_Specification (Loc,
7735 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7736 Parameter_Type =>
7737 New_Occurrence_Of (RTE (RE_Address), Loc)));
7739 -- Default case
7741 else
7742 -- V : in out Typ
7744 Formals := New_List (
7745 Make_Parameter_Specification (Loc,
7746 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7747 In_Present => True,
7748 Out_Present => True,
7749 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
7751 -- F : Boolean := True
7753 if Prim = Adjust_Case
7754 or else Prim = Finalize_Case
7755 then
7756 Append_To (Formals,
7757 Make_Parameter_Specification (Loc,
7758 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7759 Parameter_Type =>
7760 New_Occurrence_Of (Standard_Boolean, Loc),
7761 Expression =>
7762 New_Occurrence_Of (Standard_True, Loc)));
7763 end if;
7764 end if;
7766 Proc_Id :=
7767 Make_Defining_Identifier (Loc,
7768 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
7770 -- Generate:
7771 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
7772 -- begin
7773 -- <stmts>
7774 -- exception -- Finalize and Adjust cases only
7775 -- raise Program_Error;
7776 -- end Deep_Initialize / Adjust / Finalize;
7778 -- or
7780 -- procedure Finalize_Address (V : System.Address) is
7781 -- begin
7782 -- <stmts>
7783 -- end Finalize_Address;
7785 Discard_Node (
7786 Make_Subprogram_Body (Loc,
7787 Specification =>
7788 Make_Procedure_Specification (Loc,
7789 Defining_Unit_Name => Proc_Id,
7790 Parameter_Specifications => Formals),
7792 Declarations => Empty_List,
7794 Handled_Statement_Sequence =>
7795 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
7797 return Proc_Id;
7798 end Make_Deep_Proc;
7800 ---------------------------
7801 -- Make_Deep_Record_Body --
7802 ---------------------------
7804 function Make_Deep_Record_Body
7805 (Prim : Final_Primitives;
7806 Typ : Entity_Id;
7807 Is_Local : Boolean := False) return List_Id
7809 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
7810 -- Build the statements necessary to adjust a record type. The type may
7811 -- have discriminants and contain variant parts. Generate:
7813 -- begin
7814 -- begin
7815 -- [Deep_]Adjust (V.Comp_1);
7816 -- exception
7817 -- when Id : others =>
7818 -- if not Raised then
7819 -- Raised := True;
7820 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7821 -- end if;
7822 -- end;
7823 -- . . .
7824 -- begin
7825 -- [Deep_]Adjust (V.Comp_N);
7826 -- exception
7827 -- when Id : others =>
7828 -- if not Raised then
7829 -- Raised := True;
7830 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7831 -- end if;
7832 -- end;
7834 -- begin
7835 -- Deep_Adjust (V._parent, False); -- If applicable
7836 -- exception
7837 -- when Id : others =>
7838 -- if not Raised then
7839 -- Raised := True;
7840 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7841 -- end if;
7842 -- end;
7844 -- if F then
7845 -- begin
7846 -- Adjust (V); -- If applicable
7847 -- exception
7848 -- when others =>
7849 -- if not Raised then
7850 -- Raised := True;
7851 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7852 -- end if;
7853 -- end;
7854 -- end if;
7856 -- if Raised and then not Abort then
7857 -- Raise_From_Controlled_Operation (E);
7858 -- end if;
7859 -- end;
7861 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
7862 -- Build the statements necessary to finalize a record type. The type
7863 -- may have discriminants and contain variant parts. Generate:
7865 -- declare
7866 -- Abort : constant Boolean := Triggered_By_Abort;
7867 -- <or>
7868 -- Abort : constant Boolean := False; -- no abort
7869 -- E : Exception_Occurrence;
7870 -- Raised : Boolean := False;
7872 -- begin
7873 -- if F then
7874 -- begin
7875 -- Finalize (V); -- If applicable
7876 -- exception
7877 -- when others =>
7878 -- if not Raised then
7879 -- Raised := True;
7880 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7881 -- end if;
7882 -- end;
7883 -- end if;
7885 -- case Variant_1 is
7886 -- when Value_1 =>
7887 -- case State_Counter_N => -- If Is_Local is enabled
7888 -- when N => .
7889 -- goto LN; .
7890 -- ... .
7891 -- when 1 => .
7892 -- goto L1; .
7893 -- when others => .
7894 -- goto L0; .
7895 -- end case; .
7897 -- <<LN>> -- If Is_Local is enabled
7898 -- begin
7899 -- [Deep_]Finalize (V.Comp_N);
7900 -- exception
7901 -- when others =>
7902 -- if not Raised then
7903 -- Raised := True;
7904 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7905 -- end if;
7906 -- end;
7907 -- . . .
7908 -- <<L1>>
7909 -- begin
7910 -- [Deep_]Finalize (V.Comp_1);
7911 -- exception
7912 -- when others =>
7913 -- if not Raised then
7914 -- Raised := True;
7915 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7916 -- end if;
7917 -- end;
7918 -- <<L0>>
7919 -- end case;
7921 -- case State_Counter_1 => -- If Is_Local is enabled
7922 -- when M => .
7923 -- goto LM; .
7924 -- ...
7926 -- begin
7927 -- Deep_Finalize (V._parent, False); -- If applicable
7928 -- exception
7929 -- when Id : others =>
7930 -- if not Raised then
7931 -- Raised := True;
7932 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7933 -- end if;
7934 -- end;
7936 -- if Raised and then not Abort then
7937 -- Raise_From_Controlled_Operation (E);
7938 -- end if;
7939 -- end;
7941 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
7942 -- Given a derived tagged type Typ, traverse all components, find field
7943 -- _parent and return its type.
7945 procedure Preprocess_Components
7946 (Comps : Node_Id;
7947 Num_Comps : out Nat;
7948 Has_POC : out Boolean);
7949 -- Examine all components in component list Comps, count all controlled
7950 -- components and determine whether at least one of them is per-object
7951 -- constrained. Component _parent is always skipped.
7953 -----------------------------
7954 -- Build_Adjust_Statements --
7955 -----------------------------
7957 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
7958 Exceptions_OK : constant Boolean :=
7959 not Restriction_Active (No_Exception_Propagation);
7960 Loc : constant Source_Ptr := Sloc (Typ);
7961 Typ_Def : constant Node_Id :=
7962 Type_Definition (Parent (Typ));
7964 Bod_Stmts : List_Id;
7965 Finalizer_Data : Finalization_Exception_Data;
7966 Finalizer_Decls : List_Id := No_List;
7967 Rec_Def : Node_Id;
7968 Var_Case : Node_Id;
7970 function Process_Component_List_For_Adjust
7971 (Comps : Node_Id) return List_Id;
7972 -- Build all necessary adjust statements for a single component list
7974 ---------------------------------------
7975 -- Process_Component_List_For_Adjust --
7976 ---------------------------------------
7978 function Process_Component_List_For_Adjust
7979 (Comps : Node_Id) return List_Id
7981 Stmts : constant List_Id := New_List;
7983 procedure Process_Component_For_Adjust (Decl : Node_Id);
7984 -- Process the declaration of a single controlled component
7986 ----------------------------------
7987 -- Process_Component_For_Adjust --
7988 ----------------------------------
7990 procedure Process_Component_For_Adjust (Decl : Node_Id) is
7991 Id : constant Entity_Id := Defining_Identifier (Decl);
7992 Typ : constant Entity_Id := Etype (Id);
7994 Adj_Call : Node_Id;
7996 begin
7997 -- begin
7998 -- [Deep_]Adjust (V.Id);
8000 -- exception
8001 -- when others =>
8002 -- if not Raised then
8003 -- Raised := True;
8004 -- Save_Occurrence (E, Get_Current_Excep.all.all);
8005 -- end if;
8006 -- end;
8008 Adj_Call :=
8009 Make_Adjust_Call (
8010 Obj_Ref =>
8011 Make_Selected_Component (Loc,
8012 Prefix => Make_Identifier (Loc, Name_V),
8013 Selector_Name => Make_Identifier (Loc, Chars (Id))),
8014 Typ => Typ);
8016 -- Guard against a missing [Deep_]Adjust when the component
8017 -- type was not properly frozen.
8019 if Present (Adj_Call) then
8020 if Exceptions_OK then
8021 Adj_Call :=
8022 Make_Block_Statement (Loc,
8023 Handled_Statement_Sequence =>
8024 Make_Handled_Sequence_Of_Statements (Loc,
8025 Statements => New_List (Adj_Call),
8026 Exception_Handlers => New_List (
8027 Build_Exception_Handler (Finalizer_Data))));
8028 end if;
8030 Append_To (Stmts, Adj_Call);
8031 end if;
8032 end Process_Component_For_Adjust;
8034 -- Local variables
8036 Decl : Node_Id;
8037 Decl_Id : Entity_Id;
8038 Decl_Typ : Entity_Id;
8039 Has_POC : Boolean;
8040 Num_Comps : Nat;
8042 -- Start of processing for Process_Component_List_For_Adjust
8044 begin
8045 -- Perform an initial check, determine the number of controlled
8046 -- components in the current list and whether at least one of them
8047 -- is per-object constrained.
8049 Preprocess_Components (Comps, Num_Comps, Has_POC);
8051 -- The processing in this routine is done in the following order:
8052 -- 1) Regular components
8053 -- 2) Per-object constrained components
8054 -- 3) Variant parts
8056 if Num_Comps > 0 then
8058 -- Process all regular components in order of declarations
8060 Decl := First_Non_Pragma (Component_Items (Comps));
8061 while Present (Decl) loop
8062 Decl_Id := Defining_Identifier (Decl);
8063 Decl_Typ := Etype (Decl_Id);
8065 -- Skip _parent as well as per-object constrained components
8067 if Chars (Decl_Id) /= Name_uParent
8068 and then Needs_Finalization (Decl_Typ)
8069 then
8070 if Has_Access_Constraint (Decl_Id)
8071 and then No (Expression (Decl))
8072 then
8073 null;
8074 else
8075 Process_Component_For_Adjust (Decl);
8076 end if;
8077 end if;
8079 Next_Non_Pragma (Decl);
8080 end loop;
8082 -- Process all per-object constrained components in order of
8083 -- declarations.
8085 if Has_POC then
8086 Decl := First_Non_Pragma (Component_Items (Comps));
8087 while Present (Decl) loop
8088 Decl_Id := Defining_Identifier (Decl);
8089 Decl_Typ := Etype (Decl_Id);
8091 -- Skip _parent
8093 if Chars (Decl_Id) /= Name_uParent
8094 and then Needs_Finalization (Decl_Typ)
8095 and then Has_Access_Constraint (Decl_Id)
8096 and then No (Expression (Decl))
8097 then
8098 Process_Component_For_Adjust (Decl);
8099 end if;
8101 Next_Non_Pragma (Decl);
8102 end loop;
8103 end if;
8104 end if;
8106 -- Process all variants, if any
8108 Var_Case := Empty;
8109 if Present (Variant_Part (Comps)) then
8110 declare
8111 Var_Alts : constant List_Id := New_List;
8112 Var : Node_Id;
8114 begin
8115 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
8116 while Present (Var) loop
8118 -- Generate:
8119 -- when <discrete choices> =>
8120 -- <adjust statements>
8122 Append_To (Var_Alts,
8123 Make_Case_Statement_Alternative (Loc,
8124 Discrete_Choices =>
8125 New_Copy_List (Discrete_Choices (Var)),
8126 Statements =>
8127 Process_Component_List_For_Adjust (
8128 Component_List (Var))));
8130 Next_Non_Pragma (Var);
8131 end loop;
8133 -- Generate:
8134 -- case V.<discriminant> is
8135 -- when <discrete choices 1> =>
8136 -- <adjust statements 1>
8137 -- ...
8138 -- when <discrete choices N> =>
8139 -- <adjust statements N>
8140 -- end case;
8142 Var_Case :=
8143 Make_Case_Statement (Loc,
8144 Expression =>
8145 Make_Selected_Component (Loc,
8146 Prefix => Make_Identifier (Loc, Name_V),
8147 Selector_Name =>
8148 Make_Identifier (Loc,
8149 Chars => Chars (Name (Variant_Part (Comps))))),
8150 Alternatives => Var_Alts);
8151 end;
8152 end if;
8154 -- Add the variant case statement to the list of statements
8156 if Present (Var_Case) then
8157 Append_To (Stmts, Var_Case);
8158 end if;
8160 -- If the component list did not have any controlled components
8161 -- nor variants, return null.
8163 if Is_Empty_List (Stmts) then
8164 Append_To (Stmts, Make_Null_Statement (Loc));
8165 end if;
8167 return Stmts;
8168 end Process_Component_List_For_Adjust;
8170 -- Start of processing for Build_Adjust_Statements
8172 begin
8173 Finalizer_Decls := New_List;
8174 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
8176 if Nkind (Typ_Def) = N_Derived_Type_Definition then
8177 Rec_Def := Record_Extension_Part (Typ_Def);
8178 else
8179 Rec_Def := Typ_Def;
8180 end if;
8182 -- Create an adjust sequence for all record components
8184 if Present (Component_List (Rec_Def)) then
8185 Bod_Stmts :=
8186 Process_Component_List_For_Adjust (Component_List (Rec_Def));
8187 end if;
8189 -- A derived record type must adjust all inherited components. This
8190 -- action poses the following problem:
8192 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
8193 -- begin
8194 -- Adjust (Obj);
8195 -- ...
8197 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
8198 -- begin
8199 -- Deep_Adjust (Obj._parent);
8200 -- ...
8201 -- Adjust (Obj);
8202 -- ...
8204 -- Adjusting the derived type will invoke Adjust of the parent and
8205 -- then that of the derived type. This is undesirable because both
8206 -- routines may modify shared components. Only the Adjust of the
8207 -- derived type should be invoked.
8209 -- To prevent this double adjustment of shared components,
8210 -- Deep_Adjust uses a flag to control the invocation of Adjust:
8212 -- procedure Deep_Adjust
8213 -- (Obj : in out Some_Type;
8214 -- Flag : Boolean := True)
8215 -- is
8216 -- begin
8217 -- if Flag then
8218 -- Adjust (Obj);
8219 -- end if;
8220 -- ...
8222 -- When Deep_Adjust is invokes for field _parent, a value of False is
8223 -- provided for the flag:
8225 -- Deep_Adjust (Obj._parent, False);
8227 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
8228 declare
8229 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
8230 Adj_Stmt : Node_Id;
8231 Call : Node_Id;
8233 begin
8234 if Needs_Finalization (Par_Typ) then
8235 Call :=
8236 Make_Adjust_Call
8237 (Obj_Ref =>
8238 Make_Selected_Component (Loc,
8239 Prefix => Make_Identifier (Loc, Name_V),
8240 Selector_Name =>
8241 Make_Identifier (Loc, Name_uParent)),
8242 Typ => Par_Typ,
8243 Skip_Self => True);
8245 -- Generate:
8246 -- begin
8247 -- Deep_Adjust (V._parent, False);
8249 -- exception
8250 -- when Id : others =>
8251 -- if not Raised then
8252 -- Raised := True;
8253 -- Save_Occurrence (E,
8254 -- Get_Current_Excep.all.all);
8255 -- end if;
8256 -- end;
8258 if Present (Call) then
8259 Adj_Stmt := Call;
8261 if Exceptions_OK then
8262 Adj_Stmt :=
8263 Make_Block_Statement (Loc,
8264 Handled_Statement_Sequence =>
8265 Make_Handled_Sequence_Of_Statements (Loc,
8266 Statements => New_List (Adj_Stmt),
8267 Exception_Handlers => New_List (
8268 Build_Exception_Handler (Finalizer_Data))));
8269 end if;
8271 Prepend_To (Bod_Stmts, Adj_Stmt);
8272 end if;
8273 end if;
8274 end;
8275 end if;
8277 -- Adjust the object. This action must be performed last after all
8278 -- components have been adjusted.
8280 if Is_Controlled (Typ) then
8281 declare
8282 Adj_Stmt : Node_Id;
8283 Proc : Entity_Id;
8285 begin
8286 Proc := Find_Optional_Prim_Op (Typ, Name_Adjust);
8288 -- Generate:
8289 -- if F then
8290 -- begin
8291 -- Adjust (V);
8293 -- exception
8294 -- when others =>
8295 -- if not Raised then
8296 -- Raised := True;
8297 -- Save_Occurrence (E,
8298 -- Get_Current_Excep.all.all);
8299 -- end if;
8300 -- end;
8301 -- end if;
8303 if Present (Proc) then
8304 Adj_Stmt :=
8305 Make_Procedure_Call_Statement (Loc,
8306 Name => New_Occurrence_Of (Proc, Loc),
8307 Parameter_Associations => New_List (
8308 Make_Identifier (Loc, Name_V)));
8310 if Exceptions_OK then
8311 Adj_Stmt :=
8312 Make_Block_Statement (Loc,
8313 Handled_Statement_Sequence =>
8314 Make_Handled_Sequence_Of_Statements (Loc,
8315 Statements => New_List (Adj_Stmt),
8316 Exception_Handlers => New_List (
8317 Build_Exception_Handler
8318 (Finalizer_Data))));
8319 end if;
8321 Append_To (Bod_Stmts,
8322 Make_If_Statement (Loc,
8323 Condition => Make_Identifier (Loc, Name_F),
8324 Then_Statements => New_List (Adj_Stmt)));
8325 end if;
8326 end;
8327 end if;
8329 -- At this point either all adjustment statements have been generated
8330 -- or the type is not controlled.
8332 if Is_Empty_List (Bod_Stmts) then
8333 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
8335 return Bod_Stmts;
8337 -- Generate:
8338 -- declare
8339 -- Abort : constant Boolean := Triggered_By_Abort;
8340 -- <or>
8341 -- Abort : constant Boolean := False; -- no abort
8343 -- E : Exception_Occurrence;
8344 -- Raised : Boolean := False;
8346 -- begin
8347 -- <adjust statements>
8349 -- if Raised and then not Abort then
8350 -- Raise_From_Controlled_Operation (E);
8351 -- end if;
8352 -- end;
8354 else
8355 if Exceptions_OK then
8356 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
8357 end if;
8359 return
8360 New_List (
8361 Make_Block_Statement (Loc,
8362 Declarations =>
8363 Finalizer_Decls,
8364 Handled_Statement_Sequence =>
8365 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
8366 end if;
8367 end Build_Adjust_Statements;
8369 -------------------------------
8370 -- Build_Finalize_Statements --
8371 -------------------------------
8373 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
8374 Exceptions_OK : constant Boolean :=
8375 not Restriction_Active (No_Exception_Propagation);
8376 Loc : constant Source_Ptr := Sloc (Typ);
8377 Typ_Def : constant Node_Id :=
8378 Type_Definition (Parent (Typ));
8380 Bod_Stmts : List_Id;
8381 Counter : Int := 0;
8382 Finalizer_Data : Finalization_Exception_Data;
8383 Finalizer_Decls : List_Id := No_List;
8384 Rec_Def : Node_Id;
8385 Var_Case : Node_Id;
8387 function Process_Component_List_For_Finalize
8388 (Comps : Node_Id) return List_Id;
8389 -- Build all necessary finalization statements for a single component
8390 -- list. The statements may include a jump circuitry if flag Is_Local
8391 -- is enabled.
8393 -----------------------------------------
8394 -- Process_Component_List_For_Finalize --
8395 -----------------------------------------
8397 function Process_Component_List_For_Finalize
8398 (Comps : Node_Id) return List_Id
8400 Alts : List_Id;
8401 Counter_Id : Entity_Id;
8402 Decl : Node_Id;
8403 Decl_Id : Entity_Id;
8404 Decl_Typ : Entity_Id;
8405 Decls : List_Id;
8406 Has_POC : Boolean;
8407 Jump_Block : Node_Id;
8408 Label : Node_Id;
8409 Label_Id : Entity_Id;
8410 Num_Comps : Nat;
8411 Stmts : List_Id;
8413 procedure Process_Component_For_Finalize
8414 (Decl : Node_Id;
8415 Alts : List_Id;
8416 Decls : List_Id;
8417 Stmts : List_Id);
8418 -- Process the declaration of a single controlled component. If
8419 -- flag Is_Local is enabled, create the corresponding label and
8420 -- jump circuitry. Alts is the list of case alternatives, Decls
8421 -- is the top level declaration list where labels are declared
8422 -- and Stmts is the list of finalization actions.
8424 ------------------------------------
8425 -- Process_Component_For_Finalize --
8426 ------------------------------------
8428 procedure Process_Component_For_Finalize
8429 (Decl : Node_Id;
8430 Alts : List_Id;
8431 Decls : List_Id;
8432 Stmts : List_Id)
8434 Id : constant Entity_Id := Defining_Identifier (Decl);
8435 Typ : constant Entity_Id := Etype (Id);
8436 Fin_Call : Node_Id;
8438 begin
8439 if Is_Local then
8440 declare
8441 Label : Node_Id;
8442 Label_Id : Entity_Id;
8444 begin
8445 -- Generate:
8446 -- LN : label;
8448 Label_Id :=
8449 Make_Identifier (Loc,
8450 Chars => New_External_Name ('L', Num_Comps));
8451 Set_Entity (Label_Id,
8452 Make_Defining_Identifier (Loc, Chars (Label_Id)));
8453 Label := Make_Label (Loc, Label_Id);
8455 Append_To (Decls,
8456 Make_Implicit_Label_Declaration (Loc,
8457 Defining_Identifier => Entity (Label_Id),
8458 Label_Construct => Label));
8460 -- Generate:
8461 -- when N =>
8462 -- goto LN;
8464 Append_To (Alts,
8465 Make_Case_Statement_Alternative (Loc,
8466 Discrete_Choices => New_List (
8467 Make_Integer_Literal (Loc, Num_Comps)),
8469 Statements => New_List (
8470 Make_Goto_Statement (Loc,
8471 Name =>
8472 New_Occurrence_Of (Entity (Label_Id), Loc)))));
8474 -- Generate:
8475 -- <<LN>>
8477 Append_To (Stmts, Label);
8479 -- Decrease the number of components to be processed.
8480 -- This action yields a new Label_Id in future calls.
8482 Num_Comps := Num_Comps - 1;
8483 end;
8484 end if;
8486 -- Generate:
8487 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
8489 -- begin -- Exception handlers allowed
8490 -- [Deep_]Finalize (V.Id);
8491 -- exception
8492 -- when others =>
8493 -- if not Raised then
8494 -- Raised := True;
8495 -- Save_Occurrence (E,
8496 -- Get_Current_Excep.all.all);
8497 -- end if;
8498 -- end;
8500 Fin_Call :=
8501 Make_Final_Call
8502 (Obj_Ref =>
8503 Make_Selected_Component (Loc,
8504 Prefix => Make_Identifier (Loc, Name_V),
8505 Selector_Name => Make_Identifier (Loc, Chars (Id))),
8506 Typ => Typ);
8508 -- Guard against a missing [Deep_]Finalize when the component
8509 -- type was not properly frozen.
8511 if Present (Fin_Call) then
8512 if Exceptions_OK then
8513 Fin_Call :=
8514 Make_Block_Statement (Loc,
8515 Handled_Statement_Sequence =>
8516 Make_Handled_Sequence_Of_Statements (Loc,
8517 Statements => New_List (Fin_Call),
8518 Exception_Handlers => New_List (
8519 Build_Exception_Handler (Finalizer_Data))));
8520 end if;
8522 Append_To (Stmts, Fin_Call);
8523 end if;
8524 end Process_Component_For_Finalize;
8526 -- Start of processing for Process_Component_List_For_Finalize
8528 begin
8529 -- Perform an initial check, look for controlled and per-object
8530 -- constrained components.
8532 Preprocess_Components (Comps, Num_Comps, Has_POC);
8534 -- Create a state counter to service the current component list.
8535 -- This step is performed before the variants are inspected in
8536 -- order to generate the same state counter names as those from
8537 -- Build_Initialize_Statements.
8539 if Num_Comps > 0 and then Is_Local then
8540 Counter := Counter + 1;
8542 Counter_Id :=
8543 Make_Defining_Identifier (Loc,
8544 Chars => New_External_Name ('C', Counter));
8545 end if;
8547 -- Process the component in the following order:
8548 -- 1) Variants
8549 -- 2) Per-object constrained components
8550 -- 3) Regular components
8552 -- Start with the variant parts
8554 Var_Case := Empty;
8555 if Present (Variant_Part (Comps)) then
8556 declare
8557 Var_Alts : constant List_Id := New_List;
8558 Var : Node_Id;
8560 begin
8561 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
8562 while Present (Var) loop
8564 -- Generate:
8565 -- when <discrete choices> =>
8566 -- <finalize statements>
8568 Append_To (Var_Alts,
8569 Make_Case_Statement_Alternative (Loc,
8570 Discrete_Choices =>
8571 New_Copy_List (Discrete_Choices (Var)),
8572 Statements =>
8573 Process_Component_List_For_Finalize (
8574 Component_List (Var))));
8576 Next_Non_Pragma (Var);
8577 end loop;
8579 -- Generate:
8580 -- case V.<discriminant> is
8581 -- when <discrete choices 1> =>
8582 -- <finalize statements 1>
8583 -- ...
8584 -- when <discrete choices N> =>
8585 -- <finalize statements N>
8586 -- end case;
8588 Var_Case :=
8589 Make_Case_Statement (Loc,
8590 Expression =>
8591 Make_Selected_Component (Loc,
8592 Prefix => Make_Identifier (Loc, Name_V),
8593 Selector_Name =>
8594 Make_Identifier (Loc,
8595 Chars => Chars (Name (Variant_Part (Comps))))),
8596 Alternatives => Var_Alts);
8597 end;
8598 end if;
8600 -- The current component list does not have a single controlled
8601 -- component, however it may contain variants. Return the case
8602 -- statement for the variants or nothing.
8604 if Num_Comps = 0 then
8605 if Present (Var_Case) then
8606 return New_List (Var_Case);
8607 else
8608 return New_List (Make_Null_Statement (Loc));
8609 end if;
8610 end if;
8612 -- Prepare all lists
8614 Alts := New_List;
8615 Decls := New_List;
8616 Stmts := New_List;
8618 -- Process all per-object constrained components in reverse order
8620 if Has_POC then
8621 Decl := Last_Non_Pragma (Component_Items (Comps));
8622 while Present (Decl) loop
8623 Decl_Id := Defining_Identifier (Decl);
8624 Decl_Typ := Etype (Decl_Id);
8626 -- Skip _parent
8628 if Chars (Decl_Id) /= Name_uParent
8629 and then Needs_Finalization (Decl_Typ)
8630 and then Has_Access_Constraint (Decl_Id)
8631 and then No (Expression (Decl))
8632 then
8633 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
8634 end if;
8636 Prev_Non_Pragma (Decl);
8637 end loop;
8638 end if;
8640 -- Process the rest of the components in reverse order
8642 Decl := Last_Non_Pragma (Component_Items (Comps));
8643 while Present (Decl) loop
8644 Decl_Id := Defining_Identifier (Decl);
8645 Decl_Typ := Etype (Decl_Id);
8647 -- Skip _parent
8649 if Chars (Decl_Id) /= Name_uParent
8650 and then Needs_Finalization (Decl_Typ)
8651 then
8652 -- Skip per-object constrained components since they were
8653 -- handled in the above step.
8655 if Has_Access_Constraint (Decl_Id)
8656 and then No (Expression (Decl))
8657 then
8658 null;
8659 else
8660 Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
8661 end if;
8662 end if;
8664 Prev_Non_Pragma (Decl);
8665 end loop;
8667 -- Generate:
8668 -- declare
8669 -- LN : label; -- If Is_Local is enabled
8670 -- ... .
8671 -- L0 : label; .
8673 -- begin .
8674 -- case CounterX is .
8675 -- when N => .
8676 -- goto LN; .
8677 -- ... .
8678 -- when 1 => .
8679 -- goto L1; .
8680 -- when others => .
8681 -- goto L0; .
8682 -- end case; .
8684 -- <<LN>> -- If Is_Local is enabled
8685 -- begin
8686 -- [Deep_]Finalize (V.CompY);
8687 -- exception
8688 -- when Id : others =>
8689 -- if not Raised then
8690 -- Raised := True;
8691 -- Save_Occurrence (E,
8692 -- Get_Current_Excep.all.all);
8693 -- end if;
8694 -- end;
8695 -- ...
8696 -- <<L0>> -- If Is_Local is enabled
8697 -- end;
8699 if Is_Local then
8701 -- Add the declaration of default jump location L0, its
8702 -- corresponding alternative and its place in the statements.
8704 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
8705 Set_Entity (Label_Id,
8706 Make_Defining_Identifier (Loc, Chars (Label_Id)));
8707 Label := Make_Label (Loc, Label_Id);
8709 Append_To (Decls, -- declaration
8710 Make_Implicit_Label_Declaration (Loc,
8711 Defining_Identifier => Entity (Label_Id),
8712 Label_Construct => Label));
8714 Append_To (Alts, -- alternative
8715 Make_Case_Statement_Alternative (Loc,
8716 Discrete_Choices => New_List (
8717 Make_Others_Choice (Loc)),
8719 Statements => New_List (
8720 Make_Goto_Statement (Loc,
8721 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
8723 Append_To (Stmts, Label); -- statement
8725 -- Create the jump block
8727 Prepend_To (Stmts,
8728 Make_Case_Statement (Loc,
8729 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
8730 Alternatives => Alts));
8731 end if;
8733 Jump_Block :=
8734 Make_Block_Statement (Loc,
8735 Declarations => Decls,
8736 Handled_Statement_Sequence =>
8737 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
8739 if Present (Var_Case) then
8740 return New_List (Var_Case, Jump_Block);
8741 else
8742 return New_List (Jump_Block);
8743 end if;
8744 end Process_Component_List_For_Finalize;
8746 -- Start of processing for Build_Finalize_Statements
8748 begin
8749 Finalizer_Decls := New_List;
8750 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
8752 if Nkind (Typ_Def) = N_Derived_Type_Definition then
8753 Rec_Def := Record_Extension_Part (Typ_Def);
8754 else
8755 Rec_Def := Typ_Def;
8756 end if;
8758 -- Create a finalization sequence for all record components
8760 if Present (Component_List (Rec_Def)) then
8761 Bod_Stmts :=
8762 Process_Component_List_For_Finalize (Component_List (Rec_Def));
8763 end if;
8765 -- A derived record type must finalize all inherited components. This
8766 -- action poses the following problem:
8768 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
8769 -- begin
8770 -- Finalize (Obj);
8771 -- ...
8773 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
8774 -- begin
8775 -- Deep_Finalize (Obj._parent);
8776 -- ...
8777 -- Finalize (Obj);
8778 -- ...
8780 -- Finalizing the derived type will invoke Finalize of the parent and
8781 -- then that of the derived type. This is undesirable because both
8782 -- routines may modify shared components. Only the Finalize of the
8783 -- derived type should be invoked.
8785 -- To prevent this double adjustment of shared components,
8786 -- Deep_Finalize uses a flag to control the invocation of Finalize:
8788 -- procedure Deep_Finalize
8789 -- (Obj : in out Some_Type;
8790 -- Flag : Boolean := True)
8791 -- is
8792 -- begin
8793 -- if Flag then
8794 -- Finalize (Obj);
8795 -- end if;
8796 -- ...
8798 -- When Deep_Finalize is invoked for field _parent, a value of False
8799 -- is provided for the flag:
8801 -- Deep_Finalize (Obj._parent, False);
8803 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
8804 declare
8805 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
8806 Call : Node_Id;
8807 Fin_Stmt : Node_Id;
8809 begin
8810 if Needs_Finalization (Par_Typ) then
8811 Call :=
8812 Make_Final_Call
8813 (Obj_Ref =>
8814 Make_Selected_Component (Loc,
8815 Prefix => Make_Identifier (Loc, Name_V),
8816 Selector_Name =>
8817 Make_Identifier (Loc, Name_uParent)),
8818 Typ => Par_Typ,
8819 Skip_Self => True);
8821 -- Generate:
8822 -- begin
8823 -- Deep_Finalize (V._parent, False);
8825 -- exception
8826 -- when Id : others =>
8827 -- if not Raised then
8828 -- Raised := True;
8829 -- Save_Occurrence (E,
8830 -- Get_Current_Excep.all.all);
8831 -- end if;
8832 -- end;
8834 if Present (Call) then
8835 Fin_Stmt := Call;
8837 if Exceptions_OK then
8838 Fin_Stmt :=
8839 Make_Block_Statement (Loc,
8840 Handled_Statement_Sequence =>
8841 Make_Handled_Sequence_Of_Statements (Loc,
8842 Statements => New_List (Fin_Stmt),
8843 Exception_Handlers => New_List (
8844 Build_Exception_Handler
8845 (Finalizer_Data))));
8846 end if;
8848 Append_To (Bod_Stmts, Fin_Stmt);
8849 end if;
8850 end if;
8851 end;
8852 end if;
8854 -- Finalize the object. This action must be performed first before
8855 -- all components have been finalized.
8857 if Is_Controlled (Typ) and then not Is_Local then
8858 declare
8859 Fin_Stmt : Node_Id;
8860 Proc : Entity_Id;
8862 begin
8863 Proc := Find_Optional_Prim_Op (Typ, Name_Finalize);
8865 -- Generate:
8866 -- if F then
8867 -- begin
8868 -- Finalize (V);
8870 -- exception
8871 -- when others =>
8872 -- if not Raised then
8873 -- Raised := True;
8874 -- Save_Occurrence (E,
8875 -- Get_Current_Excep.all.all);
8876 -- end if;
8877 -- end;
8878 -- end if;
8880 if Present (Proc) then
8881 Fin_Stmt :=
8882 Make_Procedure_Call_Statement (Loc,
8883 Name => New_Occurrence_Of (Proc, Loc),
8884 Parameter_Associations => New_List (
8885 Make_Identifier (Loc, Name_V)));
8887 if Exceptions_OK then
8888 Fin_Stmt :=
8889 Make_Block_Statement (Loc,
8890 Handled_Statement_Sequence =>
8891 Make_Handled_Sequence_Of_Statements (Loc,
8892 Statements => New_List (Fin_Stmt),
8893 Exception_Handlers => New_List (
8894 Build_Exception_Handler
8895 (Finalizer_Data))));
8896 end if;
8898 Prepend_To (Bod_Stmts,
8899 Make_If_Statement (Loc,
8900 Condition => Make_Identifier (Loc, Name_F),
8901 Then_Statements => New_List (Fin_Stmt)));
8902 end if;
8903 end;
8904 end if;
8906 -- At this point either all finalization statements have been
8907 -- generated or the type is not controlled.
8909 if No (Bod_Stmts) then
8910 return New_List (Make_Null_Statement (Loc));
8912 -- Generate:
8913 -- declare
8914 -- Abort : constant Boolean := Triggered_By_Abort;
8915 -- <or>
8916 -- Abort : constant Boolean := False; -- no abort
8918 -- E : Exception_Occurrence;
8919 -- Raised : Boolean := False;
8921 -- begin
8922 -- <finalize statements>
8924 -- if Raised and then not Abort then
8925 -- Raise_From_Controlled_Operation (E);
8926 -- end if;
8927 -- end;
8929 else
8930 if Exceptions_OK then
8931 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
8932 end if;
8934 return
8935 New_List (
8936 Make_Block_Statement (Loc,
8937 Declarations =>
8938 Finalizer_Decls,
8939 Handled_Statement_Sequence =>
8940 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
8941 end if;
8942 end Build_Finalize_Statements;
8944 -----------------------
8945 -- Parent_Field_Type --
8946 -----------------------
8948 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
8949 Field : Entity_Id;
8951 begin
8952 Field := First_Entity (Typ);
8953 while Present (Field) loop
8954 if Chars (Field) = Name_uParent then
8955 return Etype (Field);
8956 end if;
8958 Next_Entity (Field);
8959 end loop;
8961 -- A derived tagged type should always have a parent field
8963 raise Program_Error;
8964 end Parent_Field_Type;
8966 ---------------------------
8967 -- Preprocess_Components --
8968 ---------------------------
8970 procedure Preprocess_Components
8971 (Comps : Node_Id;
8972 Num_Comps : out Nat;
8973 Has_POC : out Boolean)
8975 Decl : Node_Id;
8976 Id : Entity_Id;
8977 Typ : Entity_Id;
8979 begin
8980 Num_Comps := 0;
8981 Has_POC := False;
8983 Decl := First_Non_Pragma (Component_Items (Comps));
8984 while Present (Decl) loop
8985 Id := Defining_Identifier (Decl);
8986 Typ := Etype (Id);
8988 -- Skip field _parent
8990 if Chars (Id) /= Name_uParent
8991 and then Needs_Finalization (Typ)
8992 then
8993 Num_Comps := Num_Comps + 1;
8995 if Has_Access_Constraint (Id)
8996 and then No (Expression (Decl))
8997 then
8998 Has_POC := True;
8999 end if;
9000 end if;
9002 Next_Non_Pragma (Decl);
9003 end loop;
9004 end Preprocess_Components;
9006 -- Start of processing for Make_Deep_Record_Body
9008 begin
9009 case Prim is
9010 when Address_Case =>
9011 return Make_Finalize_Address_Stmts (Typ);
9013 when Adjust_Case =>
9014 return Build_Adjust_Statements (Typ);
9016 when Finalize_Case =>
9017 return Build_Finalize_Statements (Typ);
9019 when Initialize_Case =>
9020 declare
9021 Loc : constant Source_Ptr := Sloc (Typ);
9023 begin
9024 if Is_Controlled (Typ) then
9025 return New_List (
9026 Make_Procedure_Call_Statement (Loc,
9027 Name =>
9028 New_Occurrence_Of
9029 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
9030 Parameter_Associations => New_List (
9031 Make_Identifier (Loc, Name_V))));
9032 else
9033 return Empty_List;
9034 end if;
9035 end;
9036 end case;
9037 end Make_Deep_Record_Body;
9039 ----------------------
9040 -- Make_Final_Call --
9041 ----------------------
9043 function Make_Final_Call
9044 (Obj_Ref : Node_Id;
9045 Typ : Entity_Id;
9046 Skip_Self : Boolean := False) return Node_Id
9048 Loc : constant Source_Ptr := Sloc (Obj_Ref);
9049 Atyp : Entity_Id;
9050 Fin_Id : Entity_Id := Empty;
9051 Ref : Node_Id;
9052 Utyp : Entity_Id;
9054 begin
9055 Ref := Obj_Ref;
9057 -- Recover the proper type which contains [Deep_]Finalize
9059 if Is_Class_Wide_Type (Typ) then
9060 Utyp := Root_Type (Typ);
9061 Atyp := Utyp;
9063 elsif Is_Concurrent_Type (Typ) then
9064 Utyp := Corresponding_Record_Type (Typ);
9065 Atyp := Empty;
9066 Ref := Convert_Concurrent (Ref, Typ);
9068 elsif Is_Private_Type (Typ)
9069 and then Present (Full_View (Typ))
9070 and then Is_Concurrent_Type (Full_View (Typ))
9071 then
9072 Utyp := Corresponding_Record_Type (Full_View (Typ));
9073 Atyp := Typ;
9074 Ref := Convert_Concurrent (Ref, Full_View (Typ));
9076 else
9077 Utyp := Typ;
9078 Atyp := Typ;
9079 end if;
9081 Utyp := Underlying_Type (Base_Type (Utyp));
9082 Set_Assignment_OK (Ref);
9084 -- Deal with untagged derivation of private views. If the parent type
9085 -- is a protected type, Deep_Finalize is found on the corresponding
9086 -- record of the ancestor.
9088 if Is_Untagged_Derivation (Typ) then
9089 if Is_Protected_Type (Typ) then
9090 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
9091 else
9092 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
9094 if Is_Protected_Type (Utyp) then
9095 Utyp := Corresponding_Record_Type (Utyp);
9096 end if;
9097 end if;
9099 Ref := Unchecked_Convert_To (Utyp, Ref);
9100 Set_Assignment_OK (Ref);
9101 end if;
9103 -- Deal with derived private types which do not inherit primitives from
9104 -- their parents. In this case, [Deep_]Finalize can be found in the full
9105 -- view of the parent type.
9107 if Present (Utyp)
9108 and then Is_Tagged_Type (Utyp)
9109 and then Is_Derived_Type (Utyp)
9110 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
9111 and then Is_Private_Type (Etype (Utyp))
9112 and then Present (Full_View (Etype (Utyp)))
9113 then
9114 Utyp := Full_View (Etype (Utyp));
9115 Ref := Unchecked_Convert_To (Utyp, Ref);
9116 Set_Assignment_OK (Ref);
9117 end if;
9119 -- When dealing with the completion of a private type, use the base type
9120 -- instead.
9122 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
9123 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
9125 Utyp := Base_Type (Utyp);
9126 Ref := Unchecked_Convert_To (Utyp, Ref);
9127 Set_Assignment_OK (Ref);
9128 end if;
9130 -- The underlying type may not be present due to a missing full view. In
9131 -- this case freezing did not take place and there is no [Deep_]Finalize
9132 -- primitive to call.
9134 if No (Utyp) then
9135 return Empty;
9137 elsif Skip_Self then
9138 if Has_Controlled_Component (Utyp) then
9139 if Is_Tagged_Type (Utyp) then
9140 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
9141 else
9142 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
9143 end if;
9144 end if;
9146 -- Class-wide types, interfaces and types with controlled components
9148 elsif Is_Class_Wide_Type (Typ)
9149 or else Is_Interface (Typ)
9150 or else Has_Controlled_Component (Utyp)
9151 then
9152 if Is_Tagged_Type (Utyp) then
9153 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
9154 else
9155 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
9156 end if;
9158 -- Derivations from [Limited_]Controlled
9160 elsif Is_Controlled (Utyp) then
9161 if Has_Controlled_Component (Utyp) then
9162 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
9163 else
9164 Fin_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Finalize_Case));
9165 end if;
9167 -- Tagged types
9169 elsif Is_Tagged_Type (Utyp) then
9170 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
9172 else
9173 raise Program_Error;
9174 end if;
9176 if Present (Fin_Id) then
9178 -- When finalizing a class-wide object, do not convert to the root
9179 -- type in order to produce a dispatching call.
9181 if Is_Class_Wide_Type (Typ) then
9182 null;
9184 -- Ensure that a finalization routine is at least decorated in order
9185 -- to inspect the object parameter.
9187 elsif Analyzed (Fin_Id)
9188 or else Ekind (Fin_Id) = E_Procedure
9189 then
9190 -- In certain cases, such as the creation of Stream_Read, the
9191 -- visible entity of the type is its full view. Since Stream_Read
9192 -- will have to create an object of type Typ, the local object
9193 -- will be finalzed by the scope finalizer generated later on. The
9194 -- object parameter of Deep_Finalize will always use the private
9195 -- view of the type. To avoid such a clash between a private and a
9196 -- full view, perform an unchecked conversion of the object
9197 -- reference to the private view.
9199 declare
9200 Formal_Typ : constant Entity_Id :=
9201 Etype (First_Formal (Fin_Id));
9202 begin
9203 if Is_Private_Type (Formal_Typ)
9204 and then Present (Full_View (Formal_Typ))
9205 and then Full_View (Formal_Typ) = Utyp
9206 then
9207 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
9208 end if;
9209 end;
9211 Ref := Convert_View (Fin_Id, Ref);
9212 end if;
9214 return
9215 Make_Call (Loc,
9216 Proc_Id => Fin_Id,
9217 Param => Ref,
9218 Skip_Self => Skip_Self);
9219 else
9220 return Empty;
9221 end if;
9222 end Make_Final_Call;
9224 --------------------------------
9225 -- Make_Finalize_Address_Body --
9226 --------------------------------
9228 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
9229 Is_Task : constant Boolean :=
9230 Ekind (Typ) = E_Record_Type
9231 and then Is_Concurrent_Record_Type (Typ)
9232 and then Ekind (Corresponding_Concurrent_Type (Typ)) =
9233 E_Task_Type;
9234 Loc : constant Source_Ptr := Sloc (Typ);
9235 Proc_Id : Entity_Id;
9236 Stmts : List_Id;
9238 begin
9239 -- The corresponding records of task types are not controlled by design.
9240 -- For the sake of completeness, create an empty Finalize_Address to be
9241 -- used in task class-wide allocations.
9243 if Is_Task then
9244 null;
9246 -- Nothing to do if the type is not controlled or it already has a
9247 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
9248 -- come from source. These are usually generated for completeness and
9249 -- do not need the Finalize_Address primitive.
9251 elsif not Needs_Finalization (Typ)
9252 or else Present (TSS (Typ, TSS_Finalize_Address))
9253 or else
9254 (Is_Class_Wide_Type (Typ)
9255 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
9256 and then not Comes_From_Source (Root_Type (Typ)))
9257 then
9258 return;
9259 end if;
9261 Proc_Id :=
9262 Make_Defining_Identifier (Loc,
9263 Make_TSS_Name (Typ, TSS_Finalize_Address));
9265 -- Generate:
9267 -- procedure <Typ>FD (V : System.Address) is
9268 -- begin
9269 -- null; -- for tasks
9271 -- declare -- for all other types
9272 -- type Pnn is access all Typ;
9273 -- for Pnn'Storage_Size use 0;
9274 -- begin
9275 -- [Deep_]Finalize (Pnn (V).all);
9276 -- end;
9277 -- end TypFD;
9279 if Is_Task then
9280 Stmts := New_List (Make_Null_Statement (Loc));
9281 else
9282 Stmts := Make_Finalize_Address_Stmts (Typ);
9283 end if;
9285 Discard_Node (
9286 Make_Subprogram_Body (Loc,
9287 Specification =>
9288 Make_Procedure_Specification (Loc,
9289 Defining_Unit_Name => Proc_Id,
9291 Parameter_Specifications => New_List (
9292 Make_Parameter_Specification (Loc,
9293 Defining_Identifier =>
9294 Make_Defining_Identifier (Loc, Name_V),
9295 Parameter_Type =>
9296 New_Occurrence_Of (RTE (RE_Address), Loc)))),
9298 Declarations => No_List,
9300 Handled_Statement_Sequence =>
9301 Make_Handled_Sequence_Of_Statements (Loc,
9302 Statements => Stmts)));
9304 Set_TSS (Typ, Proc_Id);
9305 end Make_Finalize_Address_Body;
9307 ---------------------------------
9308 -- Make_Finalize_Address_Stmts --
9309 ---------------------------------
9311 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
9312 Loc : constant Source_Ptr := Sloc (Typ);
9314 Decls : List_Id;
9315 Desig_Typ : Entity_Id;
9316 Fin_Block : Node_Id;
9317 Fin_Call : Node_Id;
9318 Obj_Expr : Node_Id;
9319 Ptr_Typ : Entity_Id;
9321 begin
9322 if Is_Array_Type (Typ) then
9323 if Is_Constrained (First_Subtype (Typ)) then
9324 Desig_Typ := First_Subtype (Typ);
9325 else
9326 Desig_Typ := Base_Type (Typ);
9327 end if;
9329 -- Class-wide types of constrained root types
9331 elsif Is_Class_Wide_Type (Typ)
9332 and then Has_Discriminants (Root_Type (Typ))
9333 and then not
9334 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
9335 then
9336 declare
9337 Parent_Typ : Entity_Id;
9339 begin
9340 -- Climb the parent type chain looking for a non-constrained type
9342 Parent_Typ := Root_Type (Typ);
9343 while Parent_Typ /= Etype (Parent_Typ)
9344 and then Has_Discriminants (Parent_Typ)
9345 and then not
9346 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
9347 loop
9348 Parent_Typ := Etype (Parent_Typ);
9349 end loop;
9351 -- Handle views created for tagged types with unknown
9352 -- discriminants.
9354 if Is_Underlying_Record_View (Parent_Typ) then
9355 Parent_Typ := Underlying_Record_View (Parent_Typ);
9356 end if;
9358 Desig_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
9359 end;
9361 -- General case
9363 else
9364 Desig_Typ := Typ;
9365 end if;
9367 -- Generate:
9368 -- type Ptr_Typ is access all Typ;
9369 -- for Ptr_Typ'Storage_Size use 0;
9371 Ptr_Typ := Make_Temporary (Loc, 'P');
9373 Decls := New_List (
9374 Make_Full_Type_Declaration (Loc,
9375 Defining_Identifier => Ptr_Typ,
9376 Type_Definition =>
9377 Make_Access_To_Object_Definition (Loc,
9378 All_Present => True,
9379 Subtype_Indication => New_Occurrence_Of (Desig_Typ, Loc))),
9381 Make_Attribute_Definition_Clause (Loc,
9382 Name => New_Occurrence_Of (Ptr_Typ, Loc),
9383 Chars => Name_Storage_Size,
9384 Expression => Make_Integer_Literal (Loc, 0)));
9386 Obj_Expr := Make_Identifier (Loc, Name_V);
9388 -- Unconstrained arrays require special processing in order to retrieve
9389 -- the elements. To achieve this, we have to skip the dope vector which
9390 -- lays in front of the elements and then use a thin pointer to perform
9391 -- the address-to-access conversion.
9393 if Is_Array_Type (Typ)
9394 and then not Is_Constrained (First_Subtype (Typ))
9395 then
9396 declare
9397 Dope_Id : Entity_Id;
9399 begin
9400 -- Ensure that Ptr_Typ a thin pointer, generate:
9401 -- for Ptr_Typ'Size use System.Address'Size;
9403 Append_To (Decls,
9404 Make_Attribute_Definition_Clause (Loc,
9405 Name => New_Occurrence_Of (Ptr_Typ, Loc),
9406 Chars => Name_Size,
9407 Expression =>
9408 Make_Integer_Literal (Loc, System_Address_Size)));
9410 -- Generate:
9411 -- Dnn : constant Storage_Offset :=
9412 -- Desig_Typ'Descriptor_Size / Storage_Unit;
9414 Dope_Id := Make_Temporary (Loc, 'D');
9416 Append_To (Decls,
9417 Make_Object_Declaration (Loc,
9418 Defining_Identifier => Dope_Id,
9419 Constant_Present => True,
9420 Object_Definition =>
9421 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc),
9422 Expression =>
9423 Make_Op_Divide (Loc,
9424 Left_Opnd =>
9425 Make_Attribute_Reference (Loc,
9426 Prefix => New_Occurrence_Of (Desig_Typ, Loc),
9427 Attribute_Name => Name_Descriptor_Size),
9428 Right_Opnd =>
9429 Make_Integer_Literal (Loc, System_Storage_Unit))));
9431 -- Shift the address from the start of the dope vector to the
9432 -- start of the elements:
9434 -- V + Dnn
9436 -- Note that this is done through a wrapper routine since RTSfind
9437 -- cannot retrieve operations with string names of the form "+".
9439 Obj_Expr :=
9440 Make_Function_Call (Loc,
9441 Name =>
9442 New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
9443 Parameter_Associations => New_List (
9444 Obj_Expr,
9445 New_Occurrence_Of (Dope_Id, Loc)));
9446 end;
9447 end if;
9449 Fin_Call :=
9450 Make_Final_Call (
9451 Obj_Ref =>
9452 Make_Explicit_Dereference (Loc,
9453 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
9454 Typ => Desig_Typ);
9456 if Present (Fin_Call) then
9457 Fin_Block :=
9458 Make_Block_Statement (Loc,
9459 Declarations => Decls,
9460 Handled_Statement_Sequence =>
9461 Make_Handled_Sequence_Of_Statements (Loc,
9462 Statements => New_List (Fin_Call)));
9464 -- Otherwise previous errors or a missing full view may prevent the
9465 -- proper freezing of the designated type. If this is the case, there
9466 -- is no [Deep_]Finalize primitive to call.
9468 else
9469 Fin_Block := Make_Null_Statement (Loc);
9470 end if;
9472 return New_List (Fin_Block);
9473 end Make_Finalize_Address_Stmts;
9475 -------------------------------------
9476 -- Make_Handler_For_Ctrl_Operation --
9477 -------------------------------------
9479 -- Generate:
9481 -- when E : others =>
9482 -- Raise_From_Controlled_Operation (E);
9484 -- or:
9486 -- when others =>
9487 -- raise Program_Error [finalize raised exception];
9489 -- depending on whether Raise_From_Controlled_Operation is available
9491 function Make_Handler_For_Ctrl_Operation
9492 (Loc : Source_Ptr) return Node_Id
9494 E_Occ : Entity_Id;
9495 -- Choice parameter (for the first case above)
9497 Raise_Node : Node_Id;
9498 -- Procedure call or raise statement
9500 begin
9501 -- Standard run-time: add choice parameter E and pass it to
9502 -- Raise_From_Controlled_Operation so that the original exception
9503 -- name and message can be recorded in the exception message for
9504 -- Program_Error.
9506 if RTE_Available (RE_Raise_From_Controlled_Operation) then
9507 E_Occ := Make_Defining_Identifier (Loc, Name_E);
9508 Raise_Node :=
9509 Make_Procedure_Call_Statement (Loc,
9510 Name =>
9511 New_Occurrence_Of
9512 (RTE (RE_Raise_From_Controlled_Operation), Loc),
9513 Parameter_Associations => New_List (
9514 New_Occurrence_Of (E_Occ, Loc)));
9516 -- Restricted run-time: exception messages are not supported
9518 else
9519 E_Occ := Empty;
9520 Raise_Node :=
9521 Make_Raise_Program_Error (Loc,
9522 Reason => PE_Finalize_Raised_Exception);
9523 end if;
9525 return
9526 Make_Implicit_Exception_Handler (Loc,
9527 Exception_Choices => New_List (Make_Others_Choice (Loc)),
9528 Choice_Parameter => E_Occ,
9529 Statements => New_List (Raise_Node));
9530 end Make_Handler_For_Ctrl_Operation;
9532 --------------------
9533 -- Make_Init_Call --
9534 --------------------
9536 function Make_Init_Call
9537 (Obj_Ref : Node_Id;
9538 Typ : Entity_Id) return Node_Id
9540 Loc : constant Source_Ptr := Sloc (Obj_Ref);
9541 Is_Conc : Boolean;
9542 Proc : Entity_Id;
9543 Ref : Node_Id;
9544 Utyp : Entity_Id;
9546 begin
9547 Ref := Obj_Ref;
9549 -- Deal with the type and object reference. Depending on the context, an
9550 -- object reference may need several conversions.
9552 if Is_Concurrent_Type (Typ) then
9553 Is_Conc := True;
9554 Utyp := Corresponding_Record_Type (Typ);
9555 Ref := Convert_Concurrent (Ref, Typ);
9557 elsif Is_Private_Type (Typ)
9558 and then Present (Full_View (Typ))
9559 and then Is_Concurrent_Type (Underlying_Type (Typ))
9560 then
9561 Is_Conc := True;
9562 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
9563 Ref := Convert_Concurrent (Ref, Underlying_Type (Typ));
9565 else
9566 Is_Conc := False;
9567 Utyp := Typ;
9568 end if;
9570 Utyp := Underlying_Type (Base_Type (Utyp));
9571 Set_Assignment_OK (Ref);
9573 -- Deal with untagged derivation of private views
9575 if Is_Untagged_Derivation (Typ) and then not Is_Conc then
9576 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
9577 Ref := Unchecked_Convert_To (Utyp, Ref);
9579 -- The following is to prevent problems with UC see 1.156 RH ???
9581 Set_Assignment_OK (Ref);
9582 end if;
9584 -- If the underlying_type is a subtype, then we are dealing with the
9585 -- completion of a private type. We need to access the base type and
9586 -- generate a conversion to it.
9588 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
9589 pragma Assert (Is_Private_Type (Typ));
9590 Utyp := Base_Type (Utyp);
9591 Ref := Unchecked_Convert_To (Utyp, Ref);
9592 end if;
9594 -- The underlying type may not be present due to a missing full view.
9595 -- In this case freezing did not take place and there is no suitable
9596 -- [Deep_]Initialize primitive to call.
9598 if No (Utyp) then
9599 return Empty;
9600 end if;
9602 -- Select the appropriate version of initialize
9604 if Has_Controlled_Component (Utyp) then
9605 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
9606 else
9607 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
9608 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
9609 end if;
9611 -- The object reference may need another conversion depending on the
9612 -- type of the formal and that of the actual.
9614 Ref := Convert_View (Proc, Ref);
9616 -- Generate:
9617 -- [Deep_]Initialize (Ref);
9619 return
9620 Make_Procedure_Call_Statement (Loc,
9621 Name => New_Occurrence_Of (Proc, Loc),
9622 Parameter_Associations => New_List (Ref));
9623 end Make_Init_Call;
9625 ------------------------------
9626 -- Make_Local_Deep_Finalize --
9627 ------------------------------
9629 function Make_Local_Deep_Finalize
9630 (Typ : Entity_Id;
9631 Nam : Entity_Id) return Node_Id
9633 Loc : constant Source_Ptr := Sloc (Typ);
9634 Formals : List_Id;
9636 begin
9637 Formals := New_List (
9639 -- V : in out Typ
9641 Make_Parameter_Specification (Loc,
9642 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
9643 In_Present => True,
9644 Out_Present => True,
9645 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
9647 -- F : Boolean := True
9649 Make_Parameter_Specification (Loc,
9650 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
9651 Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc),
9652 Expression => New_Occurrence_Of (Standard_True, Loc)));
9654 -- Add the necessary number of counters to represent the initialization
9655 -- state of an object.
9657 return
9658 Make_Subprogram_Body (Loc,
9659 Specification =>
9660 Make_Procedure_Specification (Loc,
9661 Defining_Unit_Name => Nam,
9662 Parameter_Specifications => Formals),
9664 Declarations => No_List,
9666 Handled_Statement_Sequence =>
9667 Make_Handled_Sequence_Of_Statements (Loc,
9668 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
9669 end Make_Local_Deep_Finalize;
9671 ------------------------------------
9672 -- Make_Set_Finalize_Address_Call --
9673 ------------------------------------
9675 function Make_Set_Finalize_Address_Call
9676 (Loc : Source_Ptr;
9677 Ptr_Typ : Entity_Id) return Node_Id
9679 -- It is possible for Ptr_Typ to be a partial view, if the access type
9680 -- is a full view declared in the private part of a nested package, and
9681 -- the finalization actions take place when completing analysis of the
9682 -- enclosing unit. For this reason use Underlying_Type twice below.
9684 Desig_Typ : constant Entity_Id :=
9685 Available_View
9686 (Designated_Type (Underlying_Type (Ptr_Typ)));
9687 Fin_Addr : constant Entity_Id := Finalize_Address (Desig_Typ);
9688 Fin_Mas : constant Entity_Id :=
9689 Finalization_Master (Underlying_Type (Ptr_Typ));
9691 begin
9692 -- Both the finalization master and primitive Finalize_Address must be
9693 -- available.
9695 pragma Assert (Present (Fin_Addr) and Present (Fin_Mas));
9697 -- Generate:
9698 -- Set_Finalize_Address
9699 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
9701 return
9702 Make_Procedure_Call_Statement (Loc,
9703 Name =>
9704 New_Occurrence_Of (RTE (RE_Set_Finalize_Address), Loc),
9705 Parameter_Associations => New_List (
9706 New_Occurrence_Of (Fin_Mas, Loc),
9708 Make_Attribute_Reference (Loc,
9709 Prefix => New_Occurrence_Of (Fin_Addr, Loc),
9710 Attribute_Name => Name_Unrestricted_Access)));
9711 end Make_Set_Finalize_Address_Call;
9713 --------------------------
9714 -- Make_Transient_Block --
9715 --------------------------
9717 function Make_Transient_Block
9718 (Loc : Source_Ptr;
9719 Action : Node_Id;
9720 Par : Node_Id) return Node_Id
9722 Decls : constant List_Id := New_List;
9723 Instrs : constant List_Id := New_List (Action);
9724 Block : Node_Id;
9725 Insert : Node_Id;
9727 begin
9728 -- Case where only secondary stack use is involved
9730 if Uses_Sec_Stack (Current_Scope)
9731 and then Nkind (Action) /= N_Simple_Return_Statement
9732 and then Nkind (Par) /= N_Exception_Handler
9733 then
9734 declare
9735 S : Entity_Id;
9737 begin
9738 S := Scope (Current_Scope);
9739 loop
9740 -- At the outer level, no need to release the sec stack
9742 if S = Standard_Standard then
9743 Set_Uses_Sec_Stack (Current_Scope, False);
9744 exit;
9746 -- In a function, only release the sec stack if the function
9747 -- does not return on the sec stack otherwise the result may
9748 -- be lost. The caller is responsible for releasing.
9750 elsif Ekind (S) = E_Function then
9751 Set_Uses_Sec_Stack (Current_Scope, False);
9753 if not Requires_Transient_Scope (Etype (S)) then
9754 Set_Uses_Sec_Stack (S, True);
9755 Check_Restriction (No_Secondary_Stack, Action);
9756 end if;
9758 exit;
9760 -- In a loop or entry we should install a block encompassing
9761 -- all the construct. For now just release right away.
9763 elsif Ekind_In (S, E_Entry, E_Loop) then
9764 exit;
9766 -- In a procedure or a block, release the sec stack on exit
9767 -- from the construct. Note that an exception handler with a
9768 -- choice parameter requires a declarative region in the form
9769 -- of a block. The block does not physically manifest in the
9770 -- tree as it only serves as a scope. Do not consider such a
9771 -- block because it will never release the sec stack.
9773 -- ??? Memory leak can be created by recursive calls
9775 elsif Ekind (S) = E_Procedure
9776 or else (Ekind (S) = E_Block
9777 and then not Is_Exception_Handler (S))
9778 then
9779 Set_Uses_Sec_Stack (Current_Scope, False);
9780 Set_Uses_Sec_Stack (S, True);
9781 Check_Restriction (No_Secondary_Stack, Action);
9782 exit;
9784 else
9785 S := Scope (S);
9786 end if;
9787 end loop;
9788 end;
9789 end if;
9791 -- Create the transient block. Set the parent now since the block itself
9792 -- is not part of the tree. The current scope is the E_Block entity
9793 -- that has been pushed by Establish_Transient_Scope.
9795 pragma Assert (Ekind (Current_Scope) = E_Block);
9796 Block :=
9797 Make_Block_Statement (Loc,
9798 Identifier => New_Occurrence_Of (Current_Scope, Loc),
9799 Declarations => Decls,
9800 Handled_Statement_Sequence =>
9801 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
9802 Has_Created_Identifier => True);
9803 Set_Parent (Block, Par);
9805 -- Insert actions stuck in the transient scopes as well as all freezing
9806 -- nodes needed by those actions. Do not insert cleanup actions here,
9807 -- they will be transferred to the newly created block.
9809 Insert_Actions_In_Scope_Around
9810 (Action, Clean => False, Manage_SS => False);
9812 Insert := Prev (Action);
9813 if Present (Insert) then
9814 Freeze_All (First_Entity (Current_Scope), Insert);
9815 end if;
9817 -- Transfer cleanup actions to the newly created block
9819 declare
9820 Cleanup_Actions : List_Id
9821 renames Scope_Stack.Table (Scope_Stack.Last).
9822 Actions_To_Be_Wrapped (Cleanup);
9823 begin
9824 Set_Cleanup_Actions (Block, Cleanup_Actions);
9825 Cleanup_Actions := No_List;
9826 end;
9828 -- When the transient scope was established, we pushed the entry for the
9829 -- transient scope onto the scope stack, so that the scope was active
9830 -- for the installation of finalizable entities etc. Now we must remove
9831 -- this entry, since we have constructed a proper block.
9833 Pop_Scope;
9835 return Block;
9836 end Make_Transient_Block;
9838 ------------------------
9839 -- Node_To_Be_Wrapped --
9840 ------------------------
9842 function Node_To_Be_Wrapped return Node_Id is
9843 begin
9844 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
9845 end Node_To_Be_Wrapped;
9847 ----------------------------
9848 -- Set_Node_To_Be_Wrapped --
9849 ----------------------------
9851 procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
9852 begin
9853 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
9854 end Set_Node_To_Be_Wrapped;
9856 ----------------------------
9857 -- Store_Actions_In_Scope --
9858 ----------------------------
9860 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id) is
9861 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
9862 Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK);
9864 begin
9865 if No (Actions) then
9866 Actions := L;
9868 if Is_List_Member (SE.Node_To_Be_Wrapped) then
9869 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
9870 else
9871 Set_Parent (L, SE.Node_To_Be_Wrapped);
9872 end if;
9874 Analyze_List (L);
9876 elsif AK = Before then
9877 Insert_List_After_And_Analyze (Last (Actions), L);
9879 else
9880 Insert_List_Before_And_Analyze (First (Actions), L);
9881 end if;
9882 end Store_Actions_In_Scope;
9884 ----------------------------------
9885 -- Store_After_Actions_In_Scope --
9886 ----------------------------------
9888 procedure Store_After_Actions_In_Scope (L : List_Id) is
9889 begin
9890 Store_Actions_In_Scope (After, L);
9891 end Store_After_Actions_In_Scope;
9893 -----------------------------------
9894 -- Store_Before_Actions_In_Scope --
9895 -----------------------------------
9897 procedure Store_Before_Actions_In_Scope (L : List_Id) is
9898 begin
9899 Store_Actions_In_Scope (Before, L);
9900 end Store_Before_Actions_In_Scope;
9902 -----------------------------------
9903 -- Store_Cleanup_Actions_In_Scope --
9904 -----------------------------------
9906 procedure Store_Cleanup_Actions_In_Scope (L : List_Id) is
9907 begin
9908 Store_Actions_In_Scope (Cleanup, L);
9909 end Store_Cleanup_Actions_In_Scope;
9911 --------------------------------
9912 -- Wrap_Transient_Declaration --
9913 --------------------------------
9915 -- If a transient scope has been established during the processing of the
9916 -- Expression of an Object_Declaration, it is not possible to wrap the
9917 -- declaration into a transient block as usual case, otherwise the object
9918 -- would be itself declared in the wrong scope. Therefore, all entities (if
9919 -- any) defined in the transient block are moved to the proper enclosing
9920 -- scope. Furthermore, if they are controlled variables they are finalized
9921 -- right after the declaration. The finalization list of the transient
9922 -- scope is defined as a renaming of the enclosing one so during their
9923 -- initialization they will be attached to the proper finalization list.
9924 -- For instance, the following declaration :
9926 -- X : Typ := F (G (A), G (B));
9928 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
9929 -- is expanded into :
9931 -- X : Typ := [ complex Expression-Action ];
9932 -- [Deep_]Finalize (_v1);
9933 -- [Deep_]Finalize (_v2);
9935 procedure Wrap_Transient_Declaration (N : Node_Id) is
9936 Curr_S : Entity_Id;
9937 Encl_S : Entity_Id;
9939 begin
9940 Curr_S := Current_Scope;
9941 Encl_S := Scope (Curr_S);
9943 -- Insert all actions including cleanup generated while analyzing or
9944 -- expanding the transient context back into the tree. Manage the
9945 -- secondary stack when the object declaration appears in a library
9946 -- level package [body].
9948 Insert_Actions_In_Scope_Around
9949 (N => N,
9950 Clean => True,
9951 Manage_SS =>
9952 Uses_Sec_Stack (Curr_S)
9953 and then Nkind (N) = N_Object_Declaration
9954 and then Ekind_In (Encl_S, E_Package, E_Package_Body)
9955 and then Is_Library_Level_Entity (Encl_S));
9956 Pop_Scope;
9958 -- Relocate local entities declared within the transient scope to the
9959 -- enclosing scope. This action sets their Is_Public flag accordingly.
9961 Transfer_Entities (Curr_S, Encl_S);
9963 -- Mark the enclosing dynamic scope to ensure that the secondary stack
9964 -- is properly released upon exiting the said scope.
9966 if Uses_Sec_Stack (Curr_S) then
9967 Curr_S := Enclosing_Dynamic_Scope (Curr_S);
9969 -- Do not mark a function that returns on the secondary stack as the
9970 -- reclamation is done by the caller.
9972 if Ekind (Curr_S) = E_Function
9973 and then Requires_Transient_Scope (Etype (Curr_S))
9974 then
9975 null;
9977 -- Otherwise mark the enclosing dynamic scope
9979 else
9980 Set_Uses_Sec_Stack (Curr_S);
9981 Check_Restriction (No_Secondary_Stack, N);
9982 end if;
9983 end if;
9984 end Wrap_Transient_Declaration;
9986 -------------------------------
9987 -- Wrap_Transient_Expression --
9988 -------------------------------
9990 procedure Wrap_Transient_Expression (N : Node_Id) is
9991 Loc : constant Source_Ptr := Sloc (N);
9992 Expr : Node_Id := Relocate_Node (N);
9993 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
9994 Typ : constant Entity_Id := Etype (N);
9996 begin
9997 -- Generate:
9999 -- Temp : Typ;
10000 -- declare
10001 -- M : constant Mark_Id := SS_Mark;
10002 -- procedure Finalizer is ... (See Build_Finalizer)
10004 -- begin
10005 -- Temp := <Expr>; -- general case
10006 -- Temp := (if <Expr> then True else False); -- boolean case
10008 -- at end
10009 -- Finalizer;
10010 -- end;
10012 -- A special case is made for Boolean expressions so that the back-end
10013 -- knows to generate a conditional branch instruction, if running with
10014 -- -fpreserve-control-flow. This ensures that a control flow change
10015 -- signalling the decision outcome occurs before the cleanup actions.
10017 if Opt.Suppress_Control_Flow_Optimizations
10018 and then Is_Boolean_Type (Typ)
10019 then
10020 Expr :=
10021 Make_If_Expression (Loc,
10022 Expressions => New_List (
10023 Expr,
10024 New_Occurrence_Of (Standard_True, Loc),
10025 New_Occurrence_Of (Standard_False, Loc)));
10026 end if;
10028 Insert_Actions (N, New_List (
10029 Make_Object_Declaration (Loc,
10030 Defining_Identifier => Temp,
10031 Object_Definition => New_Occurrence_Of (Typ, Loc)),
10033 Make_Transient_Block (Loc,
10034 Action =>
10035 Make_Assignment_Statement (Loc,
10036 Name => New_Occurrence_Of (Temp, Loc),
10037 Expression => Expr),
10038 Par => Parent (N))));
10040 Rewrite (N, New_Occurrence_Of (Temp, Loc));
10041 Analyze_And_Resolve (N, Typ);
10042 end Wrap_Transient_Expression;
10044 ------------------------------
10045 -- Wrap_Transient_Statement --
10046 ------------------------------
10048 procedure Wrap_Transient_Statement (N : Node_Id) is
10049 Loc : constant Source_Ptr := Sloc (N);
10050 New_Stmt : constant Node_Id := Relocate_Node (N);
10052 begin
10053 -- Generate:
10054 -- declare
10055 -- M : constant Mark_Id := SS_Mark;
10056 -- procedure Finalizer is ... (See Build_Finalizer)
10058 -- begin
10059 -- <New_Stmt>;
10061 -- at end
10062 -- Finalizer;
10063 -- end;
10065 Rewrite (N,
10066 Make_Transient_Block (Loc,
10067 Action => New_Stmt,
10068 Par => Parent (N)));
10070 -- With the scope stack back to normal, we can call analyze on the
10071 -- resulting block. At this point, the transient scope is being
10072 -- treated like a perfectly normal scope, so there is nothing
10073 -- special about it.
10075 -- Note: Wrap_Transient_Statement is called with the node already
10076 -- analyzed (i.e. Analyzed (N) is True). This is important, since
10077 -- otherwise we would get a recursive processing of the node when
10078 -- we do this Analyze call.
10080 Analyze (N);
10081 end Wrap_Transient_Statement;
10083 end Exp_Ch7;