OSDN Git Service

* gcc-interface/trans.c (Attribute_to_gnu) <Attr_Last_Bit>: Add kludge
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_ch7.adb
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-2012, 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 ------------------------------------------------------------------------------
25
26 --  This package contains virtually all expansion mechanisms related to
27 --    - controlled types
28 --    - transient scopes
29
30 with Atree;    use Atree;
31 with Debug;    use Debug;
32 with Einfo;    use Einfo;
33 with Elists;   use Elists;
34 with Errout;   use Errout;
35 with Exp_Ch6;  use Exp_Ch6;
36 with Exp_Ch9;  use Exp_Ch9;
37 with Exp_Ch11; use Exp_Ch11;
38 with Exp_Dbug; use Exp_Dbug;
39 with Exp_Dist; use Exp_Dist;
40 with Exp_Disp; use Exp_Disp;
41 with Exp_Tss;  use Exp_Tss;
42 with Exp_Util; use Exp_Util;
43 with Freeze;   use Freeze;
44 with Lib;      use Lib;
45 with Nlists;   use Nlists;
46 with Nmake;    use Nmake;
47 with Opt;      use Opt;
48 with Output;   use Output;
49 with Restrict; use Restrict;
50 with Rident;   use Rident;
51 with Rtsfind;  use Rtsfind;
52 with Sinfo;    use Sinfo;
53 with Sem;      use Sem;
54 with Sem_Aux;  use Sem_Aux;
55 with Sem_Ch3;  use Sem_Ch3;
56 with Sem_Ch7;  use Sem_Ch7;
57 with Sem_Ch8;  use Sem_Ch8;
58 with Sem_Res;  use Sem_Res;
59 with Sem_Util; use Sem_Util;
60 with Snames;   use Snames;
61 with Stand;    use Stand;
62 with Targparm; use Targparm;
63 with Tbuild;   use Tbuild;
64 with Ttypes;   use Ttypes;
65 with Uintp;    use Uintp;
66
67 package body Exp_Ch7 is
68
69    --------------------------------
70    -- Transient Scope Management --
71    --------------------------------
72
73    --  A transient scope is created when temporary objects are created by the
74    --  compiler. These temporary objects are allocated on the secondary stack
75    --  and the transient scope is responsible for finalizing the object when
76    --  appropriate and reclaiming the memory at the right time. The temporary
77    --  objects are generally the objects allocated to store the result of a
78    --  function returning an unconstrained or a tagged value. Expressions
79    --  needing to be wrapped in a transient scope (functions calls returning
80    --  unconstrained or tagged values) may appear in 3 different contexts which
81    --  lead to 3 different kinds of transient scope expansion:
82
83    --   1. In a simple statement (procedure call, assignment, ...). In this
84    --      case the instruction is wrapped into a transient block. See
85    --      Wrap_Transient_Statement for details.
86
87    --   2. In an expression of a control structure (test in a IF statement,
88    --      expression in a CASE statement, ...). See Wrap_Transient_Expression
89    --      for details.
90
91    --   3. In a expression of an object_declaration. No wrapping is possible
92    --      here, so the finalization actions, if any, are done right after the
93    --      declaration and the secondary stack deallocation is done in the
94    --      proper enclosing scope. See Wrap_Transient_Declaration for details.
95
96    --  Note about functions returning tagged types: it has been decided to
97    --  always allocate their result in the secondary stack, even though is not
98    --  absolutely mandatory when the tagged type is constrained because the
99    --  caller knows the size of the returned object and thus could allocate the
100    --  result in the primary stack. An exception to this is when the function
101    --  builds its result in place, as is done for functions with inherently
102    --  limited result types for Ada 2005. In that case, certain callers may
103    --  pass the address of a constrained object as the target object for the
104    --  function result.
105
106    --  By allocating tagged results in the secondary stack a number of
107    --  implementation difficulties are avoided:
108
109    --    - If it is a dispatching function call, the computation of the size of
110    --      the result is possible but complex from the outside.
111
112    --    - If the returned type is controlled, the assignment of the returned
113    --      value to the anonymous object involves an Adjust, and we have no
114    --      easy way to access the anonymous object created by the back end.
115
116    --    - If the returned type is class-wide, this is an unconstrained type
117    --      anyway.
118
119    --  Furthermore, the small loss in efficiency which is the result of this
120    --  decision is not such a big deal because functions returning tagged types
121    --  are not as common in practice compared to functions returning access to
122    --  a tagged type.
123
124    --------------------------------------------------
125    -- Transient Blocks and Finalization Management --
126    --------------------------------------------------
127
128    function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id;
129    --  N is a node which may generate a transient scope. Loop over the parent
130    --  pointers of N until it find the appropriate node to wrap. If it returns
131    --  Empty, it means that no transient scope is needed in this context.
132
133    procedure Insert_Actions_In_Scope_Around (N : Node_Id);
134    --  Insert the before-actions kept in the scope stack before N, and the
135    --  after-actions after N, which must be a member of a list.
136
137    function Make_Transient_Block
138      (Loc    : Source_Ptr;
139       Action : Node_Id;
140       Par    : Node_Id) return Node_Id;
141    --  Action is a single statement or object declaration. Par is the proper
142    --  parent of the generated block. Create a transient block whose name is
143    --  the current scope and the only handled statement is Action. If Action
144    --  involves controlled objects or secondary stack usage, the corresponding
145    --  cleanup actions are performed at the end of the block.
146
147    procedure Set_Node_To_Be_Wrapped (N : Node_Id);
148    --  Set the field Node_To_Be_Wrapped of the current scope
149
150    --  ??? The entire comment needs to be rewritten
151
152    -----------------------------
153    -- Finalization Management --
154    -----------------------------
155
156    --  This part describe how Initialization/Adjustment/Finalization procedures
157    --  are generated and called. Two cases must be considered, types that are
158    --  Controlled (Is_Controlled flag set) and composite types that contain
159    --  controlled components (Has_Controlled_Component flag set). In the first
160    --  case the procedures to call are the user-defined primitive operations
161    --  Initialize/Adjust/Finalize. In the second case, GNAT generates
162    --  Deep_Initialize, Deep_Adjust and Deep_Finalize that are in charge
163    --  of calling the former procedures on the controlled components.
164
165    --  For records with Has_Controlled_Component set, a hidden "controller"
166    --  component is inserted. This controller component contains its own
167    --  finalization list on which all controlled components are attached
168    --  creating an indirection on the upper-level Finalization list. This
169    --  technique facilitates the management of objects whose number of
170    --  controlled components changes during execution. This controller
171    --  component is itself controlled and is attached to the upper-level
172    --  finalization chain. Its adjust primitive is in charge of calling adjust
173    --  on the components and adjusting the finalization pointer to match their
174    --  new location (see a-finali.adb).
175
176    --  It is not possible to use a similar technique for arrays that have
177    --  Has_Controlled_Component set. In this case, deep procedures are
178    --  generated that call initialize/adjust/finalize + attachment or
179    --  detachment on the finalization list for all component.
180
181    --  Initialize calls: they are generated for declarations or dynamic
182    --  allocations of Controlled objects with no initial value. They are always
183    --  followed by an attachment to the current Finalization Chain. For the
184    --  dynamic allocation case this the chain attached to the scope of the
185    --  access type definition otherwise, this is the chain of the current
186    --  scope.
187
188    --  Adjust Calls: They are generated on 2 occasions: (1) for declarations
189    --  or dynamic allocations of Controlled objects with an initial value.
190    --  (2) after an assignment. In the first case they are followed by an
191    --  attachment to the final chain, in the second case they are not.
192
193    --  Finalization Calls: They are generated on (1) scope exit, (2)
194    --  assignments, (3) unchecked deallocations. In case (3) they have to
195    --  be detached from the final chain, in case (2) they must not and in
196    --  case (1) this is not important since we are exiting the scope anyway.
197
198    --  Other details:
199
200    --    Type extensions will have a new record controller at each derivation
201    --    level containing controlled components. The record controller for
202    --    the parent/ancestor is attached to the finalization list of the
203    --    extension's record controller (i.e. the parent is like a component
204    --    of the extension).
205
206    --    For types that are both Is_Controlled and Has_Controlled_Components,
207    --    the record controller and the object itself are handled separately.
208    --    It could seem simpler to attach the object at the end of its record
209    --    controller but this would not tackle view conversions properly.
210
211    --    A classwide type can always potentially have controlled components
212    --    but the record controller of the corresponding actual type may not
213    --    be known at compile time so the dispatch table contains a special
214    --    field that allows to compute the offset of the record controller
215    --    dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
216
217    --  Here is a simple example of the expansion of a controlled block :
218
219    --    declare
220    --       X : Controlled;
221    --       Y : Controlled := Init;
222    --
223    --       type R is record
224    --          C : Controlled;
225    --       end record;
226    --       W : R;
227    --       Z : R := (C => X);
228
229    --    begin
230    --       X := Y;
231    --       W := Z;
232    --    end;
233    --
234    --  is expanded into
235    --
236    --    declare
237    --       _L : System.FI.Finalizable_Ptr;
238
239    --       procedure _Clean is
240    --       begin
241    --          Abort_Defer;
242    --          System.FI.Finalize_List (_L);
243    --          Abort_Undefer;
244    --       end _Clean;
245
246    --       X : Controlled;
247    --       begin
248    --          Abort_Defer;
249    --          Initialize (X);
250    --          Attach_To_Final_List (_L, Finalizable (X), 1);
251    --       at end: Abort_Undefer;
252    --       Y : Controlled := Init;
253    --       Adjust (Y);
254    --       Attach_To_Final_List (_L, Finalizable (Y), 1);
255    --
256    --       type R is record
257    --          C : Controlled;
258    --       end record;
259    --       W : R;
260    --       begin
261    --          Abort_Defer;
262    --          Deep_Initialize (W, _L, 1);
263    --       at end: Abort_Under;
264    --       Z : R := (C => X);
265    --       Deep_Adjust (Z, _L, 1);
266
267    --    begin
268    --       _Assign (X, Y);
269    --       Deep_Finalize (W, False);
270    --       <save W's final pointers>
271    --       W := Z;
272    --       <restore W's final pointers>
273    --       Deep_Adjust (W, _L, 0);
274    --    at end
275    --       _Clean;
276    --    end;
277
278    type Final_Primitives is
279      (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
280    --  This enumeration type is defined in order to ease sharing code for
281    --  building finalization procedures for composite types.
282
283    Name_Of      : constant array (Final_Primitives) of Name_Id :=
284                     (Initialize_Case => Name_Initialize,
285                      Adjust_Case     => Name_Adjust,
286                      Finalize_Case   => Name_Finalize,
287                      Address_Case    => Name_Finalize_Address);
288    Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
289                     (Initialize_Case => TSS_Deep_Initialize,
290                      Adjust_Case     => TSS_Deep_Adjust,
291                      Finalize_Case   => TSS_Deep_Finalize,
292                      Address_Case    => TSS_Finalize_Address);
293
294    procedure Build_Array_Deep_Procs (Typ : Entity_Id);
295    --  Build the deep Initialize/Adjust/Finalize for a record Typ with
296    --  Has_Controlled_Component set and store them using the TSS mechanism.
297
298    function Build_Cleanup_Statements (N : Node_Id) return List_Id;
299    --  Create the clean up calls for an asynchronous call block, task master,
300    --  protected subprogram body, task allocation block or task body. If the
301    --  context does not contain the above constructs, the routine returns an
302    --  empty list.
303
304    procedure Build_Finalizer
305      (N           : Node_Id;
306       Clean_Stmts : List_Id;
307       Mark_Id     : Entity_Id;
308       Top_Decls   : List_Id;
309       Defer_Abort : Boolean;
310       Fin_Id      : out Entity_Id);
311    --  N may denote an accept statement, block, entry body, package body,
312    --  package spec, protected body, subprogram body, and a task body. Create
313    --  a procedure which contains finalization calls for all controlled objects
314    --  declared in the declarative or statement region of N. The calls are
315    --  built in reverse order relative to the original declarations. In the
316    --  case of a tack body, the routine delays the creation of the finalizer
317    --  until all statements have been moved to the task body procedure.
318    --  Clean_Stmts may contain additional context-dependent code used to abort
319    --  asynchronous calls or complete tasks (see Build_Cleanup_Statements).
320    --  Mark_Id is the secondary stack used in the current context or Empty if
321    --  missing. Top_Decls is the list on which the declaration of the finalizer
322    --  is attached in the non-package case. Defer_Abort indicates that the
323    --  statements passed in perform actions that require abort to be deferred,
324    --  such as for task termination. Fin_Id is the finalizer declaration
325    --  entity.
326
327    procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
328    --  N is a construct which contains a handled sequence of statements, Fin_Id
329    --  is the entity of a finalizer. Create an At_End handler which covers the
330    --  statements of N and calls Fin_Id. If the handled statement sequence has
331    --  an exception handler, the statements will be wrapped in a block to avoid
332    --  unwanted interaction with the new At_End handler.
333
334    procedure Build_Record_Deep_Procs (Typ : Entity_Id);
335    --  Build the deep Initialize/Adjust/Finalize for a record Typ with
336    --  Has_Component_Component set and store them using the TSS mechanism.
337
338    procedure Check_Visibly_Controlled
339      (Prim : Final_Primitives;
340       Typ  : Entity_Id;
341       E    : in out Entity_Id;
342       Cref : in out Node_Id);
343    --  The controlled operation declared for a derived type may not be
344    --  overriding, if the controlled operations of the parent type are hidden,
345    --  for example when the parent is a private type whose full view is
346    --  controlled. For other primitive operations we modify the name of the
347    --  operation to indicate that it is not overriding, but this is not
348    --  possible for Initialize, etc. because they have to be retrievable by
349    --  name. Before generating the proper call to one of these operations we
350    --  check whether Typ is known to be controlled at the point of definition.
351    --  If it is not then we must retrieve the hidden operation of the parent
352    --  and use it instead.  This is one case that might be solved more cleanly
353    --  once Overriding pragmas or declarations are in place.
354
355    function Convert_View
356      (Proc : Entity_Id;
357       Arg  : Node_Id;
358       Ind  : Pos := 1) return Node_Id;
359    --  Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
360    --  argument being passed to it. Ind indicates which formal of procedure
361    --  Proc we are trying to match. This function will, if necessary, generate
362    --  a conversion between the partial and full view of Arg to match the type
363    --  of the formal of Proc, or force a conversion to the class-wide type in
364    --  the case where the operation is abstract.
365
366    function Enclosing_Function (E : Entity_Id) return Entity_Id;
367    --  Given an arbitrary entity, traverse the scope chain looking for the
368    --  first enclosing function. Return Empty if no function was found.
369
370    function Make_Call
371      (Loc        : Source_Ptr;
372       Proc_Id    : Entity_Id;
373       Param      : Node_Id;
374       For_Parent : Boolean := False) return Node_Id;
375    --  Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
376    --  routine [Deep_]Adjust / Finalize and an object parameter, create an
377    --  adjust / finalization call. Flag For_Parent should be set when field
378    --  _parent is being processed.
379
380    function Make_Deep_Proc
381      (Prim  : Final_Primitives;
382       Typ   : Entity_Id;
383       Stmts : List_Id) return Node_Id;
384    --  This function generates the tree for Deep_Initialize, Deep_Adjust or
385    --  Deep_Finalize procedures according to the first parameter, these
386    --  procedures operate on the type Typ. The Stmts parameter gives the body
387    --  of the procedure.
388
389    function Make_Deep_Array_Body
390      (Prim : Final_Primitives;
391       Typ  : Entity_Id) return List_Id;
392    --  This function generates the list of statements for implementing
393    --  Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
394    --  the first parameter, these procedures operate on the array type Typ.
395
396    function Make_Deep_Record_Body
397      (Prim     : Final_Primitives;
398       Typ      : Entity_Id;
399       Is_Local : Boolean := False) return List_Id;
400    --  This function generates the list of statements for implementing
401    --  Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
402    --  the first parameter, these procedures operate on the record type Typ.
403    --  Flag Is_Local is used in conjunction with Deep_Finalize to designate
404    --  whether the inner logic should be dictated by state counters.
405
406    function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
407    --  Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
408    --  Make_Deep_Record_Body. Generate the following statements:
409    --
410    --    declare
411    --       type Acc_Typ is access all Typ;
412    --       for Acc_Typ'Storage_Size use 0;
413    --    begin
414    --       [Deep_]Finalize (Acc_Typ (V).all);
415    --    end;
416
417    ----------------------------
418    -- Build_Array_Deep_Procs --
419    ----------------------------
420
421    procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
422    begin
423       Set_TSS (Typ,
424         Make_Deep_Proc
425           (Prim  => Initialize_Case,
426            Typ   => Typ,
427            Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
428
429       if not Is_Immutably_Limited_Type (Typ) then
430          Set_TSS (Typ,
431            Make_Deep_Proc
432              (Prim  => Adjust_Case,
433               Typ   => Typ,
434               Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
435       end if;
436
437       --  Do not generate Deep_Finalize and Finalize_Address if finalization is
438       --  suppressed since these routine will not be used.
439
440       if not Restriction_Active (No_Finalization) then
441          Set_TSS (Typ,
442            Make_Deep_Proc
443              (Prim  => Finalize_Case,
444               Typ   => Typ,
445               Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
446
447          --  Create TSS primitive Finalize_Address for non-VM targets. JVM and
448          --  .NET do not support address arithmetic and unchecked conversions.
449
450          if VM_Target = No_VM then
451             Set_TSS (Typ,
452               Make_Deep_Proc
453                 (Prim  => Address_Case,
454                  Typ   => Typ,
455                  Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
456          end if;
457       end if;
458    end Build_Array_Deep_Procs;
459
460    ------------------------------
461    -- Build_Cleanup_Statements --
462    ------------------------------
463
464    function Build_Cleanup_Statements (N : Node_Id) return List_Id is
465       Is_Asynchronous_Call : constant Boolean :=
466                                Nkind (N) = N_Block_Statement
467                                  and then Is_Asynchronous_Call_Block (N);
468       Is_Master            : constant Boolean :=
469                                Nkind (N) /= N_Entry_Body
470                                  and then Is_Task_Master (N);
471       Is_Protected_Body    : constant Boolean :=
472                                Nkind (N) = N_Subprogram_Body
473                                  and then Is_Protected_Subprogram_Body (N);
474       Is_Task_Allocation   : constant Boolean :=
475                                Nkind (N) = N_Block_Statement
476                                  and then Is_Task_Allocation_Block (N);
477       Is_Task_Body         : constant Boolean :=
478                                Nkind (Original_Node (N)) = N_Task_Body;
479
480       Loc   : constant Source_Ptr := Sloc (N);
481       Stmts : constant List_Id    := New_List;
482
483    begin
484       if Is_Task_Body then
485          if Restricted_Profile then
486             Append_To (Stmts,
487               Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
488          else
489             Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
490          end if;
491
492       elsif Is_Master then
493          if Restriction_Active (No_Task_Hierarchy) = False then
494             Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
495          end if;
496
497       --  Add statements to unlock the protected object parameter and to
498       --  undefer abort. If the context is a protected procedure and the object
499       --  has entries, call the entry service routine.
500
501       --  NOTE: The generated code references _object, a parameter to the
502       --  procedure.
503
504       elsif Is_Protected_Body then
505          declare
506             Spec      : constant Node_Id := Parent (Corresponding_Spec (N));
507             Conc_Typ  : Entity_Id;
508             Nam       : Node_Id;
509             Param     : Node_Id;
510             Param_Typ : Entity_Id;
511
512          begin
513             --  Find the _object parameter representing the protected object
514
515             Param := First (Parameter_Specifications (Spec));
516             loop
517                Param_Typ := Etype (Parameter_Type (Param));
518
519                if Ekind (Param_Typ) = E_Record_Type then
520                   Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
521                end if;
522
523                exit when No (Param) or else Present (Conc_Typ);
524                Next (Param);
525             end loop;
526
527             pragma Assert (Present (Param));
528
529             --  If the associated protected object has entries, a protected
530             --  procedure has to service entry queues. In this case generate:
531
532             --    Service_Entries (_object._object'Access);
533
534             if Nkind (Specification (N)) = N_Procedure_Specification
535               and then Has_Entries (Conc_Typ)
536             then
537                case Corresponding_Runtime_Package (Conc_Typ) is
538                   when System_Tasking_Protected_Objects_Entries =>
539                      Nam := New_Reference_To (RTE (RE_Service_Entries), Loc);
540
541                   when System_Tasking_Protected_Objects_Single_Entry =>
542                      Nam := New_Reference_To (RTE (RE_Service_Entry), Loc);
543
544                   when others =>
545                      raise Program_Error;
546                end case;
547
548                Append_To (Stmts,
549                  Make_Procedure_Call_Statement (Loc,
550                    Name                   => Nam,
551                    Parameter_Associations => New_List (
552                      Make_Attribute_Reference (Loc,
553                        Prefix         =>
554                          Make_Selected_Component (Loc,
555                            Prefix        => New_Reference_To (
556                              Defining_Identifier (Param), Loc),
557                            Selector_Name =>
558                              Make_Identifier (Loc, Name_uObject)),
559                        Attribute_Name => Name_Unchecked_Access))));
560
561             else
562                --  Generate:
563                --    Unlock (_object._object'Access);
564
565                case Corresponding_Runtime_Package (Conc_Typ) is
566                   when System_Tasking_Protected_Objects_Entries =>
567                      Nam := New_Reference_To (RTE (RE_Unlock_Entries), Loc);
568
569                   when System_Tasking_Protected_Objects_Single_Entry =>
570                      Nam := New_Reference_To (RTE (RE_Unlock_Entry), Loc);
571
572                   when System_Tasking_Protected_Objects =>
573                      Nam := New_Reference_To (RTE (RE_Unlock), Loc);
574
575                   when others =>
576                      raise Program_Error;
577                end case;
578
579                Append_To (Stmts,
580                  Make_Procedure_Call_Statement (Loc,
581                    Name                   => Nam,
582                    Parameter_Associations => New_List (
583                      Make_Attribute_Reference (Loc,
584                        Prefix         =>
585                          Make_Selected_Component (Loc,
586                            Prefix        =>
587                              New_Reference_To
588                                (Defining_Identifier (Param), Loc),
589                            Selector_Name =>
590                              Make_Identifier (Loc, Name_uObject)),
591                        Attribute_Name => Name_Unchecked_Access))));
592             end if;
593
594             --  Generate:
595             --    Abort_Undefer;
596
597             if Abort_Allowed then
598                Append_To (Stmts,
599                  Make_Procedure_Call_Statement (Loc,
600                    Name                   =>
601                      New_Reference_To (RTE (RE_Abort_Undefer), Loc),
602                    Parameter_Associations => Empty_List));
603             end if;
604          end;
605
606       --  Add a call to Expunge_Unactivated_Tasks for dynamically allocated
607       --  tasks. Other unactivated tasks are completed by Complete_Task or
608       --  Complete_Master.
609
610       --  NOTE: The generated code references _chain, a local object
611
612       elsif Is_Task_Allocation then
613
614          --  Generate:
615          --     Expunge_Unactivated_Tasks (_chain);
616
617          --  where _chain is the list of tasks created by the allocator but not
618          --  yet activated. This list will be empty unless the block completes
619          --  abnormally.
620
621          Append_To (Stmts,
622            Make_Procedure_Call_Statement (Loc,
623              Name =>
624                New_Reference_To
625                  (RTE (RE_Expunge_Unactivated_Tasks), Loc),
626              Parameter_Associations => New_List (
627                New_Reference_To (Activation_Chain_Entity (N), Loc))));
628
629       --  Attempt to cancel an asynchronous entry call whenever the block which
630       --  contains the abortable part is exited.
631
632       --  NOTE: The generated code references Cnn, a local object
633
634       elsif Is_Asynchronous_Call then
635          declare
636             Cancel_Param : constant Entity_Id :=
637                              Entry_Cancel_Parameter (Entity (Identifier (N)));
638
639          begin
640             --  If it is of type Communication_Block, this must be a protected
641             --  entry call. Generate:
642
643             --    if Enqueued (Cancel_Param) then
644             --       Cancel_Protected_Entry_Call (Cancel_Param);
645             --    end if;
646
647             if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
648                Append_To (Stmts,
649                  Make_If_Statement (Loc,
650                    Condition =>
651                      Make_Function_Call (Loc,
652                        Name                   =>
653                          New_Reference_To (RTE (RE_Enqueued), Loc),
654                        Parameter_Associations => New_List (
655                          New_Reference_To (Cancel_Param, Loc))),
656
657                    Then_Statements => New_List (
658                      Make_Procedure_Call_Statement (Loc,
659                        Name =>
660                          New_Reference_To
661                            (RTE (RE_Cancel_Protected_Entry_Call), Loc),
662                          Parameter_Associations => New_List (
663                            New_Reference_To (Cancel_Param, Loc))))));
664
665             --  Asynchronous delay, generate:
666             --    Cancel_Async_Delay (Cancel_Param);
667
668             elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
669                Append_To (Stmts,
670                  Make_Procedure_Call_Statement (Loc,
671                    Name                   =>
672                      New_Reference_To (RTE (RE_Cancel_Async_Delay), Loc),
673                    Parameter_Associations => New_List (
674                      Make_Attribute_Reference (Loc,
675                        Prefix         =>
676                          New_Reference_To (Cancel_Param, Loc),
677                        Attribute_Name => Name_Unchecked_Access))));
678
679             --  Task entry call, generate:
680             --    Cancel_Task_Entry_Call (Cancel_Param);
681
682             else
683                Append_To (Stmts,
684                  Make_Procedure_Call_Statement (Loc,
685                    Name                   =>
686                      New_Reference_To (RTE (RE_Cancel_Task_Entry_Call), Loc),
687                    Parameter_Associations => New_List (
688                      New_Reference_To (Cancel_Param, Loc))));
689             end if;
690          end;
691       end if;
692
693       return Stmts;
694    end Build_Cleanup_Statements;
695
696    -----------------------------
697    -- Build_Controlling_Procs --
698    -----------------------------
699
700    procedure Build_Controlling_Procs (Typ : Entity_Id) is
701    begin
702       if Is_Array_Type (Typ) then
703          Build_Array_Deep_Procs (Typ);
704       else pragma Assert (Is_Record_Type (Typ));
705          Build_Record_Deep_Procs (Typ);
706       end if;
707    end Build_Controlling_Procs;
708
709    -----------------------------
710    -- Build_Exception_Handler --
711    -----------------------------
712
713    function Build_Exception_Handler
714      (Data        : Finalization_Exception_Data;
715       For_Library : Boolean := False) return Node_Id
716    is
717       Actuals      : List_Id;
718       Proc_To_Call : Entity_Id;
719
720    begin
721       pragma Assert (Present (Data.E_Id));
722       pragma Assert (Present (Data.Raised_Id));
723
724       --  Generate:
725       --    Get_Current_Excep.all.all
726
727       Actuals := New_List (
728         Make_Explicit_Dereference (Data.Loc,
729           Prefix =>
730             Make_Function_Call (Data.Loc,
731               Name =>
732                 Make_Explicit_Dereference (Data.Loc,
733                   Prefix =>
734                     New_Reference_To (RTE (RE_Get_Current_Excep),
735                                       Data.Loc)))));
736
737       if For_Library and then not Restricted_Profile then
738          Proc_To_Call := RTE (RE_Save_Library_Occurrence);
739
740       else
741          Proc_To_Call := RTE (RE_Save_Occurrence);
742          Prepend_To (Actuals, New_Reference_To (Data.E_Id, Data.Loc));
743       end if;
744
745       --  Generate:
746       --    when others =>
747       --       if not Raised_Id then
748       --          Raised_Id := True;
749
750       --          Save_Occurrence (E_Id, Get_Current_Excep.all.all);
751       --            or
752       --          Save_Library_Occurrence (Get_Current_Excep.all.all);
753       --       end if;
754
755       return
756         Make_Exception_Handler (Data.Loc,
757           Exception_Choices =>
758             New_List (Make_Others_Choice (Data.Loc)),
759           Statements => New_List (
760             Make_If_Statement (Data.Loc,
761               Condition       =>
762                 Make_Op_Not (Data.Loc,
763                   Right_Opnd => New_Reference_To (Data.Raised_Id, Data.Loc)),
764
765               Then_Statements => New_List (
766                 Make_Assignment_Statement (Data.Loc,
767                   Name       => New_Reference_To (Data.Raised_Id, Data.Loc),
768                   Expression => New_Reference_To (Standard_True, Data.Loc)),
769
770                 Make_Procedure_Call_Statement (Data.Loc,
771                   Name                   =>
772                     New_Reference_To (Proc_To_Call, Data.Loc),
773                   Parameter_Associations => Actuals)))));
774    end Build_Exception_Handler;
775
776    -------------------------------
777    -- Build_Finalization_Master --
778    -------------------------------
779
780    procedure Build_Finalization_Master
781      (Typ        : Entity_Id;
782       Ins_Node   : Node_Id := Empty;
783       Encl_Scope : Entity_Id := Empty)
784    is
785       Desig_Typ : constant Entity_Id := Directly_Designated_Type (Typ);
786       Ptr_Typ   : Entity_Id := Root_Type (Base_Type (Typ));
787
788       function In_Deallocation_Instance (E : Entity_Id) return Boolean;
789       --  Determine whether entity E is inside a wrapper package created for
790       --  an instance of Ada.Unchecked_Deallocation.
791
792       ------------------------------
793       -- In_Deallocation_Instance --
794       ------------------------------
795
796       function In_Deallocation_Instance (E : Entity_Id) return Boolean is
797          Pkg : constant Entity_Id := Scope (E);
798          Par : Node_Id := Empty;
799
800       begin
801          if Ekind (Pkg) = E_Package
802            and then Present (Related_Instance (Pkg))
803            and then Ekind (Related_Instance (Pkg)) = E_Procedure
804          then
805             Par := Generic_Parent (Parent (Related_Instance (Pkg)));
806
807             return
808               Present (Par)
809                 and then Chars (Par) = Name_Unchecked_Deallocation
810                 and then Chars (Scope (Par)) = Name_Ada
811                 and then Scope (Scope (Par)) = Standard_Standard;
812          end if;
813
814          return False;
815       end In_Deallocation_Instance;
816
817    --  Start of processing for Build_Finalization_Master
818
819    begin
820       if Is_Private_Type (Ptr_Typ)
821         and then Present (Full_View (Ptr_Typ))
822       then
823          Ptr_Typ := Full_View (Ptr_Typ);
824       end if;
825
826       --  Certain run-time configurations and targets do not provide support
827       --  for controlled types.
828
829       if Restriction_Active (No_Finalization) then
830          return;
831
832       --  Do not process C, C++, CIL and Java types since it is assumend that
833       --  the non-Ada side will handle their clean up.
834
835       elsif Convention (Desig_Typ) = Convention_C
836         or else Convention (Desig_Typ) = Convention_CIL
837         or else Convention (Desig_Typ) = Convention_CPP
838         or else Convention (Desig_Typ) = Convention_Java
839       then
840          return;
841
842       --  Various machinery such as freezing may have already created a
843       --  finalization master.
844
845       elsif Present (Finalization_Master (Ptr_Typ)) then
846          return;
847
848       --  Do not process types that return on the secondary stack
849
850       elsif Present (Associated_Storage_Pool (Ptr_Typ))
851         and then Is_RTE (Associated_Storage_Pool (Ptr_Typ), RE_SS_Pool)
852       then
853          return;
854
855       --  Do not process types which may never allocate an object
856
857       elsif No_Pool_Assigned (Ptr_Typ) then
858          return;
859
860       --  Do not process access types coming from Ada.Unchecked_Deallocation
861       --  instances. Even though the designated type may be controlled, the
862       --  access type will never participate in allocation.
863
864       elsif In_Deallocation_Instance (Ptr_Typ) then
865          return;
866
867       --  Ignore the general use of anonymous access types unless the context
868       --  requires a finalization master.
869
870       elsif Ekind (Ptr_Typ) = E_Anonymous_Access_Type
871         and then No (Ins_Node)
872       then
873          return;
874
875       --  Do not process non-library access types when restriction No_Nested_
876       --  Finalization is in effect since masters are controlled objects.
877
878       elsif Restriction_Active (No_Nested_Finalization)
879         and then not Is_Library_Level_Entity (Ptr_Typ)
880       then
881          return;
882
883       --  For .NET/JVM targets, allow the processing of access-to-controlled
884       --  types where the designated type is explicitly derived from [Limited_]
885       --  Controlled.
886
887       elsif VM_Target /= No_VM
888         and then not Is_Controlled (Desig_Typ)
889       then
890          return;
891
892       --  Do not create finalization masters in Alfa mode because they result
893       --  in unwanted expansion.
894
895       elsif Alfa_Mode then
896          return;
897       end if;
898
899       declare
900          Loc        : constant Source_Ptr := Sloc (Ptr_Typ);
901          Actions    : constant List_Id := New_List;
902          Fin_Mas_Id : Entity_Id;
903          Pool_Id    : Entity_Id;
904
905       begin
906          --  Generate:
907          --    Fnn : aliased Finalization_Master;
908
909          --  Source access types use fixed master names since the master is
910          --  inserted in the same source unit only once. The only exception to
911          --  this are instances using the same access type as generic actual.
912
913          if Comes_From_Source (Ptr_Typ)
914            and then not Inside_A_Generic
915          then
916             Fin_Mas_Id :=
917               Make_Defining_Identifier (Loc,
918                 Chars => New_External_Name (Chars (Ptr_Typ), "FM"));
919
920          --  Internally generated access types use temporaries as their names
921          --  due to possible collision with identical names coming from other
922          --  packages.
923
924          else
925             Fin_Mas_Id := Make_Temporary (Loc, 'F');
926          end if;
927
928          Append_To (Actions,
929            Make_Object_Declaration (Loc,
930              Defining_Identifier => Fin_Mas_Id,
931              Aliased_Present     => True,
932              Object_Definition   =>
933                New_Reference_To (RTE (RE_Finalization_Master), Loc)));
934
935          --  Storage pool selection and attribute decoration of the generated
936          --  master. Since .NET/JVM compilers do not support pools, this step
937          --  is skipped.
938
939          if VM_Target = No_VM then
940
941             --  If the access type has a user-defined pool, use it as the base
942             --  storage medium for the finalization pool.
943
944             if Present (Associated_Storage_Pool (Ptr_Typ)) then
945                Pool_Id := Associated_Storage_Pool (Ptr_Typ);
946
947             --  The default choice is the global pool
948
949             else
950                Pool_Id := Get_Global_Pool_For_Access_Type (Ptr_Typ);
951                Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
952             end if;
953
954             --  Generate:
955             --    Set_Base_Pool (Fnn, Pool_Id'Unchecked_Access);
956
957             Append_To (Actions,
958               Make_Procedure_Call_Statement (Loc,
959                 Name                   =>
960                   New_Reference_To (RTE (RE_Set_Base_Pool), Loc),
961                 Parameter_Associations => New_List (
962                   New_Reference_To (Fin_Mas_Id, Loc),
963                   Make_Attribute_Reference (Loc,
964                     Prefix         => New_Reference_To (Pool_Id, Loc),
965                     Attribute_Name => Name_Unrestricted_Access))));
966          end if;
967
968          Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
969
970          --  A finalization master created for an anonymous access type must be
971          --  inserted before a context-dependent node.
972
973          if Present (Ins_Node) then
974             Push_Scope (Encl_Scope);
975
976             --  Treat use clauses as declarations and insert directly in front
977             --  of them.
978
979             if Nkind_In (Ins_Node, N_Use_Package_Clause,
980                                    N_Use_Type_Clause)
981             then
982                Insert_List_Before_And_Analyze (Ins_Node, Actions);
983             else
984                Insert_Actions (Ins_Node, Actions);
985             end if;
986
987             Pop_Scope;
988
989          elsif Ekind (Desig_Typ) = E_Incomplete_Type
990            and then Has_Completion_In_Body (Desig_Typ)
991          then
992             Insert_Actions (Parent (Ptr_Typ), Actions);
993
994          --  If the designated type is not yet frozen, then append the actions
995          --  to that type's freeze actions. The actions need to be appended to
996          --  whichever type is frozen later, similarly to what Freeze_Type does
997          --  for appending the storage pool declaration for an access type.
998          --  Otherwise, the call to Set_Storage_Pool_Ptr might reference the
999          --  pool object before it's declared. However, it's not clear that
1000          --  this is exactly the right test to accomplish that here. ???
1001
1002          elsif Present (Freeze_Node (Desig_Typ))
1003            and then not Analyzed (Freeze_Node (Desig_Typ))
1004          then
1005             Append_Freeze_Actions (Desig_Typ, Actions);
1006
1007          elsif Present (Freeze_Node (Ptr_Typ))
1008            and then not Analyzed (Freeze_Node (Ptr_Typ))
1009          then
1010             Append_Freeze_Actions (Ptr_Typ, Actions);
1011
1012          --  If there's a pool created locally for the access type, then we
1013          --  need to ensure that the master gets created after the pool object,
1014          --  because otherwise we can have a forward reference, so we force the
1015          --  master actions to be inserted and analyzed after the pool entity.
1016          --  Note that both the access type and its designated type may have
1017          --  already been frozen and had their freezing actions analyzed at
1018          --  this point. (This seems a little unclean.???)
1019
1020          elsif VM_Target = No_VM
1021            and then Scope (Pool_Id) = Scope (Ptr_Typ)
1022          then
1023             Insert_List_After_And_Analyze (Parent (Pool_Id), Actions);
1024
1025          else
1026             Insert_Actions (Parent (Ptr_Typ), Actions);
1027          end if;
1028       end;
1029    end Build_Finalization_Master;
1030
1031    ---------------------
1032    -- Build_Finalizer --
1033    ---------------------
1034
1035    procedure Build_Finalizer
1036      (N           : Node_Id;
1037       Clean_Stmts : List_Id;
1038       Mark_Id     : Entity_Id;
1039       Top_Decls   : List_Id;
1040       Defer_Abort : Boolean;
1041       Fin_Id      : out Entity_Id)
1042    is
1043       Acts_As_Clean    : constant Boolean :=
1044                            Present (Mark_Id)
1045                              or else
1046                                (Present (Clean_Stmts)
1047                                  and then Is_Non_Empty_List (Clean_Stmts));
1048       Exceptions_OK    : constant Boolean :=
1049                            not Restriction_Active (No_Exception_Propagation);
1050       For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1051       For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1052       For_Package      : constant Boolean :=
1053                            For_Package_Body or else For_Package_Spec;
1054       Loc              : constant Source_Ptr := Sloc (N);
1055
1056       --  NOTE: Local variable declarations are conservative and do not create
1057       --  structures right from the start. Entities and lists are created once
1058       --  it has been established that N has at least one controlled object.
1059
1060       Components_Built : Boolean := False;
1061       --  A flag used to avoid double initialization of entities and lists. If
1062       --  the flag is set then the following variables have been initialized:
1063       --    Counter_Id
1064       --    Finalizer_Decls
1065       --    Finalizer_Stmts
1066       --    Jump_Alts
1067
1068       Counter_Id  : Entity_Id := Empty;
1069       Counter_Val : Int       := 0;
1070       --  Name and value of the state counter
1071
1072       Decls : List_Id := No_List;
1073       --  Declarative region of N (if available). If N is a package declaration
1074       --  Decls denotes the visible declarations.
1075
1076       Finalizer_Data : Finalization_Exception_Data;
1077       --  Data for the exception
1078
1079       Finalizer_Decls : List_Id := No_List;
1080       --  Local variable declarations. This list holds the label declarations
1081       --  of all jump block alternatives as well as the declaration of the
1082       --  local exception occurence and the raised flag:
1083       --     E : Exception_Occurrence;
1084       --     Raised : Boolean := False;
1085       --     L<counter value> : label;
1086
1087       Finalizer_Insert_Nod : Node_Id := Empty;
1088       --  Insertion point for the finalizer body. Depending on the context
1089       --  (Nkind of N) and the individual grouping of controlled objects, this
1090       --  node may denote a package declaration or body, package instantiation,
1091       --  block statement or a counter update statement.
1092
1093       Finalizer_Stmts : List_Id := No_List;
1094       --  The statement list of the finalizer body. It contains the following:
1095       --
1096       --    Abort_Defer;               --  Added if abort is allowed
1097       --    <call to Prev_At_End>      --  Added if exists
1098       --    <cleanup statements>       --  Added if Acts_As_Clean
1099       --    <jump block>               --  Added if Has_Ctrl_Objs
1100       --    <finalization statements>  --  Added if Has_Ctrl_Objs
1101       --    <stack release>            --  Added if Mark_Id exists
1102       --    Abort_Undefer;             --  Added if abort is allowed
1103
1104       Has_Ctrl_Objs : Boolean := False;
1105       --  A general flag which denotes whether N has at least one controlled
1106       --  object.
1107
1108       Has_Tagged_Types : Boolean := False;
1109       --  A general flag which indicates whether N has at least one library-
1110       --  level tagged type declaration.
1111
1112       HSS : Node_Id := Empty;
1113       --  The sequence of statements of N (if available)
1114
1115       Jump_Alts : List_Id := No_List;
1116       --  Jump block alternatives. Depending on the value of the state counter,
1117       --  the control flow jumps to a sequence of finalization statements. This
1118       --  list contains the following:
1119       --
1120       --     when <counter value> =>
1121       --        goto L<counter value>;
1122
1123       Jump_Block_Insert_Nod : Node_Id := Empty;
1124       --  Specific point in the finalizer statements where the jump block is
1125       --  inserted.
1126
1127       Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1128       --  The last controlled construct encountered when processing the top
1129       --  level lists of N. This can be a nested package, an instantiation or
1130       --  an object declaration.
1131
1132       Prev_At_End : Entity_Id := Empty;
1133       --  The previous at end procedure of the handled statements block of N
1134
1135       Priv_Decls : List_Id := No_List;
1136       --  The private declarations of N if N is a package declaration
1137
1138       Spec_Id    : Entity_Id := Empty;
1139       Spec_Decls : List_Id   := Top_Decls;
1140       Stmts      : List_Id   := No_List;
1141
1142       Tagged_Type_Stmts : List_Id := No_List;
1143       --  Contains calls to Ada.Tags.Unregister_Tag for all library-level
1144       --  tagged types found in N.
1145
1146       -----------------------
1147       -- Local subprograms --
1148       -----------------------
1149
1150       procedure Build_Components;
1151       --  Create all entites and initialize all lists used in the creation of
1152       --  the finalizer.
1153
1154       procedure Create_Finalizer;
1155       --  Create the spec and body of the finalizer and insert them in the
1156       --  proper place in the tree depending on the context.
1157
1158       procedure Process_Declarations
1159         (Decls      : List_Id;
1160          Preprocess : Boolean := False;
1161          Top_Level  : Boolean := False);
1162       --  Inspect a list of declarations or statements which may contain
1163       --  objects that need finalization. When flag Preprocess is set, the
1164       --  routine will simply count the total number of controlled objects in
1165       --  Decls. Flag Top_Level denotes whether the processing is done for
1166       --  objects in nested package declarations or instances.
1167
1168       procedure Process_Object_Declaration
1169         (Decl         : Node_Id;
1170          Has_No_Init  : Boolean := False;
1171          Is_Protected : Boolean := False);
1172       --  Generate all the machinery associated with the finalization of a
1173       --  single object. Flag Has_No_Init is used to denote certain contexts
1174       --  where Decl does not have initialization call(s). Flag Is_Protected
1175       --  is set when Decl denotes a simple protected object.
1176
1177       procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1178       --  Generate all the code necessary to unregister the external tag of a
1179       --  tagged type.
1180
1181       ----------------------
1182       -- Build_Components --
1183       ----------------------
1184
1185       procedure Build_Components is
1186          Counter_Decl     : Node_Id;
1187          Counter_Typ      : Entity_Id;
1188          Counter_Typ_Decl : Node_Id;
1189
1190       begin
1191          pragma Assert (Present (Decls));
1192
1193          --  This routine might be invoked several times when dealing with
1194          --  constructs that have two lists (either two declarative regions
1195          --  or declarations and statements). Avoid double initialization.
1196
1197          if Components_Built then
1198             return;
1199          end if;
1200
1201          Components_Built := True;
1202
1203          if Has_Ctrl_Objs then
1204
1205             --  Create entities for the counter, its type, the local exception
1206             --  and the raised flag.
1207
1208             Counter_Id  := Make_Temporary (Loc, 'C');
1209             Counter_Typ := Make_Temporary (Loc, 'T');
1210
1211             Finalizer_Decls := New_List;
1212
1213             Build_Object_Declarations
1214               (Finalizer_Data, Finalizer_Decls, Loc, For_Package);
1215
1216             --  Since the total number of controlled objects is always known,
1217             --  build a subtype of Natural with precise bounds. This allows
1218             --  the backend to optimize the case statement. Generate:
1219             --
1220             --    subtype Tnn is Natural range 0 .. Counter_Val;
1221
1222             Counter_Typ_Decl :=
1223               Make_Subtype_Declaration (Loc,
1224                 Defining_Identifier => Counter_Typ,
1225                 Subtype_Indication  =>
1226                   Make_Subtype_Indication (Loc,
1227                     Subtype_Mark => New_Reference_To (Standard_Natural, Loc),
1228                     Constraint   =>
1229                       Make_Range_Constraint (Loc,
1230                         Range_Expression =>
1231                           Make_Range (Loc,
1232                             Low_Bound  =>
1233                               Make_Integer_Literal (Loc, Uint_0),
1234                             High_Bound =>
1235                               Make_Integer_Literal (Loc, Counter_Val)))));
1236
1237             --  Generate the declaration of the counter itself:
1238             --
1239             --    Counter : Integer := 0;
1240
1241             Counter_Decl :=
1242               Make_Object_Declaration (Loc,
1243                 Defining_Identifier => Counter_Id,
1244                 Object_Definition   => New_Reference_To (Counter_Typ, Loc),
1245                 Expression          => Make_Integer_Literal (Loc, 0));
1246
1247             --  Set the type of the counter explicitly to prevent errors when
1248             --  examining object declarations later on.
1249
1250             Set_Etype (Counter_Id, Counter_Typ);
1251
1252             --  The counter and its type are inserted before the source
1253             --  declarations of N.
1254
1255             Prepend_To (Decls, Counter_Decl);
1256             Prepend_To (Decls, Counter_Typ_Decl);
1257
1258             --  The counter and its associated type must be manually analized
1259             --  since N has already been analyzed. Use the scope of the spec
1260             --  when inserting in a package.
1261
1262             if For_Package then
1263                Push_Scope (Spec_Id);
1264                Analyze (Counter_Typ_Decl);
1265                Analyze (Counter_Decl);
1266                Pop_Scope;
1267
1268             else
1269                Analyze (Counter_Typ_Decl);
1270                Analyze (Counter_Decl);
1271             end if;
1272
1273             Jump_Alts := New_List;
1274          end if;
1275
1276          --  If the context requires additional clean up, the finalization
1277          --  machinery is added after the clean up code.
1278
1279          if Acts_As_Clean then
1280             Finalizer_Stmts       := Clean_Stmts;
1281             Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1282          else
1283             Finalizer_Stmts := New_List;
1284          end if;
1285
1286          if Has_Tagged_Types then
1287             Tagged_Type_Stmts := New_List;
1288          end if;
1289       end Build_Components;
1290
1291       ----------------------
1292       -- Create_Finalizer --
1293       ----------------------
1294
1295       procedure Create_Finalizer is
1296          Body_Id    : Entity_Id;
1297          Fin_Body   : Node_Id;
1298          Fin_Spec   : Node_Id;
1299          Jump_Block : Node_Id;
1300          Label      : Node_Id;
1301          Label_Id   : Entity_Id;
1302
1303          function New_Finalizer_Name return Name_Id;
1304          --  Create a fully qualified name of a package spec or body finalizer.
1305          --  The generated name is of the form: xx__yy__finalize_[spec|body].
1306
1307          ------------------------
1308          -- New_Finalizer_Name --
1309          ------------------------
1310
1311          function New_Finalizer_Name return Name_Id is
1312             procedure New_Finalizer_Name (Id : Entity_Id);
1313             --  Place "__<name-of-Id>" in the name buffer. If the identifier
1314             --  has a non-standard scope, process the scope first.
1315
1316             ------------------------
1317             -- New_Finalizer_Name --
1318             ------------------------
1319
1320             procedure New_Finalizer_Name (Id : Entity_Id) is
1321             begin
1322                if Scope (Id) = Standard_Standard then
1323                   Get_Name_String (Chars (Id));
1324
1325                else
1326                   New_Finalizer_Name (Scope (Id));
1327                   Add_Str_To_Name_Buffer ("__");
1328                   Add_Str_To_Name_Buffer (Get_Name_String (Chars (Id)));
1329                end if;
1330             end New_Finalizer_Name;
1331
1332          --  Start of processing for New_Finalizer_Name
1333
1334          begin
1335             --  Create the fully qualified name of the enclosing scope
1336
1337             New_Finalizer_Name (Spec_Id);
1338
1339             --  Generate:
1340             --    __finalize_[spec|body]
1341
1342             Add_Str_To_Name_Buffer ("__finalize_");
1343
1344             if For_Package_Spec then
1345                Add_Str_To_Name_Buffer ("spec");
1346             else
1347                Add_Str_To_Name_Buffer ("body");
1348             end if;
1349
1350             return Name_Find;
1351          end New_Finalizer_Name;
1352
1353       --  Start of processing for Create_Finalizer
1354
1355       begin
1356          --  Step 1: Creation of the finalizer name
1357
1358          --  Packages must use a distinct name for their finalizers since the
1359          --  binder will have to generate calls to them by name. The name is
1360          --  of the following form:
1361
1362          --    xx__yy__finalize_[spec|body]
1363
1364          if For_Package then
1365             Fin_Id := Make_Defining_Identifier (Loc, New_Finalizer_Name);
1366             Set_Has_Qualified_Name       (Fin_Id);
1367             Set_Has_Fully_Qualified_Name (Fin_Id);
1368
1369          --  The default name is _finalizer
1370
1371          else
1372             Fin_Id :=
1373               Make_Defining_Identifier (Loc,
1374                 Chars => New_External_Name (Name_uFinalizer));
1375
1376             --  The visibility semantics of AT_END handlers force a strange
1377             --  separation of spec and body for stack-related finalizers:
1378
1379             --     declare : Enclosing_Scope
1380             --        procedure _finalizer;
1381             --     begin
1382             --        <controlled objects>
1383             --        procedure _finalizer is
1384             --           ...
1385             --     at end
1386             --        _finalizer;
1387             --     end;
1388
1389             --  Both spec and body are within the same construct and scope, but
1390             --  the body is part of the handled sequence of statements. This
1391             --  placement confuses the elaboration mechanism on targets where
1392             --  AT_END handlers are expanded into "when all others" handlers:
1393
1394             --     exception
1395             --        when all others =>
1396             --           _finalizer;  --  appears to require elab checks
1397             --     at end
1398             --        _finalizer;
1399             --     end;
1400
1401             --  Since the compiler guarantees that the body of a _finalizer is
1402             --  always inserted in the same construct where the AT_END handler
1403             --  resides, there is no need for elaboration checks.
1404
1405             Set_Kill_Elaboration_Checks (Fin_Id);
1406          end if;
1407
1408          --  Step 2: Creation of the finalizer specification
1409
1410          --  Generate:
1411          --    procedure Fin_Id;
1412
1413          Fin_Spec :=
1414            Make_Subprogram_Declaration (Loc,
1415              Specification =>
1416                Make_Procedure_Specification (Loc,
1417                  Defining_Unit_Name => Fin_Id));
1418
1419          --  Step 3: Creation of the finalizer body
1420
1421          if Has_Ctrl_Objs then
1422
1423             --  Add L0, the default destination to the jump block
1424
1425             Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
1426             Set_Entity (Label_Id,
1427               Make_Defining_Identifier (Loc, Chars (Label_Id)));
1428             Label := Make_Label (Loc, Label_Id);
1429
1430             --  Generate:
1431             --    L0 : label;
1432
1433             Prepend_To (Finalizer_Decls,
1434               Make_Implicit_Label_Declaration (Loc,
1435                 Defining_Identifier => Entity (Label_Id),
1436                 Label_Construct     => Label));
1437
1438             --  Generate:
1439             --    when others =>
1440             --       goto L0;
1441
1442             Append_To (Jump_Alts,
1443               Make_Case_Statement_Alternative (Loc,
1444                 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1445                 Statements       => New_List (
1446                   Make_Goto_Statement (Loc,
1447                     Name => New_Reference_To (Entity (Label_Id), Loc)))));
1448
1449             --  Generate:
1450             --    <<L0>>
1451
1452             Append_To (Finalizer_Stmts, Label);
1453
1454             --  The local exception does not need to be reraised for library-
1455             --  level finalizers. Generate:
1456             --
1457             --    if Raised and then not Abort then
1458             --       Raise_From_Controlled_Operation (E);
1459             --    end if;
1460
1461             if not For_Package
1462               and then Exceptions_OK
1463             then
1464                Append_To (Finalizer_Stmts,
1465                  Build_Raise_Statement (Finalizer_Data));
1466             end if;
1467
1468             --  Create the jump block which controls the finalization flow
1469             --  depending on the value of the state counter.
1470
1471             Jump_Block :=
1472               Make_Case_Statement (Loc,
1473                 Expression   => Make_Identifier (Loc, Chars (Counter_Id)),
1474                 Alternatives => Jump_Alts);
1475
1476             if Acts_As_Clean
1477               and then Present (Jump_Block_Insert_Nod)
1478             then
1479                Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1480             else
1481                Prepend_To (Finalizer_Stmts, Jump_Block);
1482             end if;
1483          end if;
1484
1485          --  Add the library-level tagged type unregistration machinery before
1486          --  the jump block circuitry. This ensures that external tags will be
1487          --  removed even if a finalization exception occurs at some point.
1488
1489          if Has_Tagged_Types then
1490             Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1491          end if;
1492
1493          --  Add a call to the previous At_End handler if it exists. The call
1494          --  must always precede the jump block.
1495
1496          if Present (Prev_At_End) then
1497             Prepend_To (Finalizer_Stmts,
1498               Make_Procedure_Call_Statement (Loc, Prev_At_End));
1499
1500             --  Clear the At_End handler since we have already generated the
1501             --  proper replacement call for it.
1502
1503             Set_At_End_Proc (HSS, Empty);
1504          end if;
1505
1506          --  Release the secondary stack mark
1507
1508          if Present (Mark_Id) then
1509             Append_To (Finalizer_Stmts,
1510               Make_Procedure_Call_Statement (Loc,
1511                 Name                   =>
1512                   New_Reference_To (RTE (RE_SS_Release), Loc),
1513                 Parameter_Associations => New_List (
1514                   New_Reference_To (Mark_Id, Loc))));
1515          end if;
1516
1517          --  Protect the statements with abort defer/undefer. This is only when
1518          --  aborts are allowed and the clean up statements require deferral or
1519          --  there are controlled objects to be finalized.
1520
1521          if Abort_Allowed
1522            and then
1523              (Defer_Abort or else Has_Ctrl_Objs)
1524          then
1525             Prepend_To (Finalizer_Stmts,
1526               Make_Procedure_Call_Statement (Loc,
1527                 Name => New_Reference_To (RTE (RE_Abort_Defer), Loc)));
1528
1529             Append_To (Finalizer_Stmts,
1530               Make_Procedure_Call_Statement (Loc,
1531                 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
1532          end if;
1533
1534          --  Generate:
1535          --    procedure Fin_Id is
1536          --       Abort  : constant Boolean := Triggered_By_Abort;
1537          --         <or>
1538          --       Abort  : constant Boolean := False;  --  no abort
1539
1540          --       E      : Exception_Occurrence;  --  All added if flag
1541          --       Raised : Boolean := False;      --  Has_Ctrl_Objs is set
1542          --       L0     : label;
1543          --       ...
1544          --       Lnn    : label;
1545
1546          --    begin
1547          --       Abort_Defer;               --  Added if abort is allowed
1548          --       <call to Prev_At_End>      --  Added if exists
1549          --       <cleanup statements>       --  Added if Acts_As_Clean
1550          --       <jump block>               --  Added if Has_Ctrl_Objs
1551          --       <finalization statements>  --  Added if Has_Ctrl_Objs
1552          --       <stack release>            --  Added if Mark_Id exists
1553          --       Abort_Undefer;             --  Added if abort is allowed
1554          --    end Fin_Id;
1555
1556          --  Create the body of the finalizer
1557
1558          Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1559
1560          if For_Package then
1561             Set_Has_Qualified_Name       (Body_Id);
1562             Set_Has_Fully_Qualified_Name (Body_Id);
1563          end if;
1564
1565          Fin_Body :=
1566            Make_Subprogram_Body (Loc,
1567              Specification              =>
1568                Make_Procedure_Specification (Loc,
1569                  Defining_Unit_Name => Body_Id),
1570              Declarations               => Finalizer_Decls,
1571              Handled_Statement_Sequence =>
1572                Make_Handled_Sequence_Of_Statements (Loc, Finalizer_Stmts));
1573
1574          --  Step 4: Spec and body insertion, analysis
1575
1576          if For_Package then
1577
1578             --  If the package spec has private declarations, the finalizer
1579             --  body must be added to the end of the list in order to have
1580             --  visibility of all private controlled objects.
1581
1582             if For_Package_Spec then
1583                if Present (Priv_Decls) then
1584                   Append_To (Priv_Decls, Fin_Spec);
1585                   Append_To (Priv_Decls, Fin_Body);
1586                else
1587                   Append_To (Decls, Fin_Spec);
1588                   Append_To (Decls, Fin_Body);
1589                end if;
1590
1591             --  For package bodies, both the finalizer spec and body are
1592             --  inserted at the end of the package declarations.
1593
1594             else
1595                Append_To (Decls, Fin_Spec);
1596                Append_To (Decls, Fin_Body);
1597             end if;
1598
1599             --  Push the name of the package
1600
1601             Push_Scope (Spec_Id);
1602             Analyze (Fin_Spec);
1603             Analyze (Fin_Body);
1604             Pop_Scope;
1605
1606          --  Non-package case
1607
1608          else
1609             --  Create the spec for the finalizer. The At_End handler must be
1610             --  able to call the body which resides in a nested structure.
1611
1612             --  Generate:
1613             --    declare
1614             --       procedure Fin_Id;                  --  Spec
1615             --    begin
1616             --       <objects and possibly statements>
1617             --       procedure Fin_Id is ...            --  Body
1618             --       <statements>
1619             --    at end
1620             --       Fin_Id;                            --  At_End handler
1621             --    end;
1622
1623             pragma Assert (Present (Spec_Decls));
1624
1625             Append_To (Spec_Decls, Fin_Spec);
1626             Analyze (Fin_Spec);
1627
1628             --  When the finalizer acts solely as a clean up routine, the body
1629             --  is inserted right after the spec.
1630
1631             if Acts_As_Clean
1632               and then not Has_Ctrl_Objs
1633             then
1634                Insert_After (Fin_Spec, Fin_Body);
1635
1636             --  In all other cases the body is inserted after either:
1637             --
1638             --    1) The counter update statement of the last controlled object
1639             --    2) The last top level nested controlled package
1640             --    3) The last top level controlled instantiation
1641
1642             else
1643                --  Manually freeze the spec. This is somewhat of a hack because
1644                --  a subprogram is frozen when its body is seen and the freeze
1645                --  node appears right before the body. However, in this case,
1646                --  the spec must be frozen earlier since the At_End handler
1647                --  must be able to call it.
1648                --
1649                --    declare
1650                --       procedure Fin_Id;               --  Spec
1651                --       [Fin_Id]                        --  Freeze node
1652                --    begin
1653                --       ...
1654                --    at end
1655                --       Fin_Id;                         --  At_End handler
1656                --    end;
1657
1658                Ensure_Freeze_Node (Fin_Id);
1659                Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
1660                Set_Is_Frozen (Fin_Id);
1661
1662                --  In the case where the last construct to contain a controlled
1663                --  object is either a nested package, an instantiation or a
1664                --  freeze node, the body must be inserted directly after the
1665                --  construct.
1666
1667                if Nkind_In (Last_Top_Level_Ctrl_Construct,
1668                               N_Freeze_Entity,
1669                               N_Package_Declaration,
1670                               N_Package_Body)
1671                then
1672                   Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
1673                end if;
1674
1675                Insert_After (Finalizer_Insert_Nod, Fin_Body);
1676             end if;
1677
1678             Analyze (Fin_Body);
1679          end if;
1680       end Create_Finalizer;
1681
1682       --------------------------
1683       -- Process_Declarations --
1684       --------------------------
1685
1686       procedure Process_Declarations
1687         (Decls      : List_Id;
1688          Preprocess : Boolean := False;
1689          Top_Level  : Boolean := False)
1690       is
1691          Decl    : Node_Id;
1692          Expr    : Node_Id;
1693          Obj_Id  : Entity_Id;
1694          Obj_Typ : Entity_Id;
1695          Pack_Id : Entity_Id;
1696          Spec    : Node_Id;
1697          Typ     : Entity_Id;
1698
1699          Old_Counter_Val : Int;
1700          --  This variable is used to determine whether a nested package or
1701          --  instance contains at least one controlled object.
1702
1703          procedure Processing_Actions
1704            (Has_No_Init  : Boolean := False;
1705             Is_Protected : Boolean := False);
1706          --  Depending on the mode of operation of Process_Declarations, either
1707          --  increment the controlled object counter, set the controlled object
1708          --  flag and store the last top level construct or process the current
1709          --  declaration. Flag Has_No_Init is used to propagate scenarios where
1710          --  the current declaration may not have initialization proc(s). Flag
1711          --  Is_Protected should be set when the current declaration denotes a
1712          --  simple protected object.
1713
1714          ------------------------
1715          -- Processing_Actions --
1716          ------------------------
1717
1718          procedure Processing_Actions
1719            (Has_No_Init  : Boolean := False;
1720             Is_Protected : Boolean := False)
1721          is
1722          begin
1723             --  Library-level tagged type
1724
1725             if Nkind (Decl) = N_Full_Type_Declaration then
1726                if Preprocess then
1727                   Has_Tagged_Types := True;
1728
1729                   if Top_Level
1730                     and then No (Last_Top_Level_Ctrl_Construct)
1731                   then
1732                      Last_Top_Level_Ctrl_Construct := Decl;
1733                   end if;
1734
1735                else
1736                   Process_Tagged_Type_Declaration (Decl);
1737                end if;
1738
1739             --  Controlled object declaration
1740
1741             else
1742                if Preprocess then
1743                   Counter_Val   := Counter_Val + 1;
1744                   Has_Ctrl_Objs := True;
1745
1746                   if Top_Level
1747                     and then No (Last_Top_Level_Ctrl_Construct)
1748                   then
1749                      Last_Top_Level_Ctrl_Construct := Decl;
1750                   end if;
1751
1752                else
1753                   Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
1754                end if;
1755             end if;
1756          end Processing_Actions;
1757
1758       --  Start of processing for Process_Declarations
1759
1760       begin
1761          if No (Decls) or else Is_Empty_List (Decls) then
1762             return;
1763          end if;
1764
1765          --  Process all declarations in reverse order
1766
1767          Decl := Last_Non_Pragma (Decls);
1768          while Present (Decl) loop
1769
1770             --  Library-level tagged types
1771
1772             if Nkind (Decl) = N_Full_Type_Declaration then
1773                Typ := Defining_Identifier (Decl);
1774
1775                if Is_Tagged_Type (Typ)
1776                  and then Is_Library_Level_Entity (Typ)
1777                  and then Convention (Typ) = Convention_Ada
1778                  and then Present (Access_Disp_Table (Typ))
1779                  and then RTE_Available (RE_Register_Tag)
1780                  and then not No_Run_Time_Mode
1781                  and then not Is_Abstract_Type (Typ)
1782                then
1783                   Processing_Actions;
1784                end if;
1785
1786             --  Regular object declarations
1787
1788             elsif Nkind (Decl) = N_Object_Declaration then
1789                Obj_Id  := Defining_Identifier (Decl);
1790                Obj_Typ := Base_Type (Etype (Obj_Id));
1791                Expr    := Expression (Decl);
1792
1793                --  Bypass any form of processing for objects which have their
1794                --  finalization disabled. This applies only to objects at the
1795                --  library level.
1796
1797                if For_Package
1798                  and then Finalize_Storage_Only (Obj_Typ)
1799                then
1800                   null;
1801
1802                --  Transient variables are treated separately in order to
1803                --  minimize the size of the generated code. For details, see
1804                --  Process_Transient_Objects.
1805
1806                elsif Is_Processed_Transient (Obj_Id) then
1807                   null;
1808
1809                --  The object is of the form:
1810                --    Obj : Typ [:= Expr];
1811
1812                --  Do not process the incomplete view of a deferred constant.
1813                --  Do not consider tag-to-class-wide conversions.
1814
1815                elsif not Is_Imported (Obj_Id)
1816                  and then Needs_Finalization (Obj_Typ)
1817                  and then not (Ekind (Obj_Id) = E_Constant
1818                                 and then not Has_Completion (Obj_Id))
1819                  and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id)
1820                then
1821                   Processing_Actions;
1822
1823                --  The object is of the form:
1824                --    Obj : Access_Typ := Non_BIP_Function_Call'reference;
1825
1826                --    Obj : Access_Typ :=
1827                --            BIP_Function_Call
1828                --              (..., BIPaccess => null, ...)'reference;
1829
1830                elsif Is_Access_Type (Obj_Typ)
1831                  and then Needs_Finalization
1832                             (Available_View (Designated_Type (Obj_Typ)))
1833                  and then Present (Expr)
1834                  and then
1835                    (Is_Null_Access_BIP_Func_Call (Expr)
1836                      or else
1837                        (Is_Non_BIP_Func_Call (Expr)
1838                          and then not Is_Related_To_Func_Return (Obj_Id)))
1839                then
1840                   Processing_Actions (Has_No_Init => True);
1841
1842                --  Processing for "hook" objects generated for controlled
1843                --  transients declared inside an Expression_With_Actions.
1844
1845                elsif Is_Access_Type (Obj_Typ)
1846                  and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1847                  and then Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
1848                                    N_Object_Declaration
1849                  and then Is_Finalizable_Transient
1850                             (Return_Flag_Or_Transient_Decl (Obj_Id), Decl)
1851                then
1852                   Processing_Actions (Has_No_Init => True);
1853
1854                --  Simple protected objects which use type System.Tasking.
1855                --  Protected_Objects.Protection to manage their locks should
1856                --  be treated as controlled since they require manual cleanup.
1857                --  The only exception is illustrated in the following example:
1858
1859                --     package Pkg is
1860                --        type Ctrl is new Controlled ...
1861                --        procedure Finalize (Obj : in out Ctrl);
1862                --        Lib_Obj : Ctrl;
1863                --     end Pkg;
1864
1865                --     package body Pkg is
1866                --        protected Prot is
1867                --           procedure Do_Something (Obj : in out Ctrl);
1868                --        end Prot;
1869
1870                --        protected body Prot is
1871                --           procedure Do_Something (Obj : in out Ctrl) is ...
1872                --        end Prot;
1873
1874                --        procedure Finalize (Obj : in out Ctrl) is
1875                --        begin
1876                --           Prot.Do_Something (Obj);
1877                --        end Finalize;
1878                --     end Pkg;
1879
1880                --  Since for the most part entities in package bodies depend on
1881                --  those in package specs, Prot's lock should be cleaned up
1882                --  first. The subsequent cleanup of the spec finalizes Lib_Obj.
1883                --  This act however attempts to invoke Do_Something and fails
1884                --  because the lock has disappeared.
1885
1886                elsif Ekind (Obj_Id) = E_Variable
1887                  and then not In_Library_Level_Package_Body (Obj_Id)
1888                  and then
1889                    (Is_Simple_Protected_Type (Obj_Typ)
1890                      or else Has_Simple_Protected_Object (Obj_Typ))
1891                then
1892                   Processing_Actions (Is_Protected => True);
1893                end if;
1894
1895             --  Specific cases of object renamings
1896
1897             elsif Nkind (Decl) = N_Object_Renaming_Declaration then
1898                Obj_Id  := Defining_Identifier (Decl);
1899                Obj_Typ := Base_Type (Etype (Obj_Id));
1900
1901                --  Bypass any form of processing for objects which have their
1902                --  finalization disabled. This applies only to objects at the
1903                --  library level.
1904
1905                if For_Package
1906                  and then Finalize_Storage_Only (Obj_Typ)
1907                then
1908                   null;
1909
1910                --  Return object of a build-in-place function. This case is
1911                --  recognized and marked by the expansion of an extended return
1912                --  statement (see Expand_N_Extended_Return_Statement).
1913
1914                elsif Needs_Finalization (Obj_Typ)
1915                  and then Is_Return_Object (Obj_Id)
1916                  and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
1917                then
1918                   Processing_Actions (Has_No_Init => True);
1919
1920                --  Detect a case where a source object has been initialized by
1921                --  a controlled function call which was later rewritten as a
1922                --  class-wide conversion of Ada.Tags.Displace.
1923
1924                --     Obj : Class_Wide_Type := Function_Call (...);
1925
1926                --     Temp : ... := Function_Call (...)'reference;
1927                --     Obj  : Class_Wide_Type renames
1928                --              (... Ada.Tags.Displace (Temp));
1929
1930                elsif Is_Displacement_Of_Ctrl_Function_Result (Obj_Id) then
1931                   Processing_Actions (Has_No_Init => True);
1932                end if;
1933
1934             --  Inspect the freeze node of an access-to-controlled type and
1935             --  look for a delayed finalization master. This case arises when
1936             --  the freeze actions are inserted at a later time than the
1937             --  expansion of the context. Since Build_Finalizer is never called
1938             --  on a single construct twice, the master will be ultimately
1939             --  left out and never finalized. This is also needed for freeze
1940             --  actions of designated types themselves, since in some cases the
1941             --  finalization master is associated with a designated type's
1942             --  freeze node rather than that of the access type (see handling
1943             --  for freeze actions in Build_Finalization_Master).
1944
1945             elsif Nkind (Decl) = N_Freeze_Entity
1946               and then Present (Actions (Decl))
1947             then
1948                Typ := Entity (Decl);
1949
1950                if (Is_Access_Type (Typ)
1951                     and then not Is_Access_Subprogram_Type (Typ)
1952                     and then Needs_Finalization
1953                                (Available_View (Designated_Type (Typ))))
1954                  or else (Is_Type (Typ) and then Needs_Finalization (Typ))
1955                then
1956                   Old_Counter_Val := Counter_Val;
1957
1958                   --  Freeze nodes are considered to be identical to packages
1959                   --  and blocks in terms of nesting. The difference is that
1960                   --  a finalization master created inside the freeze node is
1961                   --  at the same nesting level as the node itself.
1962
1963                   Process_Declarations (Actions (Decl), Preprocess);
1964
1965                   --  The freeze node contains a finalization master
1966
1967                   if Preprocess
1968                     and then Top_Level
1969                     and then No (Last_Top_Level_Ctrl_Construct)
1970                     and then Counter_Val > Old_Counter_Val
1971                   then
1972                      Last_Top_Level_Ctrl_Construct := Decl;
1973                   end if;
1974                end if;
1975
1976             --  Nested package declarations, avoid generics
1977
1978             elsif Nkind (Decl) = N_Package_Declaration then
1979                Spec    := Specification (Decl);
1980                Pack_Id := Defining_Unit_Name (Spec);
1981
1982                if Nkind (Pack_Id) = N_Defining_Program_Unit_Name then
1983                   Pack_Id := Defining_Identifier (Pack_Id);
1984                end if;
1985
1986                if Ekind (Pack_Id) /= E_Generic_Package then
1987                   Old_Counter_Val := Counter_Val;
1988                   Process_Declarations
1989                     (Private_Declarations (Spec), Preprocess);
1990                   Process_Declarations
1991                     (Visible_Declarations (Spec), Preprocess);
1992
1993                   --  Either the visible or the private declarations contain a
1994                   --  controlled object. The nested package declaration is the
1995                   --  last such construct.
1996
1997                   if Preprocess
1998                     and then Top_Level
1999                     and then No (Last_Top_Level_Ctrl_Construct)
2000                     and then Counter_Val > Old_Counter_Val
2001                   then
2002                      Last_Top_Level_Ctrl_Construct := Decl;
2003                   end if;
2004                end if;
2005
2006             --  Nested package bodies, avoid generics
2007
2008             elsif Nkind (Decl) = N_Package_Body then
2009                Spec := Corresponding_Spec (Decl);
2010
2011                if Ekind (Spec) /= E_Generic_Package then
2012                   Old_Counter_Val := Counter_Val;
2013                   Process_Declarations (Declarations (Decl), Preprocess);
2014
2015                   --  The nested package body is the last construct to contain
2016                   --  a controlled object.
2017
2018                   if Preprocess
2019                     and then Top_Level
2020                     and then No (Last_Top_Level_Ctrl_Construct)
2021                     and then Counter_Val > Old_Counter_Val
2022                   then
2023                      Last_Top_Level_Ctrl_Construct := Decl;
2024                   end if;
2025                end if;
2026
2027             --  Handle a rare case caused by a controlled transient variable
2028             --  created as part of a record init proc. The variable is wrapped
2029             --  in a block, but the block is not associated with a transient
2030             --  scope.
2031
2032             elsif Nkind (Decl) = N_Block_Statement
2033               and then Inside_Init_Proc
2034             then
2035                Old_Counter_Val := Counter_Val;
2036
2037                if Present (Handled_Statement_Sequence (Decl)) then
2038                   Process_Declarations
2039                     (Statements (Handled_Statement_Sequence (Decl)),
2040                      Preprocess);
2041                end if;
2042
2043                Process_Declarations (Declarations (Decl), Preprocess);
2044
2045                --  Either the declaration or statement list of the block has a
2046                --  controlled object.
2047
2048                if Preprocess
2049                  and then Top_Level
2050                  and then No (Last_Top_Level_Ctrl_Construct)
2051                  and then Counter_Val > Old_Counter_Val
2052                then
2053                   Last_Top_Level_Ctrl_Construct := Decl;
2054                end if;
2055             end if;
2056
2057             Prev_Non_Pragma (Decl);
2058          end loop;
2059       end Process_Declarations;
2060
2061       --------------------------------
2062       -- Process_Object_Declaration --
2063       --------------------------------
2064
2065       procedure Process_Object_Declaration
2066         (Decl         : Node_Id;
2067          Has_No_Init  : Boolean := False;
2068          Is_Protected : Boolean := False)
2069       is
2070          Obj_Id    : constant Entity_Id := Defining_Identifier (Decl);
2071          Loc       : constant Source_Ptr := Sloc (Decl);
2072          Body_Ins  : Node_Id;
2073          Count_Ins : Node_Id;
2074          Fin_Call  : Node_Id;
2075          Fin_Stmts : List_Id;
2076          Inc_Decl  : Node_Id;
2077          Label     : Node_Id;
2078          Label_Id  : Entity_Id;
2079          Obj_Ref   : Node_Id;
2080          Obj_Typ   : Entity_Id;
2081
2082          function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2083          --  Once it has been established that the current object is in fact a
2084          --  return object of build-in-place function Func_Id, generate the
2085          --  following cleanup code:
2086          --
2087          --    if BIPallocfrom > Secondary_Stack'Pos
2088          --      and then BIPfinalizationmaster /= null
2089          --    then
2090          --       declare
2091          --          type Ptr_Typ is access Obj_Typ;
2092          --          for Ptr_Typ'Storage_Pool
2093          --            use Base_Pool (BIPfinalizationmaster);
2094          --       begin
2095          --          Free (Ptr_Typ (Temp));
2096          --       end;
2097          --    end if;
2098          --
2099          --  Obj_Typ is the type of the current object, Temp is the original
2100          --  allocation which Obj_Id renames.
2101
2102          procedure Find_Last_Init
2103            (Decl        : Node_Id;
2104             Typ         : Entity_Id;
2105             Last_Init   : out Node_Id;
2106             Body_Insert : out Node_Id);
2107          --  An object declaration has at least one and at most two init calls:
2108          --  that of the type and the user-defined initialize. Given an object
2109          --  declaration, Last_Init denotes the last initialization call which
2110          --  follows the declaration. Body_Insert denotes the place where the
2111          --  finalizer body could be potentially inserted.
2112
2113          -----------------------------
2114          -- Build_BIP_Cleanup_Stmts --
2115          -----------------------------
2116
2117          function Build_BIP_Cleanup_Stmts
2118            (Func_Id : Entity_Id) return Node_Id
2119          is
2120             Decls      : constant List_Id := New_List;
2121             Fin_Mas_Id : constant Entity_Id :=
2122                            Build_In_Place_Formal
2123                              (Func_Id, BIP_Finalization_Master);
2124             Obj_Typ    : constant Entity_Id := Etype (Func_Id);
2125             Temp_Id    : constant Entity_Id :=
2126                            Entity (Prefix (Name (Parent (Obj_Id))));
2127
2128             Cond      : Node_Id;
2129             Free_Blk  : Node_Id;
2130             Free_Stmt : Node_Id;
2131             Pool_Id   : Entity_Id;
2132             Ptr_Typ   : Entity_Id;
2133
2134          begin
2135             --  Generate:
2136             --    Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
2137
2138             Pool_Id := Make_Temporary (Loc, 'P');
2139
2140             Append_To (Decls,
2141               Make_Object_Renaming_Declaration (Loc,
2142                 Defining_Identifier => Pool_Id,
2143                 Subtype_Mark        =>
2144                   New_Reference_To (RTE (RE_Root_Storage_Pool), Loc),
2145                 Name                =>
2146                   Make_Explicit_Dereference (Loc,
2147                     Prefix =>
2148                       Make_Function_Call (Loc,
2149                         Name                   =>
2150                           New_Reference_To (RTE (RE_Base_Pool), Loc),
2151                         Parameter_Associations => New_List (
2152                           Make_Explicit_Dereference (Loc,
2153                             Prefix => New_Reference_To (Fin_Mas_Id, Loc)))))));
2154
2155             --  Create an access type which uses the storage pool of the
2156             --  caller's finalization master.
2157
2158             --  Generate:
2159             --    type Ptr_Typ is access Obj_Typ;
2160
2161             Ptr_Typ := Make_Temporary (Loc, 'P');
2162
2163             Append_To (Decls,
2164               Make_Full_Type_Declaration (Loc,
2165                 Defining_Identifier => Ptr_Typ,
2166                 Type_Definition     =>
2167                   Make_Access_To_Object_Definition (Loc,
2168                     Subtype_Indication => New_Reference_To (Obj_Typ, Loc))));
2169
2170             --  Perform minor decoration in order to set the master and the
2171             --  storage pool attributes.
2172
2173             Set_Ekind (Ptr_Typ, E_Access_Type);
2174             Set_Finalization_Master     (Ptr_Typ, Fin_Mas_Id);
2175             Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2176
2177             --  Create an explicit free statement. Note that the free uses the
2178             --  caller's pool expressed as a renaming.
2179
2180             Free_Stmt :=
2181               Make_Free_Statement (Loc,
2182                 Expression =>
2183                   Unchecked_Convert_To (Ptr_Typ,
2184                     New_Reference_To (Temp_Id, Loc)));
2185
2186             Set_Storage_Pool (Free_Stmt, Pool_Id);
2187
2188             --  Create a block to house the dummy type and the instantiation as
2189             --  well as to perform the cleanup the temporary.
2190
2191             --  Generate:
2192             --    declare
2193             --       <Decls>
2194             --    begin
2195             --       Free (Ptr_Typ (Temp_Id));
2196             --    end;
2197
2198             Free_Blk :=
2199               Make_Block_Statement (Loc,
2200                 Declarations               => Decls,
2201                 Handled_Statement_Sequence =>
2202                   Make_Handled_Sequence_Of_Statements (Loc,
2203                     Statements => New_List (Free_Stmt)));
2204
2205             --  Generate:
2206             --    if BIPfinalizationmaster /= null then
2207
2208             Cond :=
2209               Make_Op_Ne (Loc,
2210                 Left_Opnd  => New_Reference_To (Fin_Mas_Id, Loc),
2211                 Right_Opnd => Make_Null (Loc));
2212
2213             --  For constrained or tagged results escalate the condition to
2214             --  include the allocation format. Generate:
2215             --
2216             --    if BIPallocform > Secondary_Stack'Pos
2217             --      and then BIPfinalizationmaster /= null
2218             --    then
2219
2220             if not Is_Constrained (Obj_Typ)
2221               or else Is_Tagged_Type (Obj_Typ)
2222             then
2223                declare
2224                   Alloc : constant Entity_Id :=
2225                             Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2226                begin
2227                   Cond :=
2228                     Make_And_Then (Loc,
2229                       Left_Opnd  =>
2230                         Make_Op_Gt (Loc,
2231                           Left_Opnd  => New_Reference_To (Alloc, Loc),
2232                           Right_Opnd =>
2233                             Make_Integer_Literal (Loc,
2234                               UI_From_Int
2235                                 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2236
2237                       Right_Opnd => Cond);
2238                end;
2239             end if;
2240
2241             --  Generate:
2242             --    if <Cond> then
2243             --       <Free_Blk>
2244             --    end if;
2245
2246             return
2247               Make_If_Statement (Loc,
2248                 Condition       => Cond,
2249                 Then_Statements => New_List (Free_Blk));
2250          end Build_BIP_Cleanup_Stmts;
2251
2252          --------------------
2253          -- Find_Last_Init --
2254          --------------------
2255
2256          procedure Find_Last_Init
2257            (Decl        : Node_Id;
2258             Typ         : Entity_Id;
2259             Last_Init   : out Node_Id;
2260             Body_Insert : out Node_Id)
2261          is
2262             Nod_1 : Node_Id := Empty;
2263             Nod_2 : Node_Id := Empty;
2264             Utyp  : Entity_Id;
2265
2266             function Is_Init_Call
2267               (N   : Node_Id;
2268                Typ : Entity_Id) return Boolean;
2269             --  Given an arbitrary node, determine whether N is a procedure
2270             --  call and if it is, try to match the name of the call with the
2271             --  [Deep_]Initialize proc of Typ.
2272
2273             function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
2274             --  Given a statement which is part of a list, return the next
2275             --  real statement while skipping over dynamic elab checks.
2276
2277             ------------------
2278             -- Is_Init_Call --
2279             ------------------
2280
2281             function Is_Init_Call
2282               (N   : Node_Id;
2283                Typ : Entity_Id) return Boolean
2284             is
2285             begin
2286                --  A call to [Deep_]Initialize is always direct
2287
2288                if Nkind (N) = N_Procedure_Call_Statement
2289                  and then Nkind (Name (N)) = N_Identifier
2290                then
2291                   declare
2292                      Call_Ent  : constant Entity_Id := Entity (Name (N));
2293                      Deep_Init : constant Entity_Id :=
2294                                    TSS (Typ, TSS_Deep_Initialize);
2295                      Init      : Entity_Id := Empty;
2296
2297                   begin
2298                      --  A type may have controlled components but not be
2299                      --  controlled.
2300
2301                      if Is_Controlled (Typ) then
2302                         Init := Find_Prim_Op (Typ, Name_Initialize);
2303
2304                         if Present (Init) then
2305                            Init := Ultimate_Alias (Init);
2306                         end if;
2307                      end if;
2308
2309                      return
2310                        (Present (Deep_Init) and then Call_Ent = Deep_Init)
2311                          or else
2312                        (Present (Init)      and then Call_Ent = Init);
2313                   end;
2314                end if;
2315
2316                return False;
2317             end Is_Init_Call;
2318
2319             -----------------------------
2320             -- Next_Suitable_Statement --
2321             -----------------------------
2322
2323             function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
2324                Result : Node_Id := Next (Stmt);
2325
2326             begin
2327                --  Skip over access-before-elaboration checks
2328
2329                if Dynamic_Elaboration_Checks
2330                  and then Nkind (Result) = N_Raise_Program_Error
2331                then
2332                   Result := Next (Result);
2333                end if;
2334
2335                return Result;
2336             end Next_Suitable_Statement;
2337
2338          --  Start of processing for Find_Last_Init
2339
2340          begin
2341             Last_Init   := Decl;
2342             Body_Insert := Empty;
2343
2344             --  Object renamings and objects associated with controlled
2345             --  function results do not have initialization calls.
2346
2347             if Has_No_Init then
2348                return;
2349             end if;
2350
2351             if Is_Concurrent_Type (Typ) then
2352                Utyp := Corresponding_Record_Type (Typ);
2353             else
2354                Utyp := Typ;
2355             end if;
2356
2357             if Is_Private_Type (Utyp)
2358               and then Present (Full_View (Utyp))
2359             then
2360                Utyp := Full_View (Utyp);
2361             end if;
2362
2363             --  The init procedures are arranged as follows:
2364
2365             --    Object : Controlled_Type;
2366             --    Controlled_TypeIP (Object);
2367             --    [[Deep_]Initialize (Object);]
2368
2369             --  where the user-defined initialize may be optional or may appear
2370             --  inside a block when abort deferral is needed.
2371
2372             Nod_1 := Next_Suitable_Statement (Decl);
2373             if Present (Nod_1) then
2374                Nod_2 := Next_Suitable_Statement (Nod_1);
2375
2376                --  The statement following an object declaration is always a
2377                --  call to the type init proc.
2378
2379                Last_Init := Nod_1;
2380             end if;
2381
2382             --  Optional user-defined init or deep init processing
2383
2384             if Present (Nod_2) then
2385
2386                --  The statement following the type init proc may be a block
2387                --  statement in cases where abort deferral is required.
2388
2389                if Nkind (Nod_2) = N_Block_Statement then
2390                   declare
2391                      HSS  : constant Node_Id :=
2392                               Handled_Statement_Sequence (Nod_2);
2393                      Stmt : Node_Id;
2394
2395                   begin
2396                      if Present (HSS)
2397                        and then Present (Statements (HSS))
2398                      then
2399                         Stmt := First (Statements (HSS));
2400
2401                         --  Examine individual block statements and locate the
2402                         --  call to [Deep_]Initialze.
2403
2404                         while Present (Stmt) loop
2405                            if Is_Init_Call (Stmt, Utyp) then
2406                               Last_Init   := Stmt;
2407                               Body_Insert := Nod_2;
2408
2409                               exit;
2410                            end if;
2411
2412                            Next (Stmt);
2413                         end loop;
2414                      end if;
2415                   end;
2416
2417                elsif Is_Init_Call (Nod_2, Utyp) then
2418                   Last_Init := Nod_2;
2419                end if;
2420             end if;
2421          end Find_Last_Init;
2422
2423       --  Start of processing for Process_Object_Declaration
2424
2425       begin
2426          Obj_Ref := New_Reference_To (Obj_Id, Loc);
2427          Obj_Typ := Base_Type (Etype (Obj_Id));
2428
2429          --  Handle access types
2430
2431          if Is_Access_Type (Obj_Typ) then
2432             Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
2433             Obj_Typ := Directly_Designated_Type (Obj_Typ);
2434          end if;
2435
2436          Set_Etype (Obj_Ref, Obj_Typ);
2437
2438          --  Set a new value for the state counter and insert the statement
2439          --  after the object declaration. Generate:
2440          --
2441          --    Counter := <value>;
2442
2443          Inc_Decl :=
2444            Make_Assignment_Statement (Loc,
2445              Name       => New_Reference_To (Counter_Id, Loc),
2446              Expression => Make_Integer_Literal (Loc, Counter_Val));
2447
2448          --  Insert the counter after all initialization has been done. The
2449          --  place of insertion depends on the context. When dealing with a
2450          --  controlled function, the counter is inserted directly after the
2451          --  declaration because such objects lack init calls.
2452
2453          Find_Last_Init (Decl, Obj_Typ, Count_Ins, Body_Ins);
2454
2455          Insert_After (Count_Ins, Inc_Decl);
2456          Analyze (Inc_Decl);
2457
2458          --  If the current declaration is the last in the list, the finalizer
2459          --  body needs to be inserted after the set counter statement for the
2460          --  current object declaration. This is complicated by the fact that
2461          --  the set counter statement may appear in abort deferred block. In
2462          --  that case, the proper insertion place is after the block.
2463
2464          if No (Finalizer_Insert_Nod) then
2465
2466             --  Insertion after an abort deffered block
2467
2468             if Present (Body_Ins) then
2469                Finalizer_Insert_Nod := Body_Ins;
2470             else
2471                Finalizer_Insert_Nod := Inc_Decl;
2472             end if;
2473          end if;
2474
2475          --  Create the associated label with this object, generate:
2476          --
2477          --    L<counter> : label;
2478
2479          Label_Id :=
2480            Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
2481          Set_Entity
2482            (Label_Id, Make_Defining_Identifier (Loc, Chars (Label_Id)));
2483          Label := Make_Label (Loc, Label_Id);
2484
2485          Prepend_To (Finalizer_Decls,
2486            Make_Implicit_Label_Declaration (Loc,
2487              Defining_Identifier => Entity (Label_Id),
2488              Label_Construct     => Label));
2489
2490          --  Create the associated jump with this object, generate:
2491          --
2492          --    when <counter> =>
2493          --       goto L<counter>;
2494
2495          Prepend_To (Jump_Alts,
2496            Make_Case_Statement_Alternative (Loc,
2497              Discrete_Choices => New_List (
2498                Make_Integer_Literal (Loc, Counter_Val)),
2499              Statements       => New_List (
2500                Make_Goto_Statement (Loc,
2501                  Name => New_Reference_To (Entity (Label_Id), Loc)))));
2502
2503          --  Insert the jump destination, generate:
2504          --
2505          --     <<L<counter>>>
2506
2507          Append_To (Finalizer_Stmts, Label);
2508
2509          --  Processing for simple protected objects. Such objects require
2510          --  manual finalization of their lock managers.
2511
2512          if Is_Protected then
2513             Fin_Stmts := No_List;
2514
2515             if Is_Simple_Protected_Type (Obj_Typ) then
2516                Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
2517
2518                if Present (Fin_Call) then
2519                   Fin_Stmts := New_List (Fin_Call);
2520                end if;
2521
2522             elsif Has_Simple_Protected_Object (Obj_Typ) then
2523                if Is_Record_Type (Obj_Typ) then
2524                   Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
2525                elsif Is_Array_Type (Obj_Typ) then
2526                   Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
2527                end if;
2528             end if;
2529
2530             --  Generate:
2531             --    begin
2532             --       System.Tasking.Protected_Objects.Finalize_Protection
2533             --         (Obj._object);
2534
2535             --    exception
2536             --       when others =>
2537             --          null;
2538             --    end;
2539
2540             if Present (Fin_Stmts) then
2541                Append_To (Finalizer_Stmts,
2542                  Make_Block_Statement (Loc,
2543                    Handled_Statement_Sequence =>
2544                      Make_Handled_Sequence_Of_Statements (Loc,
2545                        Statements         => Fin_Stmts,
2546
2547                        Exception_Handlers => New_List (
2548                          Make_Exception_Handler (Loc,
2549                            Exception_Choices => New_List (
2550                              Make_Others_Choice (Loc)),
2551
2552                            Statements     => New_List (
2553                              Make_Null_Statement (Loc)))))));
2554             end if;
2555
2556          --  Processing for regular controlled objects
2557
2558          else
2559             --  Generate:
2560             --    [Deep_]Finalize (Obj);  --  No_Exception_Propagation
2561
2562             --    begin                   --  Exception handlers allowed
2563             --       [Deep_]Finalize (Obj);
2564
2565             --    exception
2566             --       when Id : others =>
2567             --          if not Raised then
2568             --             Raised := True;
2569             --             Save_Occurrence (E, Id);
2570             --          end if;
2571             --    end;
2572
2573             Fin_Call :=
2574               Make_Final_Call (
2575                 Obj_Ref => Obj_Ref,
2576                 Typ     => Obj_Typ);
2577
2578             if Exceptions_OK then
2579                Fin_Stmts := New_List (
2580                  Make_Block_Statement (Loc,
2581                    Handled_Statement_Sequence =>
2582                      Make_Handled_Sequence_Of_Statements (Loc,
2583                        Statements => New_List (Fin_Call),
2584
2585                     Exception_Handlers => New_List (
2586                       Build_Exception_Handler
2587                         (Finalizer_Data, For_Package)))));
2588
2589             --  When exception handlers are prohibited, the finalization call
2590             --  appears unprotected. Any exception raised during finalization
2591             --  will bypass the circuitry which ensures the cleanup of all
2592             --  remaining objects.
2593
2594             else
2595                Fin_Stmts := New_List (Fin_Call);
2596             end if;
2597
2598             --  If we are dealing with a return object of a build-in-place
2599             --  function, generate the following cleanup statements:
2600
2601             --    if BIPallocfrom > Secondary_Stack'Pos
2602             --      and then BIPfinalizationmaster /= null
2603             --    then
2604             --       declare
2605             --          type Ptr_Typ is access Obj_Typ;
2606             --          for Ptr_Typ'Storage_Pool use
2607             --                Base_Pool (BIPfinalizationmaster.all).all;
2608             --       begin
2609             --          Free (Ptr_Typ (Temp));
2610             --       end;
2611             --    end if;
2612             --
2613             --  The generated code effectively detaches the temporary from the
2614             --  caller finalization master and deallocates the object. This is
2615             --  disabled on .NET/JVM because pools are not supported.
2616
2617             if VM_Target = No_VM and then Is_Return_Object (Obj_Id) then
2618                declare
2619                   Func_Id : constant Entity_Id := Enclosing_Function (Obj_Id);
2620                begin
2621                   if Is_Build_In_Place_Function (Func_Id)
2622                     and then Needs_BIP_Finalization_Master (Func_Id)
2623                   then
2624                      Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
2625                   end if;
2626                end;
2627             end if;
2628
2629             if Ekind_In (Obj_Id, E_Constant, E_Variable)
2630               and then Present (Return_Flag_Or_Transient_Decl (Obj_Id))
2631             then
2632                --  Return objects use a flag to aid their potential
2633                --  finalization when the enclosing function fails to return
2634                --  properly. Generate:
2635
2636                --    if not Flag then
2637                --       <object finalization statements>
2638                --    end if;
2639
2640                if Is_Return_Object (Obj_Id) then
2641                   Fin_Stmts := New_List (
2642                     Make_If_Statement (Loc,
2643                       Condition     =>
2644                         Make_Op_Not (Loc,
2645                           Right_Opnd =>
2646                             New_Reference_To
2647                               (Return_Flag_Or_Transient_Decl (Obj_Id), Loc)),
2648
2649                     Then_Statements => Fin_Stmts));
2650
2651                --  Temporaries created for the purpose of "exporting" a
2652                --  controlled transient out of an Expression_With_Actions (EWA)
2653                --  need guards. The following illustrates the usage of such
2654                --  temporaries.
2655
2656                --    Access_Typ : access [all] Obj_Typ;
2657                --    Temp       : Access_Typ := null;
2658                --    <Counter>  := ...;
2659
2660                --    do
2661                --       Ctrl_Trans : [access [all]] Obj_Typ := ...;
2662                --       Temp := Access_Typ (Ctrl_Trans);  --  when a pointer
2663                --         <or>
2664                --       Temp := Ctrl_Trans'Unchecked_Access;
2665                --    in ... end;
2666
2667                --  The finalization machinery does not process EWA nodes as
2668                --  this may lead to premature finalization of expressions. Note
2669                --  that Temp is marked as being properly initialized regardless
2670                --  of whether the initialization of Ctrl_Trans succeeded. Since
2671                --  a failed initialization may leave Temp with a value of null,
2672                --  add a guard to handle this case:
2673
2674                --    if Obj /= null then
2675                --       <object finalization statements>
2676                --    end if;
2677
2678                else
2679                   pragma Assert
2680                     (Nkind (Return_Flag_Or_Transient_Decl (Obj_Id)) =
2681                        N_Object_Declaration);
2682
2683                   Fin_Stmts := New_List (
2684                     Make_If_Statement (Loc,
2685                       Condition       =>
2686                         Make_Op_Ne (Loc,
2687                           Left_Opnd  => New_Reference_To (Obj_Id, Loc),
2688                           Right_Opnd => Make_Null (Loc)),
2689
2690                       Then_Statements => Fin_Stmts));
2691                end if;
2692             end if;
2693          end if;
2694
2695          Append_List_To (Finalizer_Stmts, Fin_Stmts);
2696
2697          --  Since the declarations are examined in reverse, the state counter
2698          --  must be decremented in order to keep with the true position of
2699          --  objects.
2700
2701          Counter_Val := Counter_Val - 1;
2702       end Process_Object_Declaration;
2703
2704       -------------------------------------
2705       -- Process_Tagged_Type_Declaration --
2706       -------------------------------------
2707
2708       procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
2709          Typ    : constant Entity_Id := Defining_Identifier (Decl);
2710          DT_Ptr : constant Entity_Id :=
2711                     Node (First_Elmt (Access_Disp_Table (Typ)));
2712       begin
2713          --  Generate:
2714          --    Ada.Tags.Unregister_Tag (<Typ>P);
2715
2716          Append_To (Tagged_Type_Stmts,
2717            Make_Procedure_Call_Statement (Loc,
2718              Name                   =>
2719                New_Reference_To (RTE (RE_Unregister_Tag), Loc),
2720              Parameter_Associations => New_List (
2721                New_Reference_To (DT_Ptr, Loc))));
2722       end Process_Tagged_Type_Declaration;
2723
2724    --  Start of processing for Build_Finalizer
2725
2726    begin
2727       Fin_Id := Empty;
2728
2729       --  Do not perform this expansion in Alfa mode because it is not
2730       --  necessary.
2731
2732       if Alfa_Mode then
2733          return;
2734       end if;
2735
2736       --  Step 1: Extract all lists which may contain controlled objects or
2737       --  library-level tagged types.
2738
2739       if For_Package_Spec then
2740          Decls      := Visible_Declarations (Specification (N));
2741          Priv_Decls := Private_Declarations (Specification (N));
2742
2743          --  Retrieve the package spec id
2744
2745          Spec_Id := Defining_Unit_Name (Specification (N));
2746
2747          if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
2748             Spec_Id := Defining_Identifier (Spec_Id);
2749          end if;
2750
2751       --  Accept statement, block, entry body, package body, protected body,
2752       --  subprogram body or task body.
2753
2754       else
2755          Decls := Declarations (N);
2756          HSS   := Handled_Statement_Sequence (N);
2757
2758          if Present (HSS) then
2759             if Present (Statements (HSS)) then
2760                Stmts := Statements (HSS);
2761             end if;
2762
2763             if Present (At_End_Proc (HSS)) then
2764                Prev_At_End := At_End_Proc (HSS);
2765             end if;
2766          end if;
2767
2768          --  Retrieve the package spec id for package bodies
2769
2770          if For_Package_Body then
2771             Spec_Id := Corresponding_Spec (N);
2772          end if;
2773       end if;
2774
2775       --  Do not process nested packages since those are handled by the
2776       --  enclosing scope's finalizer. Do not process non-expanded package
2777       --  instantiations since those will be re-analyzed and re-expanded.
2778
2779       if For_Package
2780         and then
2781           (not Is_Library_Level_Entity (Spec_Id)
2782
2783              --  Nested packages are considered to be library level entities,
2784              --  but do not need to be processed separately. True library level
2785              --  packages have a scope value of 1.
2786
2787              or else Scope_Depth_Value (Spec_Id) /= Uint_1
2788              or else (Is_Generic_Instance (Spec_Id)
2789                        and then Package_Instantiation (Spec_Id) /= N))
2790       then
2791          return;
2792       end if;
2793
2794       --  Step 2: Object [pre]processing
2795
2796       if For_Package then
2797
2798          --  Preprocess the visible declarations now in order to obtain the
2799          --  correct number of controlled object by the time the private
2800          --  declarations are processed.
2801
2802          Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2803
2804          --  From all the possible contexts, only package specifications may
2805          --  have private declarations.
2806
2807          if For_Package_Spec then
2808             Process_Declarations
2809               (Priv_Decls, Preprocess => True, Top_Level => True);
2810          end if;
2811
2812          --  The current context may lack controlled objects, but require some
2813          --  other form of completion (task termination for instance). In such
2814          --  cases, the finalizer must be created and carry the additional
2815          --  statements.
2816
2817          if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2818             Build_Components;
2819          end if;
2820
2821          --  The preprocessing has determined that the context has controlled
2822          --  objects or library-level tagged types.
2823
2824          if Has_Ctrl_Objs or Has_Tagged_Types then
2825
2826             --  Private declarations are processed first in order to preserve
2827             --  possible dependencies between public and private objects.
2828
2829             if For_Package_Spec then
2830                Process_Declarations (Priv_Decls);
2831             end if;
2832
2833             Process_Declarations (Decls);
2834          end if;
2835
2836       --  Non-package case
2837
2838       else
2839          --  Preprocess both declarations and statements
2840
2841          Process_Declarations (Decls, Preprocess => True, Top_Level => True);
2842          Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
2843
2844          --  At this point it is known that N has controlled objects. Ensure
2845          --  that N has a declarative list since the finalizer spec will be
2846          --  attached to it.
2847
2848          if Has_Ctrl_Objs and then No (Decls) then
2849             Set_Declarations (N, New_List);
2850             Decls      := Declarations (N);
2851             Spec_Decls := Decls;
2852          end if;
2853
2854          --  The current context may lack controlled objects, but require some
2855          --  other form of completion (task termination for instance). In such
2856          --  cases, the finalizer must be created and carry the additional
2857          --  statements.
2858
2859          if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2860             Build_Components;
2861          end if;
2862
2863          if Has_Ctrl_Objs or Has_Tagged_Types then
2864             Process_Declarations (Stmts);
2865             Process_Declarations (Decls);
2866          end if;
2867       end if;
2868
2869       --  Step 3: Finalizer creation
2870
2871       if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
2872          Create_Finalizer;
2873       end if;
2874    end Build_Finalizer;
2875
2876    --------------------------
2877    -- Build_Finalizer_Call --
2878    --------------------------
2879
2880    procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
2881       Is_Prot_Body : constant Boolean :=
2882                        Nkind (N) = N_Subprogram_Body
2883                          and then Is_Protected_Subprogram_Body (N);
2884       --  Determine whether N denotes the protected version of a subprogram
2885       --  which belongs to a protected type.
2886
2887       Loc : constant Source_Ptr := Sloc (N);
2888       HSS : Node_Id;
2889
2890    begin
2891       --  Do not perform this expansion in Alfa mode because we do not create
2892       --  finalizers in the first place.
2893
2894       if Alfa_Mode then
2895          return;
2896       end if;
2897
2898       --  The At_End handler should have been assimilated by the finalizer
2899
2900       HSS := Handled_Statement_Sequence (N);
2901       pragma Assert (No (At_End_Proc (HSS)));
2902
2903       --  If the construct to be cleaned up is a protected subprogram body, the
2904       --  finalizer call needs to be associated with the block which wraps the
2905       --  unprotected version of the subprogram. The following illustrates this
2906       --  scenario:
2907
2908       --     procedure Prot_SubpP is
2909       --        procedure finalizer is
2910       --        begin
2911       --           Service_Entries (Prot_Obj);
2912       --           Abort_Undefer;
2913       --        end finalizer;
2914
2915       --     begin
2916       --        . . .
2917       --        begin
2918       --           Prot_SubpN (Prot_Obj);
2919       --        at end
2920       --           finalizer;
2921       --        end;
2922       --     end Prot_SubpP;
2923
2924       if Is_Prot_Body then
2925          HSS := Handled_Statement_Sequence (Last (Statements (HSS)));
2926
2927       --  An At_End handler and regular exception handlers cannot coexist in
2928       --  the same statement sequence. Wrap the original statements in a block.
2929
2930       elsif Present (Exception_Handlers (HSS)) then
2931          declare
2932             End_Lab : constant Node_Id := End_Label (HSS);
2933             Block   : Node_Id;
2934
2935          begin
2936             Block :=
2937               Make_Block_Statement (Loc, Handled_Statement_Sequence => HSS);
2938
2939             Set_Handled_Statement_Sequence (N,
2940               Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
2941
2942             HSS := Handled_Statement_Sequence (N);
2943             Set_End_Label (HSS, End_Lab);
2944          end;
2945       end if;
2946
2947       Set_At_End_Proc (HSS, New_Reference_To (Fin_Id, Loc));
2948
2949       Analyze (At_End_Proc (HSS));
2950       Expand_At_End_Handler (HSS, Empty);
2951    end Build_Finalizer_Call;
2952
2953    ---------------------
2954    -- Build_Late_Proc --
2955    ---------------------
2956
2957    procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
2958    begin
2959       for Final_Prim in Name_Of'Range loop
2960          if Name_Of (Final_Prim) = Nam then
2961             Set_TSS (Typ,
2962               Make_Deep_Proc
2963                 (Prim  => Final_Prim,
2964                  Typ   => Typ,
2965                  Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
2966          end if;
2967       end loop;
2968    end Build_Late_Proc;
2969
2970    -------------------------------
2971    -- Build_Object_Declarations --
2972    -------------------------------
2973
2974    procedure Build_Object_Declarations
2975      (Data        : out Finalization_Exception_Data;
2976       Decls       : List_Id;
2977       Loc         : Source_Ptr;
2978       For_Package : Boolean := False)
2979    is
2980       A_Expr : Node_Id;
2981       E_Decl : Node_Id;
2982
2983    begin
2984       pragma Assert (Decls /= No_List);
2985
2986       --  Always set the proper location as it may be needed even when
2987       --  exception propagation is forbidden.
2988
2989       Data.Loc := Loc;
2990
2991       if Restriction_Active (No_Exception_Propagation) then
2992          Data.Abort_Id  := Empty;
2993          Data.E_Id      := Empty;
2994          Data.Raised_Id := Empty;
2995          return;
2996       end if;
2997
2998       Data.Abort_Id  := Make_Temporary (Loc, 'A');
2999       Data.E_Id      := Make_Temporary (Loc, 'E');
3000       Data.Raised_Id := Make_Temporary (Loc, 'R');
3001
3002       --  In certain scenarios, finalization can be triggered by an abort. If
3003       --  the finalization itself fails and raises an exception, the resulting
3004       --  Program_Error must be supressed and replaced by an abort signal. In
3005       --  order to detect this scenario, save the state of entry into the
3006       --  finalization code.
3007
3008       --  No need to do this for VM case, since VM version of Ada.Exceptions
3009       --  does not include routine Raise_From_Controlled_Operation which is the
3010       --  the sole user of flag Abort.
3011
3012       --  This is not needed for library-level finalizers as they are called
3013       --  by the environment task and cannot be aborted.
3014
3015       if Abort_Allowed
3016         and then VM_Target = No_VM
3017         and then not For_Package
3018       then
3019          A_Expr := New_Reference_To (RTE (RE_Triggered_By_Abort), Loc);
3020
3021       --  No abort, .NET/JVM or library-level finalizers
3022
3023       else
3024          A_Expr := New_Reference_To (Standard_False, Loc);
3025       end if;
3026
3027       --  Generate:
3028       --    Abort_Id : constant Boolean := <A_Expr>;
3029
3030       Append_To (Decls,
3031         Make_Object_Declaration (Loc,
3032           Defining_Identifier => Data.Abort_Id,
3033           Constant_Present    => True,
3034           Object_Definition   => New_Reference_To (Standard_Boolean, Loc),
3035           Expression          => A_Expr));
3036
3037       --  Generate:
3038       --    E_Id : Exception_Occurrence;
3039
3040       E_Decl :=
3041         Make_Object_Declaration (Loc,
3042           Defining_Identifier => Data.E_Id,
3043           Object_Definition   =>
3044             New_Reference_To (RTE (RE_Exception_Occurrence), Loc));
3045       Set_No_Initialization (E_Decl);
3046
3047       Append_To (Decls, E_Decl);
3048
3049       --  Generate:
3050       --    Raised_Id : Boolean := False;
3051
3052       Append_To (Decls,
3053         Make_Object_Declaration (Loc,
3054           Defining_Identifier => Data.Raised_Id,
3055           Object_Definition   => New_Reference_To (Standard_Boolean, Loc),
3056           Expression          => New_Reference_To (Standard_False, Loc)));
3057    end Build_Object_Declarations;
3058
3059    ---------------------------
3060    -- Build_Raise_Statement --
3061    ---------------------------
3062
3063    function Build_Raise_Statement
3064      (Data : Finalization_Exception_Data) return Node_Id
3065    is
3066       Stmt : Node_Id;
3067
3068    begin
3069       --  Standard run-time and .NET/JVM targets use the specialized routine
3070       --  Raise_From_Controlled_Operation.
3071
3072       if RTE_Available (RE_Raise_From_Controlled_Operation) then
3073          Stmt :=
3074            Make_Procedure_Call_Statement (Data.Loc,
3075               Name                   =>
3076                 New_Reference_To
3077                   (RTE (RE_Raise_From_Controlled_Operation), Data.Loc),
3078               Parameter_Associations =>
3079                 New_List (New_Reference_To (Data.E_Id, Data.Loc)));
3080
3081       --  Restricted run-time: exception messages are not supported and hence
3082       --  Raise_From_Controlled_Operation is not supported. Raise Program_Error
3083       --  instead.
3084
3085       else
3086          Stmt :=
3087            Make_Raise_Program_Error (Data.Loc,
3088              Reason => PE_Finalize_Raised_Exception);
3089       end if;
3090
3091       --  Generate:
3092       --    if Raised_Id and then not Abort_Id then
3093       --       Raise_From_Controlled_Operation (E_Id);
3094       --         <or>
3095       --       raise Program_Error;  --  restricted runtime
3096       --    end if;
3097
3098       return
3099         Make_If_Statement (Data.Loc,
3100           Condition       =>
3101             Make_And_Then (Data.Loc,
3102               Left_Opnd  => New_Reference_To (Data.Raised_Id, Data.Loc),
3103               Right_Opnd =>
3104                 Make_Op_Not (Data.Loc,
3105                   Right_Opnd => New_Reference_To (Data.Abort_Id, Data.Loc))),
3106
3107           Then_Statements => New_List (Stmt));
3108    end Build_Raise_Statement;
3109
3110    -----------------------------
3111    -- Build_Record_Deep_Procs --
3112    -----------------------------
3113
3114    procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3115    begin
3116       Set_TSS (Typ,
3117         Make_Deep_Proc
3118           (Prim  => Initialize_Case,
3119            Typ   => Typ,
3120            Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
3121
3122       if not Is_Immutably_Limited_Type (Typ) then
3123          Set_TSS (Typ,
3124            Make_Deep_Proc
3125              (Prim  => Adjust_Case,
3126               Typ   => Typ,
3127               Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
3128       end if;
3129
3130       --  Do not generate Deep_Finalize and Finalize_Address if finalization is
3131       --  suppressed since these routine will not be used.
3132
3133       if not Restriction_Active (No_Finalization) then
3134          Set_TSS (Typ,
3135            Make_Deep_Proc
3136              (Prim  => Finalize_Case,
3137               Typ   => Typ,
3138               Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3139
3140          --  Create TSS primitive Finalize_Address for non-VM targets. JVM and
3141          --  .NET do not support address arithmetic and unchecked conversions.
3142
3143          if VM_Target = No_VM then
3144             Set_TSS (Typ,
3145               Make_Deep_Proc
3146                 (Prim  => Address_Case,
3147                  Typ   => Typ,
3148                  Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3149          end if;
3150       end if;
3151    end Build_Record_Deep_Procs;
3152
3153    -------------------
3154    -- Cleanup_Array --
3155    -------------------
3156
3157    function Cleanup_Array
3158      (N    : Node_Id;
3159       Obj  : Node_Id;
3160       Typ  : Entity_Id) return List_Id
3161    is
3162       Loc        : constant Source_Ptr := Sloc (N);
3163       Index_List : constant List_Id := New_List;
3164
3165       function Free_Component return List_Id;
3166       --  Generate the code to finalize the task or protected  subcomponents
3167       --  of a single component of the array.
3168
3169       function Free_One_Dimension (Dim : Int) return List_Id;
3170       --  Generate a loop over one dimension of the array
3171
3172       --------------------
3173       -- Free_Component --
3174       --------------------
3175
3176       function Free_Component return List_Id is
3177          Stmts : List_Id := New_List;
3178          Tsk   : Node_Id;
3179          C_Typ : constant Entity_Id := Component_Type (Typ);
3180
3181       begin
3182          --  Component type is known to contain tasks or protected objects
3183
3184          Tsk :=
3185            Make_Indexed_Component (Loc,
3186              Prefix        => Duplicate_Subexpr_No_Checks (Obj),
3187              Expressions   => Index_List);
3188
3189          Set_Etype (Tsk, C_Typ);
3190
3191          if Is_Task_Type (C_Typ) then
3192             Append_To (Stmts, Cleanup_Task (N, Tsk));
3193
3194          elsif Is_Simple_Protected_Type (C_Typ) then
3195             Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3196
3197          elsif Is_Record_Type (C_Typ) then
3198             Stmts := Cleanup_Record (N, Tsk, C_Typ);
3199
3200          elsif Is_Array_Type (C_Typ) then
3201             Stmts := Cleanup_Array (N, Tsk, C_Typ);
3202          end if;
3203
3204          return Stmts;
3205       end Free_Component;
3206
3207       ------------------------
3208       -- Free_One_Dimension --
3209       ------------------------
3210
3211       function Free_One_Dimension (Dim : Int) return List_Id is
3212          Index : Entity_Id;
3213
3214       begin
3215          if Dim > Number_Dimensions (Typ) then
3216             return Free_Component;
3217
3218          --  Here we generate the required loop
3219
3220          else
3221             Index := Make_Temporary (Loc, 'J');
3222             Append (New_Reference_To (Index, Loc), Index_List);
3223
3224             return New_List (
3225               Make_Implicit_Loop_Statement (N,
3226                 Identifier       => Empty,
3227                 Iteration_Scheme =>
3228                   Make_Iteration_Scheme (Loc,
3229                     Loop_Parameter_Specification =>
3230                       Make_Loop_Parameter_Specification (Loc,
3231                         Defining_Identifier         => Index,
3232                         Discrete_Subtype_Definition =>
3233                           Make_Attribute_Reference (Loc,
3234                             Prefix          => Duplicate_Subexpr (Obj),
3235                             Attribute_Name  => Name_Range,
3236                             Expressions     => New_List (
3237                               Make_Integer_Literal (Loc, Dim))))),
3238                 Statements       =>  Free_One_Dimension (Dim + 1)));
3239          end if;
3240       end Free_One_Dimension;
3241
3242    --  Start of processing for Cleanup_Array
3243
3244    begin
3245       return Free_One_Dimension (1);
3246    end Cleanup_Array;
3247
3248    --------------------
3249    -- Cleanup_Record --
3250    --------------------
3251
3252    function Cleanup_Record
3253      (N    : Node_Id;
3254       Obj  : Node_Id;
3255       Typ  : Entity_Id) return List_Id
3256    is
3257       Loc   : constant Source_Ptr := Sloc (N);
3258       Tsk   : Node_Id;
3259       Comp  : Entity_Id;
3260       Stmts : constant List_Id    := New_List;
3261       U_Typ : constant Entity_Id  := Underlying_Type (Typ);
3262
3263    begin
3264       if Has_Discriminants (U_Typ)
3265         and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
3266         and then
3267           Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
3268         and then
3269           Present
3270             (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
3271       then
3272          --  For now, do not attempt to free a component that may appear in a
3273          --  variant, and instead issue a warning. Doing this "properly" would
3274          --  require building a case statement and would be quite a mess. Note
3275          --  that the RM only requires that free "work" for the case of a task
3276          --  access value, so already we go way beyond this in that we deal
3277          --  with the array case and non-discriminated record cases.
3278
3279          Error_Msg_N
3280            ("task/protected object in variant record will not be freed?", N);
3281          return New_List (Make_Null_Statement (Loc));
3282       end if;
3283
3284       Comp := First_Component (Typ);
3285       while Present (Comp) loop
3286          if Has_Task (Etype (Comp))
3287            or else Has_Simple_Protected_Object (Etype (Comp))
3288          then
3289             Tsk :=
3290               Make_Selected_Component (Loc,
3291                 Prefix        => Duplicate_Subexpr_No_Checks (Obj),
3292                 Selector_Name => New_Occurrence_Of (Comp, Loc));
3293             Set_Etype (Tsk, Etype (Comp));
3294
3295             if Is_Task_Type (Etype (Comp)) then
3296                Append_To (Stmts, Cleanup_Task (N, Tsk));
3297
3298             elsif Is_Simple_Protected_Type (Etype (Comp)) then
3299                Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3300
3301             elsif Is_Record_Type (Etype (Comp)) then
3302
3303                --  Recurse, by generating the prefix of the argument to
3304                --  the eventual cleanup call.
3305
3306                Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
3307
3308             elsif Is_Array_Type (Etype (Comp)) then
3309                Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
3310             end if;
3311          end if;
3312
3313          Next_Component (Comp);
3314       end loop;
3315
3316       return Stmts;
3317    end Cleanup_Record;
3318
3319    ------------------------------
3320    -- Cleanup_Protected_Object --
3321    ------------------------------
3322
3323    function Cleanup_Protected_Object
3324      (N   : Node_Id;
3325       Ref : Node_Id) return Node_Id
3326    is
3327       Loc : constant Source_Ptr := Sloc (N);
3328
3329    begin
3330       --  For restricted run-time libraries (Ravenscar), tasks are
3331       --  non-terminating, and protected objects can only appear at library
3332       --  level, so we do not want finalization of protected objects.
3333
3334       if Restricted_Profile then
3335          return Empty;
3336
3337       else
3338          return
3339            Make_Procedure_Call_Statement (Loc,
3340              Name                   =>
3341                New_Reference_To (RTE (RE_Finalize_Protection), Loc),
3342              Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3343       end if;
3344    end Cleanup_Protected_Object;
3345
3346    ------------------
3347    -- Cleanup_Task --
3348    ------------------
3349
3350    function Cleanup_Task
3351      (N   : Node_Id;
3352       Ref : Node_Id) return Node_Id
3353    is
3354       Loc  : constant Source_Ptr := Sloc (N);
3355
3356    begin
3357       --  For restricted run-time libraries (Ravenscar), tasks are
3358       --  non-terminating and they can only appear at library level, so we do
3359       --  not want finalization of task objects.
3360
3361       if Restricted_Profile then
3362          return Empty;
3363
3364       else
3365          return
3366            Make_Procedure_Call_Statement (Loc,
3367              Name                   =>
3368                New_Reference_To (RTE (RE_Free_Task), Loc),
3369              Parameter_Associations => New_List (Concurrent_Ref (Ref)));
3370       end if;
3371    end Cleanup_Task;
3372
3373    ------------------------------
3374    -- Check_Visibly_Controlled --
3375    ------------------------------
3376
3377    procedure Check_Visibly_Controlled
3378      (Prim : Final_Primitives;
3379       Typ  : Entity_Id;
3380       E    : in out Entity_Id;
3381       Cref : in out Node_Id)
3382    is
3383       Parent_Type : Entity_Id;
3384       Op          : Entity_Id;
3385
3386    begin
3387       if Is_Derived_Type (Typ)
3388         and then Comes_From_Source (E)
3389         and then not Present (Overridden_Operation (E))
3390       then
3391          --  We know that the explicit operation on the type does not override
3392          --  the inherited operation of the parent, and that the derivation
3393          --  is from a private type that is not visibly controlled.
3394
3395          Parent_Type := Etype (Typ);
3396          Op := Find_Prim_Op (Parent_Type, Name_Of (Prim));
3397
3398          if Present (Op) then
3399             E := Op;
3400
3401             --  Wrap the object to be initialized into the proper
3402             --  unchecked conversion, to be compatible with the operation
3403             --  to be called.
3404
3405             if Nkind (Cref) = N_Unchecked_Type_Conversion then
3406                Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
3407             else
3408                Cref := Unchecked_Convert_To (Parent_Type, Cref);
3409             end if;
3410          end if;
3411       end if;
3412    end Check_Visibly_Controlled;
3413
3414    -------------------------------
3415    -- CW_Or_Has_Controlled_Part --
3416    -------------------------------
3417
3418    function CW_Or_Has_Controlled_Part (T : Entity_Id) return Boolean is
3419    begin
3420       return Is_Class_Wide_Type (T) or else Needs_Finalization (T);
3421    end CW_Or_Has_Controlled_Part;
3422
3423    ------------------
3424    -- Convert_View --
3425    ------------------
3426
3427    function Convert_View
3428      (Proc : Entity_Id;
3429       Arg  : Node_Id;
3430       Ind  : Pos := 1) return Node_Id
3431    is
3432       Fent : Entity_Id := First_Entity (Proc);
3433       Ftyp : Entity_Id;
3434       Atyp : Entity_Id;
3435
3436    begin
3437       for J in 2 .. Ind loop
3438          Next_Entity (Fent);
3439       end loop;
3440
3441       Ftyp := Etype (Fent);
3442
3443       if Nkind_In (Arg, N_Type_Conversion, N_Unchecked_Type_Conversion) then
3444          Atyp := Entity (Subtype_Mark (Arg));
3445       else
3446          Atyp := Etype (Arg);
3447       end if;
3448
3449       if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
3450          return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
3451
3452       elsif Ftyp /= Atyp
3453         and then Present (Atyp)
3454         and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
3455         and then Base_Type (Underlying_Type (Atyp)) =
3456                  Base_Type (Underlying_Type (Ftyp))
3457       then
3458          return Unchecked_Convert_To (Ftyp, Arg);
3459
3460       --  If the argument is already a conversion, as generated by
3461       --  Make_Init_Call, set the target type to the type of the formal
3462       --  directly, to avoid spurious typing problems.
3463
3464       elsif Nkind_In (Arg, N_Unchecked_Type_Conversion, N_Type_Conversion)
3465         and then not Is_Class_Wide_Type (Atyp)
3466       then
3467          Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
3468          Set_Etype (Arg, Ftyp);
3469          return Arg;
3470
3471       else
3472          return Arg;
3473       end if;
3474    end Convert_View;
3475
3476    ------------------------
3477    -- Enclosing_Function --
3478    ------------------------
3479
3480    function Enclosing_Function (E : Entity_Id) return Entity_Id is
3481       Func_Id : Entity_Id;
3482
3483    begin
3484       Func_Id := E;
3485       while Present (Func_Id)
3486         and then Func_Id /= Standard_Standard
3487       loop
3488          if Ekind (Func_Id) = E_Function then
3489             return Func_Id;
3490          end if;
3491
3492          Func_Id := Scope (Func_Id);
3493       end loop;
3494
3495       return Empty;
3496    end Enclosing_Function;
3497
3498    -------------------------------
3499    -- Establish_Transient_Scope --
3500    -------------------------------
3501
3502    --  This procedure is called each time a transient block has to be inserted
3503    --  that is to say for each call to a function with unconstrained or tagged
3504    --  result. It creates a new scope on the stack scope in order to enclose
3505    --  all transient variables generated
3506
3507    procedure Establish_Transient_Scope (N : Node_Id; Sec_Stack : Boolean) is
3508       Loc       : constant Source_Ptr := Sloc (N);
3509       Wrap_Node : Node_Id;
3510
3511    begin
3512       --  Do not create a transient scope if we are already inside one
3513
3514       for S in reverse Scope_Stack.First .. Scope_Stack.Last loop
3515          if Scope_Stack.Table (S).Is_Transient then
3516             if Sec_Stack then
3517                Set_Uses_Sec_Stack (Scope_Stack.Table (S).Entity);
3518             end if;
3519
3520             return;
3521
3522          --  If we have encountered Standard there are no enclosing
3523          --  transient scopes.
3524
3525          elsif Scope_Stack.Table (S).Entity = Standard_Standard then
3526             exit;
3527          end if;
3528       end loop;
3529
3530       Wrap_Node := Find_Node_To_Be_Wrapped (N);
3531
3532       --  Case of no wrap node, false alert, no transient scope needed
3533
3534       if No (Wrap_Node) then
3535          null;
3536
3537       --  If the node to wrap is an iteration_scheme, the expression is
3538       --  one of the bounds, and the expansion will make an explicit
3539       --  declaration for it (see Analyze_Iteration_Scheme, sem_ch5.adb),
3540       --  so do not apply any transformations here.
3541
3542       elsif Nkind (Wrap_Node) = N_Iteration_Scheme then
3543          null;
3544
3545       --  In formal verification mode, if the node to wrap is a pragma check,
3546       --  this node and enclosed expression are not expanded, so do not apply
3547       --  any transformations here.
3548
3549       elsif Alfa_Mode
3550         and then Nkind (Wrap_Node) = N_Pragma
3551         and then Get_Pragma_Id (Wrap_Node) = Pragma_Check
3552       then
3553          null;
3554
3555       else
3556          Push_Scope (New_Internal_Entity (E_Block, Current_Scope, Loc, 'B'));
3557          Set_Scope_Is_Transient;
3558
3559          if Sec_Stack then
3560             Set_Uses_Sec_Stack (Current_Scope);
3561             Check_Restriction (No_Secondary_Stack, N);
3562          end if;
3563
3564          Set_Etype (Current_Scope, Standard_Void_Type);
3565          Set_Node_To_Be_Wrapped (Wrap_Node);
3566
3567          if Debug_Flag_W then
3568             Write_Str ("    <Transient>");
3569             Write_Eol;
3570          end if;
3571       end if;
3572    end Establish_Transient_Scope;
3573
3574    ----------------------------
3575    -- Expand_Cleanup_Actions --
3576    ----------------------------
3577
3578    procedure Expand_Cleanup_Actions (N : Node_Id) is
3579       Scop : constant Entity_Id := Current_Scope;
3580
3581       Is_Asynchronous_Call : constant Boolean :=
3582                                Nkind (N) = N_Block_Statement
3583                                  and then Is_Asynchronous_Call_Block (N);
3584       Is_Master            : constant Boolean :=
3585                                Nkind (N) /= N_Entry_Body
3586                                  and then Is_Task_Master (N);
3587       Is_Protected_Body    : constant Boolean :=
3588                                Nkind (N) = N_Subprogram_Body
3589                                  and then Is_Protected_Subprogram_Body (N);
3590       Is_Task_Allocation   : constant Boolean :=
3591                                Nkind (N) = N_Block_Statement
3592                                  and then Is_Task_Allocation_Block (N);
3593       Is_Task_Body         : constant Boolean :=
3594                                Nkind (Original_Node (N)) = N_Task_Body;
3595       Needs_Sec_Stack_Mark : constant Boolean :=
3596                                Uses_Sec_Stack (Scop)
3597                                  and then
3598                                    not Sec_Stack_Needed_For_Return (Scop)
3599                                  and then VM_Target = No_VM;
3600
3601       Actions_Required     : constant Boolean :=
3602                                Requires_Cleanup_Actions (N)
3603                                  or else Is_Asynchronous_Call
3604                                  or else Is_Master
3605                                  or else Is_Protected_Body
3606                                  or else Is_Task_Allocation
3607                                  or else Is_Task_Body
3608                                  or else Needs_Sec_Stack_Mark;
3609
3610       HSS : Node_Id := Handled_Statement_Sequence (N);
3611       Loc : Source_Ptr;
3612
3613       procedure Wrap_HSS_In_Block;
3614       --  Move HSS inside a new block along with the original exception
3615       --  handlers. Make the newly generated block the sole statement of HSS.
3616
3617       -----------------------
3618       -- Wrap_HSS_In_Block --
3619       -----------------------
3620
3621       procedure Wrap_HSS_In_Block is
3622          Block   : Node_Id;
3623          End_Lab : Node_Id;
3624
3625       begin
3626          --  Preserve end label to provide proper cross-reference information
3627
3628          End_Lab := End_Label (HSS);
3629          Block :=
3630            Make_Block_Statement (Loc,
3631              Handled_Statement_Sequence => HSS);
3632
3633          Set_Handled_Statement_Sequence (N,
3634            Make_Handled_Sequence_Of_Statements (Loc, New_List (Block)));
3635          HSS := Handled_Statement_Sequence (N);
3636
3637          Set_First_Real_Statement (HSS, Block);
3638          Set_End_Label (HSS, End_Lab);
3639
3640          --  Comment needed here, see RH for 1.306 ???
3641
3642          if Nkind (N) = N_Subprogram_Body then
3643             Set_Has_Nested_Block_With_Handler (Scop);
3644          end if;
3645       end Wrap_HSS_In_Block;
3646
3647    --  Start of processing for Expand_Cleanup_Actions
3648
3649    begin
3650       --  The current construct does not need any form of servicing
3651
3652       if not Actions_Required then
3653          return;
3654
3655       --  If the current node is a rewritten task body and the descriptors have
3656       --  not been delayed (due to some nested instantiations), do not generate
3657       --  redundant cleanup actions.
3658
3659       elsif Is_Task_Body
3660         and then Nkind (N) = N_Subprogram_Body
3661         and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
3662       then
3663          return;
3664       end if;
3665
3666       declare
3667          Decls     : List_Id := Declarations (N);
3668          Fin_Id    : Entity_Id;
3669          Mark      : Entity_Id := Empty;
3670          New_Decls : List_Id;
3671          Old_Poll  : Boolean;
3672
3673       begin
3674          --  If we are generating expanded code for debugging purposes, use the
3675          --  Sloc of the point of insertion for the cleanup code. The Sloc will
3676          --  be updated subsequently to reference the proper line in .dg files.
3677          --  If we are not debugging generated code, use No_Location instead,
3678          --  so that no debug information is generated for the cleanup code.
3679          --  This makes the behavior of the NEXT command in GDB monotonic, and
3680          --  makes the placement of breakpoints more accurate.
3681
3682          if Debug_Generated_Code then
3683             Loc := Sloc (Scop);
3684          else
3685             Loc := No_Location;
3686          end if;
3687
3688          --  Set polling off. The finalization and cleanup code is executed
3689          --  with aborts deferred.
3690
3691          Old_Poll := Polling_Required;
3692          Polling_Required := False;
3693
3694          --  A task activation call has already been built for a task
3695          --  allocation block.
3696
3697          if not Is_Task_Allocation then
3698             Build_Task_Activation_Call (N);
3699          end if;
3700
3701          if Is_Master then
3702             Establish_Task_Master (N);
3703          end if;
3704
3705          New_Decls := New_List;
3706
3707          --  If secondary stack is in use, generate:
3708          --
3709          --    Mnn : constant Mark_Id := SS_Mark;
3710
3711          --  Suppress calls to SS_Mark and SS_Release if VM_Target, since the
3712          --  secondary stack is never used on a VM.
3713
3714          if Needs_Sec_Stack_Mark then
3715             Mark := Make_Temporary (Loc, 'M');
3716
3717             Append_To (New_Decls,
3718               Make_Object_Declaration (Loc,
3719                 Defining_Identifier => Mark,
3720                 Object_Definition   =>
3721                   New_Reference_To (RTE (RE_Mark_Id), Loc),
3722                 Expression          =>
3723                   Make_Function_Call (Loc,
3724                     Name => New_Reference_To (RTE (RE_SS_Mark), Loc))));
3725
3726             Set_Uses_Sec_Stack (Scop, False);
3727          end if;
3728
3729          --  If exception handlers are present, wrap the sequence of statements
3730          --  in a block since it is not possible to have exception handlers and
3731          --  an At_End handler in the same construct.
3732
3733          if Present (Exception_Handlers (HSS)) then
3734             Wrap_HSS_In_Block;
3735
3736          --  Ensure that the First_Real_Statement field is set
3737
3738          elsif No (First_Real_Statement (HSS)) then
3739             Set_First_Real_Statement (HSS, First (Statements (HSS)));
3740          end if;
3741
3742          --  Do not move the Activation_Chain declaration in the context of
3743          --  task allocation blocks. Task allocation blocks use _chain in their
3744          --  cleanup handlers and gigi complains if it is declared in the
3745          --  sequence of statements of the scope that declares the handler.
3746
3747          if Is_Task_Allocation then
3748             declare
3749                Chain : constant Entity_Id := Activation_Chain_Entity (N);
3750                Decl  : Node_Id;
3751
3752             begin
3753                Decl := First (Decls);
3754                while Nkind (Decl) /= N_Object_Declaration
3755                  or else Defining_Identifier (Decl) /= Chain
3756                loop
3757                   Next (Decl);
3758
3759                   --  A task allocation block should always include a _chain
3760                   --  declaration.
3761
3762                   pragma Assert (Present (Decl));
3763                end loop;
3764
3765                Remove (Decl);
3766                Prepend_To (New_Decls, Decl);
3767             end;
3768          end if;
3769
3770          --  Ensure the presence of a declaration list in order to successfully
3771          --  append all original statements to it.
3772
3773          if No (Decls) then
3774             Set_Declarations (N, New_List);
3775             Decls := Declarations (N);
3776          end if;
3777
3778          --  Move the declarations into the sequence of statements in order to
3779          --  have them protected by the At_End handler. It may seem weird to
3780          --  put declarations in the sequence of statement but in fact nothing
3781          --  forbids that at the tree level.
3782
3783          Append_List_To (Decls, Statements (HSS));
3784          Set_Statements (HSS, Decls);
3785
3786          --  Reset the Sloc of the handled statement sequence to properly
3787          --  reflect the new initial "statement" in the sequence.
3788
3789          Set_Sloc (HSS, Sloc (First (Decls)));
3790
3791          --  The declarations of finalizer spec and auxiliary variables replace
3792          --  the old declarations that have been moved inward.
3793
3794          Set_Declarations (N, New_Decls);
3795          Analyze_Declarations (New_Decls);
3796
3797          --  Generate finalization calls for all controlled objects appearing
3798          --  in the statements of N. Add context specific cleanup for various
3799          --  constructs.
3800
3801          Build_Finalizer
3802            (N           => N,
3803             Clean_Stmts => Build_Cleanup_Statements (N),
3804             Mark_Id     => Mark,
3805             Top_Decls   => New_Decls,
3806             Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
3807                              or else Is_Master,
3808             Fin_Id      => Fin_Id);
3809
3810          if Present (Fin_Id) then
3811             Build_Finalizer_Call (N, Fin_Id);
3812          end if;
3813
3814          --  Restore saved polling mode
3815
3816          Polling_Required := Old_Poll;
3817       end;
3818    end Expand_Cleanup_Actions;
3819
3820    ---------------------------
3821    -- Expand_N_Package_Body --
3822    ---------------------------
3823
3824    --  Add call to Activate_Tasks if body is an activator (actual processing
3825    --  is in chapter 9).
3826
3827    --  Generate subprogram descriptor for elaboration routine
3828
3829    --  Encode entity names in package body
3830
3831    procedure Expand_N_Package_Body (N : Node_Id) is
3832       Spec_Ent : constant Entity_Id := Corresponding_Spec (N);
3833       Fin_Id   : Entity_Id;
3834
3835    begin
3836       --  This is done only for non-generic packages
3837
3838       if Ekind (Spec_Ent) = E_Package then
3839          Push_Scope (Corresponding_Spec (N));
3840
3841          --  Build dispatch tables of library level tagged types
3842
3843          if Tagged_Type_Expansion
3844            and then Is_Library_Level_Entity (Spec_Ent)
3845          then
3846             Build_Static_Dispatch_Tables (N);
3847          end if;
3848
3849          Build_Task_Activation_Call (N);
3850          Pop_Scope;
3851       end if;
3852
3853       Set_Elaboration_Flag (N, Corresponding_Spec (N));
3854       Set_In_Package_Body (Spec_Ent, False);
3855
3856       --  Set to encode entity names in package body before gigi is called
3857
3858       Qualify_Entity_Names (N);
3859
3860       if Ekind (Spec_Ent) /= E_Generic_Package then
3861          Build_Finalizer
3862            (N           => N,
3863             Clean_Stmts => No_List,
3864             Mark_Id     => Empty,
3865             Top_Decls   => No_List,
3866             Defer_Abort => False,
3867             Fin_Id      => Fin_Id);
3868
3869          if Present (Fin_Id) then
3870             declare
3871                Body_Ent : Node_Id := Defining_Unit_Name (N);
3872
3873             begin
3874                if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
3875                   Body_Ent := Defining_Identifier (Body_Ent);
3876                end if;
3877
3878                Set_Finalizer (Body_Ent, Fin_Id);
3879             end;
3880          end if;
3881       end if;
3882    end Expand_N_Package_Body;
3883
3884    ----------------------------------
3885    -- Expand_N_Package_Declaration --
3886    ----------------------------------
3887
3888    --  Add call to Activate_Tasks if there are tasks declared and the package
3889    --  has no body. Note that in Ada 83 this may result in premature activation
3890    --  of some tasks, given that we cannot tell whether a body will eventually
3891    --  appear.
3892
3893    procedure Expand_N_Package_Declaration (N : Node_Id) is
3894       Id     : constant Entity_Id := Defining_Entity (N);
3895       Spec   : constant Node_Id   := Specification (N);
3896       Decls  : List_Id;
3897       Fin_Id : Entity_Id;
3898
3899       No_Body : Boolean := False;
3900       --  True in the case of a package declaration that is a compilation
3901       --  unit and for which no associated body will be compiled in this
3902       --  compilation.
3903
3904    begin
3905       --  Case of a package declaration other than a compilation unit
3906
3907       if Nkind (Parent (N)) /= N_Compilation_Unit then
3908          null;
3909
3910       --  Case of a compilation unit that does not require a body
3911
3912       elsif not Body_Required (Parent (N))
3913         and then not Unit_Requires_Body (Id)
3914       then
3915          No_Body := True;
3916
3917       --  Special case of generating calling stubs for a remote call interface
3918       --  package: even though the package declaration requires one, the body
3919       --  won't be processed in this compilation (so any stubs for RACWs
3920       --  declared in the package must be generated here, along with the spec).
3921
3922       elsif Parent (N) = Cunit (Main_Unit)
3923         and then Is_Remote_Call_Interface (Id)
3924         and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
3925       then
3926          No_Body := True;
3927       end if;
3928
3929       --  For a nested instance, delay processing until freeze point
3930
3931       if Has_Delayed_Freeze (Id)
3932         and then Nkind (Parent (N)) /= N_Compilation_Unit
3933       then
3934          return;
3935       end if;
3936
3937       --  For a package declaration that implies no associated body, generate
3938       --  task activation call and RACW supporting bodies now (since we won't
3939       --  have a specific separate compilation unit for that).
3940
3941       if No_Body then
3942          Push_Scope (Id);
3943
3944          if Has_RACW (Id) then
3945
3946             --  Generate RACW subprogram bodies
3947
3948             Decls := Private_Declarations (Spec);
3949
3950             if No (Decls) then
3951                Decls := Visible_Declarations (Spec);
3952             end if;
3953
3954             if No (Decls) then
3955                Decls := New_List;
3956                Set_Visible_Declarations (Spec, Decls);
3957             end if;
3958
3959             Append_RACW_Bodies (Decls, Id);
3960             Analyze_List (Decls);
3961          end if;
3962
3963          if Present (Activation_Chain_Entity (N)) then
3964
3965             --  Generate task activation call as last step of elaboration
3966
3967             Build_Task_Activation_Call (N);
3968          end if;
3969
3970          Pop_Scope;
3971       end if;
3972
3973       --  Build dispatch tables of library level tagged types
3974
3975       if Tagged_Type_Expansion
3976         and then (Is_Compilation_Unit (Id)
3977                    or else (Is_Generic_Instance (Id)
3978                              and then Is_Library_Level_Entity (Id)))
3979       then
3980          Build_Static_Dispatch_Tables (N);
3981       end if;
3982
3983       --  Note: it is not necessary to worry about generating a subprogram
3984       --  descriptor, since the only way to get exception handlers into a
3985       --  package spec is to include instantiations, and that would cause
3986       --  generation of subprogram descriptors to be delayed in any case.
3987
3988       --  Set to encode entity names in package spec before gigi is called
3989
3990       Qualify_Entity_Names (N);
3991
3992       if Ekind (Id) /= E_Generic_Package then
3993          Build_Finalizer
3994            (N           => N,
3995             Clean_Stmts => No_List,
3996             Mark_Id     => Empty,
3997             Top_Decls   => No_List,
3998             Defer_Abort => False,
3999             Fin_Id      => Fin_Id);
4000
4001          Set_Finalizer (Id, Fin_Id);
4002       end if;
4003    end Expand_N_Package_Declaration;
4004
4005    -----------------------------
4006    -- Find_Node_To_Be_Wrapped --
4007    -----------------------------
4008
4009    function Find_Node_To_Be_Wrapped (N : Node_Id) return Node_Id is
4010       P          : Node_Id;
4011       The_Parent : Node_Id;
4012
4013    begin
4014       The_Parent := N;
4015       loop
4016          P := The_Parent;
4017          pragma Assert (P /= Empty);
4018          The_Parent := Parent (P);
4019
4020          case Nkind (The_Parent) is
4021
4022             --  Simple statement can be wrapped
4023
4024             when N_Pragma =>
4025                return The_Parent;
4026
4027             --  Usually assignments are good candidate for wrapping except
4028             --  when they have been generated as part of a controlled aggregate
4029             --  where the wrapping should take place more globally.
4030
4031             when N_Assignment_Statement =>
4032                if No_Ctrl_Actions (The_Parent) then
4033                   null;
4034                else
4035                   return The_Parent;
4036                end if;
4037
4038             --  An entry call statement is a special case if it occurs in the
4039             --  context of a Timed_Entry_Call. In this case we wrap the entire
4040             --  timed entry call.
4041
4042             when N_Entry_Call_Statement     |
4043                  N_Procedure_Call_Statement =>
4044                if Nkind (Parent (The_Parent)) = N_Entry_Call_Alternative
4045                  and then Nkind_In (Parent (Parent (The_Parent)),
4046                                     N_Timed_Entry_Call,
4047                                     N_Conditional_Entry_Call)
4048                then
4049                   return Parent (Parent (The_Parent));
4050                else
4051                   return The_Parent;
4052                end if;
4053
4054             --  Object declarations are also a boundary for the transient scope
4055             --  even if they are not really wrapped. For further details, see
4056             --  Wrap_Transient_Declaration.
4057
4058             when N_Object_Declaration          |
4059                  N_Object_Renaming_Declaration |
4060                  N_Subtype_Declaration         =>
4061                return The_Parent;
4062
4063             --  The expression itself is to be wrapped if its parent is a
4064             --  compound statement or any other statement where the expression
4065             --  is known to be scalar
4066
4067             when N_Accept_Alternative               |
4068                  N_Attribute_Definition_Clause      |
4069                  N_Case_Statement                   |
4070                  N_Code_Statement                   |
4071                  N_Delay_Alternative                |
4072                  N_Delay_Until_Statement            |
4073                  N_Delay_Relative_Statement         |
4074                  N_Discriminant_Association         |
4075                  N_Elsif_Part                       |
4076                  N_Entry_Body_Formal_Part           |
4077                  N_Exit_Statement                   |
4078                  N_If_Statement                     |
4079                  N_Iteration_Scheme                 |
4080                  N_Terminate_Alternative            =>
4081                return P;
4082
4083             when N_Attribute_Reference =>
4084
4085                if Is_Procedure_Attribute_Name
4086                     (Attribute_Name (The_Parent))
4087                then
4088                   return The_Parent;
4089                end if;
4090
4091             --  A raise statement can be wrapped. This will arise when the
4092             --  expression in a raise_with_expression uses the secondary
4093             --  stack, for example.
4094
4095             when N_Raise_Statement =>
4096                return The_Parent;
4097
4098             --  If the expression is within the iteration scheme of a loop,
4099             --  we must create a declaration for it, followed by an assignment
4100             --  in order to have a usable statement to wrap.
4101
4102             when N_Loop_Parameter_Specification =>
4103                return Parent (The_Parent);
4104
4105             --  The following nodes contains "dummy calls" which don't need to
4106             --  be wrapped.
4107
4108             when N_Parameter_Specification     |
4109                  N_Discriminant_Specification  |
4110                  N_Component_Declaration       =>
4111                return Empty;
4112
4113             --  The return statement is not to be wrapped when the function
4114             --  itself needs wrapping at the outer-level
4115
4116             when N_Simple_Return_Statement =>
4117                declare
4118                   Applies_To : constant Entity_Id :=
4119                                  Return_Applies_To
4120                                    (Return_Statement_Entity (The_Parent));
4121                   Return_Type : constant Entity_Id := Etype (Applies_To);
4122                begin
4123                   if Requires_Transient_Scope (Return_Type) then
4124                      return Empty;
4125                   else
4126                      return The_Parent;
4127                   end if;
4128                end;
4129
4130             --  If we leave a scope without having been able to find a node to
4131             --  wrap, something is going wrong but this can happen in error
4132             --  situation that are not detected yet (such as a dynamic string
4133             --  in a pragma export)
4134
4135             when N_Subprogram_Body     |
4136                  N_Package_Declaration |
4137                  N_Package_Body        |
4138                  N_Block_Statement     =>
4139                return Empty;
4140
4141             --  Otherwise continue the search
4142
4143             when others =>
4144                null;
4145          end case;
4146       end loop;
4147    end Find_Node_To_Be_Wrapped;
4148
4149    -------------------------------------
4150    -- Get_Global_Pool_For_Access_Type --
4151    -------------------------------------
4152
4153    function Get_Global_Pool_For_Access_Type (T : Entity_Id) return Entity_Id is
4154    begin
4155       --  Access types whose size is smaller than System.Address size can exist
4156       --  only on VMS. We can't use the usual global pool which returns an
4157       --  object of type Address as truncation will make it invalid. To handle
4158       --  this case, VMS has a dedicated global pool that returns addresses
4159       --  that fit into 32 bit accesses.
4160
4161       if Opt.True_VMS_Target and then Esize (T) = 32 then
4162          return RTE (RE_Global_Pool_32_Object);
4163       else
4164          return RTE (RE_Global_Pool_Object);
4165       end if;
4166    end Get_Global_Pool_For_Access_Type;
4167
4168    ----------------------------------
4169    -- Has_New_Controlled_Component --
4170    ----------------------------------
4171
4172    function Has_New_Controlled_Component (E : Entity_Id) return Boolean is
4173       Comp : Entity_Id;
4174
4175    begin
4176       if not Is_Tagged_Type (E) then
4177          return Has_Controlled_Component (E);
4178       elsif not Is_Derived_Type (E) then
4179          return Has_Controlled_Component (E);
4180       end if;
4181
4182       Comp := First_Component (E);
4183       while Present (Comp) loop
4184          if Chars (Comp) = Name_uParent then
4185             null;
4186
4187          elsif Scope (Original_Record_Component (Comp)) = E
4188            and then Needs_Finalization (Etype (Comp))
4189          then
4190             return True;
4191          end if;
4192
4193          Next_Component (Comp);
4194       end loop;
4195
4196       return False;
4197    end Has_New_Controlled_Component;
4198
4199    ---------------------------------
4200    -- Has_Simple_Protected_Object --
4201    ---------------------------------
4202
4203    function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
4204    begin
4205       if Has_Task (T) then
4206          return False;
4207
4208       elsif Is_Simple_Protected_Type (T) then
4209          return True;
4210
4211       elsif Is_Array_Type (T) then
4212          return Has_Simple_Protected_Object (Component_Type (T));
4213
4214       elsif Is_Record_Type (T) then
4215          declare
4216             Comp : Entity_Id;
4217
4218          begin
4219             Comp := First_Component (T);
4220             while Present (Comp) loop
4221                if Has_Simple_Protected_Object (Etype (Comp)) then
4222                   return True;
4223                end if;
4224
4225                Next_Component (Comp);
4226             end loop;
4227
4228             return False;
4229          end;
4230
4231       else
4232          return False;
4233       end if;
4234    end Has_Simple_Protected_Object;
4235
4236    ------------------------------------
4237    -- Insert_Actions_In_Scope_Around --
4238    ------------------------------------
4239
4240    procedure Insert_Actions_In_Scope_Around (N : Node_Id) is
4241       SE     : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
4242       After  : List_Id renames SE.Actions_To_Be_Wrapped_After;
4243       Before : List_Id renames SE.Actions_To_Be_Wrapped_Before;
4244
4245       procedure Process_Transient_Objects
4246         (First_Object : Node_Id;
4247          Last_Object  : Node_Id;
4248          Related_Node : Node_Id);
4249       --  First_Object and Last_Object define a list which contains potential
4250       --  controlled transient objects. Finalization flags are inserted before
4251       --  First_Object and finalization calls are inserted after Last_Object.
4252       --  Related_Node is the node for which transient objects have been
4253       --  created.
4254
4255       -------------------------------
4256       -- Process_Transient_Objects --
4257       -------------------------------
4258
4259       procedure Process_Transient_Objects
4260         (First_Object : Node_Id;
4261          Last_Object  : Node_Id;
4262          Related_Node : Node_Id)
4263       is
4264          Requires_Hooking : constant Boolean :=
4265                               Nkind_In (N, N_Function_Call,
4266                                            N_Procedure_Call_Statement);
4267
4268          Built     : Boolean := False;
4269          Desig_Typ : Entity_Id;
4270          Fin_Block : Node_Id;
4271          Fin_Data  : Finalization_Exception_Data;
4272          Fin_Decls : List_Id;
4273          Last_Fin  : Node_Id := Empty;
4274          Loc       : Source_Ptr;
4275          Obj_Id    : Entity_Id;
4276          Obj_Ref   : Node_Id;
4277          Obj_Typ   : Entity_Id;
4278          Stmt      : Node_Id;
4279          Stmts     : List_Id;
4280          Temp_Id   : Entity_Id;
4281
4282       begin
4283          --  Examine all objects in the list First_Object .. Last_Object
4284
4285          Stmt := First_Object;
4286          while Present (Stmt) loop
4287             if Nkind (Stmt) = N_Object_Declaration
4288               and then Analyzed (Stmt)
4289               and then Is_Finalizable_Transient (Stmt, N)
4290
4291               --  Do not process the node to be wrapped since it will be
4292               --  handled by the enclosing finalizer.
4293
4294               and then Stmt /= Related_Node
4295             then
4296                Loc       := Sloc (Stmt);
4297                Obj_Id    := Defining_Identifier (Stmt);
4298                Obj_Typ   := Base_Type (Etype (Obj_Id));
4299                Desig_Typ := Obj_Typ;
4300
4301                Set_Is_Processed_Transient (Obj_Id);
4302
4303                --  Handle access types
4304
4305                if Is_Access_Type (Desig_Typ) then
4306                   Desig_Typ := Available_View (Designated_Type (Desig_Typ));
4307                end if;
4308
4309                --  Create the necessary entities and declarations the first
4310                --  time around.
4311
4312                if not Built then
4313                   Fin_Decls := New_List;
4314
4315                   Build_Object_Declarations (Fin_Data, Fin_Decls, Loc);
4316                   Insert_List_Before_And_Analyze (First_Object, Fin_Decls);
4317
4318                   Built := True;
4319                end if;
4320
4321                --  Transient variables associated with subprogram calls need
4322                --  extra processing. These variables are usually created right
4323                --  before the call and finalized immediately after the call.
4324                --  If an exception occurs during the call, the clean up code
4325                --  is skipped due to the sudden change in control and the
4326                --  transient is never finalized.
4327
4328                --  To handle this case, such variables are "exported" to the
4329                --  enclosing sequence of statements where their corresponding
4330                --  "hooks" are picked up by the finalization machinery.
4331
4332                if Requires_Hooking then
4333                   declare
4334                      Expr   : Node_Id;
4335                      Ptr_Id : Entity_Id;
4336
4337                   begin
4338                      --  Step 1: Create an access type which provides a
4339                      --  reference to the transient object. Generate:
4340
4341                      --    Ann : access [all] <Desig_Typ>;
4342
4343                      Ptr_Id := Make_Temporary (Loc, 'A');
4344
4345                      Insert_Action (Stmt,
4346                        Make_Full_Type_Declaration (Loc,
4347                          Defining_Identifier => Ptr_Id,
4348                          Type_Definition     =>
4349                            Make_Access_To_Object_Definition (Loc,
4350                              All_Present        =>
4351                                Ekind (Obj_Typ) = E_General_Access_Type,
4352                              Subtype_Indication =>
4353                                New_Reference_To (Desig_Typ, Loc))));
4354
4355                      --  Step 2: Create a temporary which acts as a hook to
4356                      --  the transient object. Generate:
4357
4358                      --    Temp : Ptr_Id := null;
4359
4360                      Temp_Id := Make_Temporary (Loc, 'T');
4361
4362                      Insert_Action (Stmt,
4363                        Make_Object_Declaration (Loc,
4364                          Defining_Identifier => Temp_Id,
4365                          Object_Definition   =>
4366                            New_Reference_To (Ptr_Id, Loc)));
4367
4368                      --  Mark the temporary as a transient hook. This signals
4369                      --  the machinery in Build_Finalizer to recognize this
4370                      --  special case.
4371
4372                      Set_Return_Flag_Or_Transient_Decl (Temp_Id, Stmt);
4373
4374                      --  Step 3: Hook the transient object to the temporary
4375
4376                      if Is_Access_Type (Obj_Typ) then
4377                         Expr :=
4378                           Convert_To (Ptr_Id, New_Reference_To (Obj_Id, Loc));
4379                      else
4380                         Expr :=
4381                           Make_Attribute_Reference (Loc,
4382                             Prefix         => New_Reference_To (Obj_Id, Loc),
4383                             Attribute_Name => Name_Unrestricted_Access);
4384                      end if;
4385
4386                      --  Generate:
4387                      --    Temp := Ptr_Id (Obj_Id);
4388                      --      <or>
4389                      --    Temp := Obj_Id'Unrestricted_Access;
4390
4391                      Insert_After_And_Analyze (Stmt,
4392                        Make_Assignment_Statement (Loc,
4393                          Name       => New_Reference_To (Temp_Id, Loc),
4394                          Expression => Expr));
4395                   end;
4396                end if;
4397
4398                Stmts := New_List;
4399
4400                --  The transient object is about to be finalized by the clean
4401                --  up code following the subprogram call. In order to avoid
4402                --  double finalization, clear the hook.
4403
4404                --  Generate:
4405                --    Temp := null;
4406
4407                if Requires_Hooking then
4408                   Append_To (Stmts,
4409                     Make_Assignment_Statement (Loc,
4410                       Name       => New_Reference_To (Temp_Id, Loc),
4411                       Expression => Make_Null (Loc)));
4412                end if;
4413
4414                --  Generate:
4415                --    [Deep_]Finalize (Obj_Ref);
4416
4417                Obj_Ref := New_Reference_To (Obj_Id, Loc);
4418
4419                if Is_Access_Type (Obj_Typ) then
4420                   Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
4421                end if;
4422
4423                Append_To (Stmts,
4424                  Make_Final_Call (Obj_Ref => Obj_Ref, Typ => Desig_Typ));
4425
4426                --  Generate:
4427                --    [Temp := null;]
4428                --    begin
4429                --       [Deep_]Finalize (Obj_Ref);
4430
4431                --    exception
4432                --       when others =>
4433                --          if not Raised then
4434                --             Raised := True;
4435                --             Save_Occurrence
4436                --               (Enn, Get_Current_Excep.all.all);
4437                --          end if;
4438                --    end;
4439
4440                Fin_Block :=
4441                  Make_Block_Statement (Loc,
4442                    Handled_Statement_Sequence =>
4443                      Make_Handled_Sequence_Of_Statements (Loc,
4444                        Statements => Stmts,
4445                        Exception_Handlers => New_List (
4446                          Build_Exception_Handler (Fin_Data))));
4447
4448                Insert_After_And_Analyze (Last_Object, Fin_Block);
4449
4450                --  The raise statement must be inserted after all the
4451                --  finalization blocks.
4452
4453                if No (Last_Fin) then
4454                   Last_Fin := Fin_Block;
4455                end if;
4456
4457             --  When the associated node is an array object, the expander may
4458             --  sometimes generate a loop and create transient objects inside
4459             --  the loop.
4460
4461             elsif Nkind (Related_Node) = N_Object_Declaration
4462               and then Is_Array_Type
4463                          (Base_Type
4464                            (Etype (Defining_Identifier (Related_Node))))
4465               and then Nkind (Stmt) = N_Loop_Statement
4466             then
4467                declare
4468                   Block_HSS : Node_Id := First (Statements (Stmt));
4469
4470                begin
4471                   --  The loop statements may have been wrapped in a block by
4472                   --  Process_Statements_For_Controlled_Objects, inspect the
4473                   --  handled sequence of statements.
4474
4475                   if Nkind (Block_HSS) = N_Block_Statement
4476                     and then No (Next (Block_HSS))
4477                   then
4478                      Block_HSS := Handled_Statement_Sequence (Block_HSS);
4479
4480                      Process_Transient_Objects
4481                        (First_Object => First (Statements (Block_HSS)),
4482                         Last_Object  => Last (Statements (Block_HSS)),
4483                         Related_Node => Related_Node);
4484
4485                   --  Inspect the statements of the loop
4486
4487                   else
4488                      Process_Transient_Objects
4489                        (First_Object => First (Statements (Stmt)),
4490                         Last_Object  => Last (Statements (Stmt)),
4491                         Related_Node => Related_Node);
4492                   end if;
4493                end;
4494
4495             --  Terminate the scan after the last object has been processed
4496
4497             elsif Stmt = Last_Object then
4498                exit;
4499             end if;
4500
4501             Next (Stmt);
4502          end loop;
4503
4504          --  Generate:
4505          --    if Raised and then not Abort then
4506          --       Raise_From_Controlled_Operation (E);
4507          --    end if;
4508
4509          if Built
4510            and then Present (Last_Fin)
4511          then
4512             Insert_After_And_Analyze (Last_Fin,
4513               Build_Raise_Statement (Fin_Data));
4514          end if;
4515       end Process_Transient_Objects;
4516
4517    --  Start of processing for Insert_Actions_In_Scope_Around
4518
4519    begin
4520       if No (Before) and then No (After) then
4521          return;
4522       end if;
4523
4524       declare
4525          Node_To_Wrap  : constant Node_Id := Node_To_Be_Wrapped;
4526          First_Obj  : Node_Id;
4527          Last_Obj   : Node_Id;
4528          Target     : Node_Id;
4529
4530       begin
4531          --  If the node to be wrapped is the trigger of an asynchronous
4532          --  select, it is not part of a statement list. The actions must be
4533          --  inserted before the select itself, which is part of some list of
4534          --  statements. Note that the triggering alternative includes the
4535          --  triggering statement and an optional statement list. If the node
4536          --  to be wrapped is part of that list, the normal insertion applies.
4537
4538          if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
4539            and then not Is_List_Member (Node_To_Wrap)
4540          then
4541             Target := Parent (Parent (Node_To_Wrap));
4542          else
4543             Target := N;
4544          end if;
4545
4546          First_Obj := Target;
4547          Last_Obj  := Target;
4548
4549          --  Add all actions associated with a transient scope into the main
4550          --  tree. There are several scenarios here:
4551
4552          --       +--- Before ----+        +----- After ---+
4553          --    1) First_Obj ....... Target ........ Last_Obj
4554
4555          --    2) First_Obj ....... Target
4556
4557          --    3)                   Target ........ Last_Obj
4558
4559          if Present (Before) then
4560
4561             --  Flag declarations are inserted before the first object
4562
4563             First_Obj := First (Before);
4564
4565             Insert_List_Before (Target, Before);
4566          end if;
4567
4568          if Present (After) then
4569
4570             --  Finalization calls are inserted after the last object
4571
4572             Last_Obj := Last (After);
4573
4574             Insert_List_After (Target, After);
4575          end if;
4576
4577          --  Check for transient controlled objects associated with Target and
4578          --  generate the appropriate finalization actions for them.
4579
4580          Process_Transient_Objects
4581            (First_Object => First_Obj,
4582             Last_Object  => Last_Obj,
4583             Related_Node => Target);
4584
4585          --  Reset the action lists
4586
4587          if Present (Before) then
4588             Before := No_List;
4589          end if;
4590
4591          if Present (After) then
4592             After := No_List;
4593          end if;
4594       end;
4595    end Insert_Actions_In_Scope_Around;
4596
4597    ------------------------------
4598    -- Is_Simple_Protected_Type --
4599    ------------------------------
4600
4601    function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
4602    begin
4603       return
4604         Is_Protected_Type (T)
4605           and then not Has_Entries (T)
4606           and then Is_RTE (Find_Protection_Type (T), RE_Protection);
4607    end Is_Simple_Protected_Type;
4608
4609    -----------------------
4610    -- Make_Adjust_Call --
4611    -----------------------
4612
4613    function Make_Adjust_Call
4614      (Obj_Ref    : Node_Id;
4615       Typ        : Entity_Id;
4616       For_Parent : Boolean := False) return Node_Id
4617    is
4618       Loc    : constant Source_Ptr := Sloc (Obj_Ref);
4619       Adj_Id : Entity_Id := Empty;
4620       Ref    : Node_Id   := Obj_Ref;
4621       Utyp   : Entity_Id;
4622
4623    begin
4624       --  Recover the proper type which contains Deep_Adjust
4625
4626       if Is_Class_Wide_Type (Typ) then
4627          Utyp := Root_Type (Typ);
4628       else
4629          Utyp := Typ;
4630       end if;
4631
4632       Utyp := Underlying_Type (Base_Type (Utyp));
4633       Set_Assignment_OK (Ref);
4634
4635       --  Deal with non-tagged derivation of private views
4636
4637       if Is_Untagged_Derivation (Typ) then
4638          Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
4639          Ref  := Unchecked_Convert_To (Utyp, Ref);
4640          Set_Assignment_OK (Ref);
4641       end if;
4642
4643       --  When dealing with the completion of a private type, use the base
4644       --  type instead.
4645
4646       if Utyp /= Base_Type (Utyp) then
4647          pragma Assert (Is_Private_Type (Typ));
4648
4649          Utyp := Base_Type (Utyp);
4650          Ref  := Unchecked_Convert_To (Utyp, Ref);
4651       end if;
4652
4653       --  Select the appropriate version of adjust
4654
4655       if For_Parent then
4656          if Has_Controlled_Component (Utyp) then
4657             Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4658          end if;
4659
4660       --  Class-wide types, interfaces and types with controlled components
4661
4662       elsif Is_Class_Wide_Type (Typ)
4663         or else Is_Interface (Typ)
4664         or else Has_Controlled_Component (Utyp)
4665       then
4666          if Is_Tagged_Type (Utyp) then
4667             Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4668          else
4669             Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
4670          end if;
4671
4672       --  Derivations from [Limited_]Controlled
4673
4674       elsif Is_Controlled (Utyp) then
4675          if Has_Controlled_Component (Utyp) then
4676             Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4677          else
4678             Adj_Id := Find_Prim_Op (Utyp, Name_Of (Adjust_Case));
4679          end if;
4680
4681       --  Tagged types
4682
4683       elsif Is_Tagged_Type (Utyp) then
4684          Adj_Id := Find_Prim_Op (Utyp, TSS_Deep_Adjust);
4685
4686       else
4687          raise Program_Error;
4688       end if;
4689
4690       if Present (Adj_Id) then
4691
4692          --  If the object is unanalyzed, set its expected type for use in
4693          --  Convert_View in case an additional conversion is needed.
4694
4695          if No (Etype (Ref))
4696            and then Nkind (Ref) /= N_Unchecked_Type_Conversion
4697          then
4698             Set_Etype (Ref, Typ);
4699          end if;
4700
4701          --  The object reference may need another conversion depending on the
4702          --  type of the formal and that of the actual.
4703
4704          if not Is_Class_Wide_Type (Typ) then
4705             Ref := Convert_View (Adj_Id, Ref);
4706          end if;
4707
4708          return Make_Call (Loc, Adj_Id, New_Copy_Tree (Ref), For_Parent);
4709       else
4710          return Empty;
4711       end if;
4712    end Make_Adjust_Call;
4713
4714    ----------------------
4715    -- Make_Attach_Call --
4716    ----------------------
4717
4718    function Make_Attach_Call
4719      (Obj_Ref : Node_Id;
4720       Ptr_Typ : Entity_Id) return Node_Id
4721    is
4722       pragma Assert (VM_Target /= No_VM);
4723
4724       Loc : constant Source_Ptr := Sloc (Obj_Ref);
4725    begin
4726       return
4727         Make_Procedure_Call_Statement (Loc,
4728           Name                   =>
4729             New_Reference_To (RTE (RE_Attach), Loc),
4730           Parameter_Associations => New_List (
4731             New_Reference_To (Finalization_Master (Ptr_Typ), Loc),
4732             Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4733    end Make_Attach_Call;
4734
4735    ----------------------
4736    -- Make_Detach_Call --
4737    ----------------------
4738
4739    function Make_Detach_Call (Obj_Ref : Node_Id) return Node_Id is
4740       Loc : constant Source_Ptr := Sloc (Obj_Ref);
4741
4742    begin
4743       return
4744         Make_Procedure_Call_Statement (Loc,
4745           Name                   =>
4746             New_Reference_To (RTE (RE_Detach), Loc),
4747           Parameter_Associations => New_List (
4748             Unchecked_Convert_To (RTE (RE_Root_Controlled_Ptr), Obj_Ref)));
4749    end Make_Detach_Call;
4750
4751    ---------------
4752    -- Make_Call --
4753    ---------------
4754
4755    function Make_Call
4756      (Loc        : Source_Ptr;
4757       Proc_Id    : Entity_Id;
4758       Param      : Node_Id;
4759       For_Parent : Boolean := False) return Node_Id
4760    is
4761       Params : constant List_Id := New_List (Param);
4762
4763    begin
4764       --  When creating a call to Deep_Finalize for a _parent field of a
4765       --  derived type, disable the invocation of the nested Finalize by giving
4766       --  the corresponding flag a False value.
4767
4768       if For_Parent then
4769          Append_To (Params, New_Reference_To (Standard_False, Loc));
4770       end if;
4771
4772       return
4773         Make_Procedure_Call_Statement (Loc,
4774           Name                   => New_Reference_To (Proc_Id, Loc),
4775           Parameter_Associations => Params);
4776    end Make_Call;
4777
4778    --------------------------
4779    -- Make_Deep_Array_Body --
4780    --------------------------
4781
4782    function Make_Deep_Array_Body
4783      (Prim : Final_Primitives;
4784       Typ  : Entity_Id) return List_Id
4785    is
4786       function Build_Adjust_Or_Finalize_Statements
4787         (Typ : Entity_Id) return List_Id;
4788       --  Create the statements necessary to adjust or finalize an array of
4789       --  controlled elements. Generate:
4790       --
4791       --    declare
4792       --       Abort  : constant Boolean := Triggered_By_Abort;
4793       --         <or>
4794       --       Abort  : constant Boolean := False;  --  no abort
4795       --
4796       --       E      : Exception_Occurrence;
4797       --       Raised : Boolean := False;
4798       --
4799       --    begin
4800       --       for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
4801       --                 ^--  in the finalization case
4802       --          ...
4803       --          for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
4804       --             begin
4805       --                [Deep_]Adjust / Finalize (V (J1, ..., Jn));
4806       --
4807       --             exception
4808       --                when others =>
4809       --                   if not Raised then
4810       --                      Raised := True;
4811       --                      Save_Occurrence (E, Get_Current_Excep.all.all);
4812       --                   end if;
4813       --             end;
4814       --          end loop;
4815       --          ...
4816       --       end loop;
4817       --
4818       --       if Raised and then not Abort then
4819       --          Raise_From_Controlled_Operation (E);
4820       --       end if;
4821       --    end;
4822
4823       function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
4824       --  Create the statements necessary to initialize an array of controlled
4825       --  elements. Include a mechanism to carry out partial finalization if an
4826       --  exception occurs. Generate:
4827       --
4828       --    declare
4829       --       Counter : Integer := 0;
4830       --
4831       --    begin
4832       --       for J1 in V'Range (1) loop
4833       --          ...
4834       --          for JN in V'Range (N) loop
4835       --             begin
4836       --                [Deep_]Initialize (V (J1, ..., JN));
4837       --
4838       --                Counter := Counter + 1;
4839       --
4840       --             exception
4841       --                when others =>
4842       --                   declare
4843       --                      Abort  : constant Boolean := Triggered_By_Abort;
4844       --                        <or>
4845       --                      Abort  : constant Boolean := False; --  no abort
4846       --                      E      : Exception_Occurence;
4847       --                      Raised : Boolean := False;
4848
4849       --                   begin
4850       --                      Counter :=
4851       --                        V'Length (1) *
4852       --                        V'Length (2) *
4853       --                        ...
4854       --                        V'Length (N) - Counter;
4855
4856       --                      for F1 in reverse V'Range (1) loop
4857       --                         ...
4858       --                         for FN in reverse V'Range (N) loop
4859       --                            if Counter > 0 then
4860       --                               Counter := Counter - 1;
4861       --                            else
4862       --                               begin
4863       --                                  [Deep_]Finalize (V (F1, ..., FN));
4864
4865       --                               exception
4866       --                                  when others =>
4867       --                                     if not Raised then
4868       --                                        Raised := True;
4869       --                                        Save_Occurrence (E,
4870       --                                          Get_Current_Excep.all.all);
4871       --                                     end if;
4872       --                               end;
4873       --                            end if;
4874       --                         end loop;
4875       --                         ...
4876       --                      end loop;
4877       --                   end;
4878       --
4879       --                   if Raised and then not Abort then
4880       --                      Raise_From_Controlled_Operation (E);
4881       --                   end if;
4882       --
4883       --                   raise;
4884       --             end;
4885       --          end loop;
4886       --       end loop;
4887       --    end;
4888
4889       function New_References_To
4890         (L   : List_Id;
4891          Loc : Source_Ptr) return List_Id;
4892       --  Given a list of defining identifiers, return a list of references to
4893       --  the original identifiers, in the same order as they appear.
4894
4895       -----------------------------------------
4896       -- Build_Adjust_Or_Finalize_Statements --
4897       -----------------------------------------
4898
4899       function Build_Adjust_Or_Finalize_Statements
4900         (Typ : Entity_Id) return List_Id
4901       is
4902          Comp_Typ        : constant Entity_Id  := Component_Type (Typ);
4903          Index_List      : constant List_Id    := New_List;
4904          Loc             : constant Source_Ptr := Sloc (Typ);
4905          Num_Dims        : constant Int        := Number_Dimensions (Typ);
4906          Finalizer_Decls : List_Id := No_List;
4907          Finalizer_Data  : Finalization_Exception_Data;
4908          Call            : Node_Id;
4909          Comp_Ref        : Node_Id;
4910          Core_Loop       : Node_Id;
4911          Dim             : Int;
4912          J               : Entity_Id;
4913          Loop_Id         : Entity_Id;
4914          Stmts           : List_Id;
4915
4916          Exceptions_OK : constant Boolean :=
4917                            not Restriction_Active (No_Exception_Propagation);
4918
4919          procedure Build_Indices;
4920          --  Generate the indices used in the dimension loops
4921
4922          -------------------
4923          -- Build_Indices --
4924          -------------------
4925
4926          procedure Build_Indices is
4927          begin
4928             --  Generate the following identifiers:
4929             --    Jnn  -  for initialization
4930
4931             for Dim in 1 .. Num_Dims loop
4932                Append_To (Index_List,
4933                  Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
4934             end loop;
4935          end Build_Indices;
4936
4937       --  Start of processing for Build_Adjust_Or_Finalize_Statements
4938
4939       begin
4940          Finalizer_Decls := New_List;
4941
4942          Build_Indices;
4943          Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
4944
4945          Comp_Ref :=
4946            Make_Indexed_Component (Loc,
4947              Prefix      => Make_Identifier (Loc, Name_V),
4948              Expressions => New_References_To (Index_List, Loc));
4949          Set_Etype (Comp_Ref, Comp_Typ);
4950
4951          --  Generate:
4952          --    [Deep_]Adjust (V (J1, ..., JN))
4953
4954          if Prim = Adjust_Case then
4955             Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4956
4957          --  Generate:
4958          --    [Deep_]Finalize (V (J1, ..., JN))
4959
4960          else pragma Assert (Prim = Finalize_Case);
4961             Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
4962          end if;
4963
4964          --  Generate the block which houses the adjust or finalize call:
4965
4966          --    <adjust or finalize call>;  --  No_Exception_Propagation
4967
4968          --    begin                       --  Exception handlers allowed
4969          --       <adjust or finalize call>
4970
4971          --    exception
4972          --       when others =>
4973          --          if not Raised then
4974          --             Raised := True;
4975          --             Save_Occurrence (E, Get_Current_Excep.all.all);
4976          --          end if;
4977          --    end;
4978
4979          if Exceptions_OK then
4980             Core_Loop :=
4981               Make_Block_Statement (Loc,
4982                 Handled_Statement_Sequence =>
4983                   Make_Handled_Sequence_Of_Statements (Loc,
4984                     Statements         => New_List (Call),
4985                     Exception_Handlers => New_List (
4986                       Build_Exception_Handler (Finalizer_Data))));
4987          else
4988             Core_Loop := Call;
4989          end if;
4990
4991          --  Generate the dimension loops starting from the innermost one
4992
4993          --    for Jnn in [reverse] V'Range (Dim) loop
4994          --       <core loop>
4995          --    end loop;
4996
4997          J := Last (Index_List);
4998          Dim := Num_Dims;
4999          while Present (J) and then Dim > 0 loop
5000             Loop_Id := J;
5001             Prev (J);
5002             Remove (Loop_Id);
5003
5004             Core_Loop :=
5005               Make_Loop_Statement (Loc,
5006                 Iteration_Scheme =>
5007                   Make_Iteration_Scheme (Loc,
5008                     Loop_Parameter_Specification =>
5009                       Make_Loop_Parameter_Specification (Loc,
5010                         Defining_Identifier         => Loop_Id,
5011                         Discrete_Subtype_Definition =>
5012                           Make_Attribute_Reference (Loc,
5013                             Prefix         => Make_Identifier (Loc, Name_V),
5014                             Attribute_Name => Name_Range,
5015                             Expressions    => New_List (
5016                               Make_Integer_Literal (Loc, Dim))),
5017
5018                         Reverse_Present => Prim = Finalize_Case)),
5019
5020                 Statements => New_List (Core_Loop),
5021                 End_Label  => Empty);
5022
5023             Dim := Dim - 1;
5024          end loop;
5025
5026          --  Generate the block which contains the core loop, the declarations
5027          --  of the abort flag, the exception occurrence, the raised flag and
5028          --  the conditional raise:
5029
5030          --    declare
5031          --       Abort  : constant Boolean := Triggered_By_Abort;
5032          --         <or>
5033          --       Abort  : constant Boolean := False;  --  no abort
5034
5035          --       E      : Exception_Occurrence;
5036          --       Raised : Boolean := False;
5037
5038          --    begin
5039          --       <core loop>
5040
5041          --       if Raised and then not Abort then  --  Expection handlers OK
5042          --          Raise_From_Controlled_Operation (E);
5043          --       end if;
5044          --    end;
5045
5046          Stmts := New_List (Core_Loop);
5047
5048          if Exceptions_OK then
5049             Append_To (Stmts,
5050               Build_Raise_Statement (Finalizer_Data));
5051          end if;
5052
5053          return
5054            New_List (
5055              Make_Block_Statement (Loc,
5056                Declarations               =>
5057                  Finalizer_Decls,
5058                Handled_Statement_Sequence =>
5059                  Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5060       end Build_Adjust_Or_Finalize_Statements;
5061
5062       ---------------------------------
5063       -- Build_Initialize_Statements --
5064       ---------------------------------
5065
5066       function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
5067          Comp_Typ        : constant Entity_Id  := Component_Type (Typ);
5068          Final_List      : constant List_Id    := New_List;
5069          Index_List      : constant List_Id    := New_List;
5070          Loc             : constant Source_Ptr := Sloc (Typ);
5071          Num_Dims        : constant Int        := Number_Dimensions (Typ);
5072          Counter_Id      : Entity_Id;
5073          Dim             : Int;
5074          F               : Node_Id;
5075          Fin_Stmt        : Node_Id;
5076          Final_Block     : Node_Id;
5077          Final_Loop      : Node_Id;
5078          Finalizer_Data  : Finalization_Exception_Data;
5079          Finalizer_Decls : List_Id := No_List;
5080          Init_Loop       : Node_Id;
5081          J               : Node_Id;
5082          Loop_Id         : Node_Id;
5083          Stmts           : List_Id;
5084
5085          Exceptions_OK : constant Boolean :=
5086                            not Restriction_Active (No_Exception_Propagation);
5087
5088          function Build_Counter_Assignment return Node_Id;
5089          --  Generate the following assignment:
5090          --    Counter := V'Length (1) *
5091          --               ...
5092          --               V'Length (N) - Counter;
5093
5094          function Build_Finalization_Call return Node_Id;
5095          --  Generate a deep finalization call for an array element
5096
5097          procedure Build_Indices;
5098          --  Generate the initialization and finalization indices used in the
5099          --  dimension loops.
5100
5101          function Build_Initialization_Call return Node_Id;
5102          --  Generate a deep initialization call for an array element
5103
5104          ------------------------------
5105          -- Build_Counter_Assignment --
5106          ------------------------------
5107
5108          function Build_Counter_Assignment return Node_Id is
5109             Dim  : Int;
5110             Expr : Node_Id;
5111
5112          begin
5113             --  Start from the first dimension and generate:
5114             --    V'Length (1)
5115
5116             Dim := 1;
5117             Expr :=
5118               Make_Attribute_Reference (Loc,
5119                 Prefix         => Make_Identifier (Loc, Name_V),
5120                 Attribute_Name => Name_Length,
5121                 Expressions    => New_List (Make_Integer_Literal (Loc, Dim)));
5122
5123             --  Process the rest of the dimensions, generate:
5124             --    Expr * V'Length (N)
5125
5126             Dim := Dim + 1;
5127             while Dim <= Num_Dims loop
5128                Expr :=
5129                  Make_Op_Multiply (Loc,
5130                    Left_Opnd  => Expr,
5131                    Right_Opnd =>
5132                      Make_Attribute_Reference (Loc,
5133                        Prefix         => Make_Identifier (Loc, Name_V),
5134                        Attribute_Name => Name_Length,
5135                        Expressions    => New_List (
5136                          Make_Integer_Literal (Loc, Dim))));
5137
5138                Dim := Dim + 1;
5139             end loop;
5140
5141             --  Generate:
5142             --    Counter := Expr - Counter;
5143
5144             return
5145               Make_Assignment_Statement (Loc,
5146                 Name       => New_Reference_To (Counter_Id, Loc),
5147                 Expression =>
5148                   Make_Op_Subtract (Loc,
5149                     Left_Opnd  => Expr,
5150                     Right_Opnd => New_Reference_To (Counter_Id, Loc)));
5151          end Build_Counter_Assignment;
5152
5153          -----------------------------
5154          -- Build_Finalization_Call --
5155          -----------------------------
5156
5157          function Build_Finalization_Call return Node_Id is
5158             Comp_Ref : constant Node_Id :=
5159                          Make_Indexed_Component (Loc,
5160                            Prefix      => Make_Identifier (Loc, Name_V),
5161                            Expressions => New_References_To (Final_List, Loc));
5162
5163          begin
5164             Set_Etype (Comp_Ref, Comp_Typ);
5165
5166             --  Generate:
5167             --    [Deep_]Finalize (V);
5168
5169             return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5170          end Build_Finalization_Call;
5171
5172          -------------------
5173          -- Build_Indices --
5174          -------------------
5175
5176          procedure Build_Indices is
5177          begin
5178             --  Generate the following identifiers:
5179             --    Jnn  -  for initialization
5180             --    Fnn  -  for finalization
5181
5182             for Dim in 1 .. Num_Dims loop
5183                Append_To (Index_List,
5184                  Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
5185
5186                Append_To (Final_List,
5187                  Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
5188             end loop;
5189          end Build_Indices;
5190
5191          -------------------------------
5192          -- Build_Initialization_Call --
5193          -------------------------------
5194
5195          function Build_Initialization_Call return Node_Id is
5196             Comp_Ref : constant Node_Id :=
5197                          Make_Indexed_Component (Loc,
5198                            Prefix      => Make_Identifier (Loc, Name_V),
5199                            Expressions => New_References_To (Index_List, Loc));
5200
5201          begin
5202             Set_Etype (Comp_Ref, Comp_Typ);
5203
5204             --  Generate:
5205             --    [Deep_]Initialize (V (J1, ..., JN));
5206
5207             return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
5208          end Build_Initialization_Call;
5209
5210       --  Start of processing for Build_Initialize_Statements
5211
5212       begin
5213          Counter_Id := Make_Temporary (Loc, 'C');
5214          Finalizer_Decls := New_List;
5215
5216          Build_Indices;
5217          Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
5218
5219          --  Generate the block which houses the finalization call, the index
5220          --  guard and the handler which triggers Program_Error later on.
5221
5222          --    if Counter > 0 then
5223          --       Counter := Counter - 1;
5224          --    else
5225          --       [Deep_]Finalize (V (F1, ..., FN));  --  No_Except_Propagation
5226
5227          --       begin                               --  Exceptions allowed
5228          --          [Deep_]Finalize (V (F1, ..., FN));
5229          --       exception
5230          --          when others =>
5231          --             if not Raised then
5232          --                Raised := True;
5233          --                Save_Occurrence (E, Get_Current_Excep.all.all);
5234          --             end if;
5235          --       end;
5236          --    end if;
5237
5238          if Exceptions_OK then
5239             Fin_Stmt :=
5240               Make_Block_Statement (Loc,
5241                 Handled_Statement_Sequence =>
5242                   Make_Handled_Sequence_Of_Statements (Loc,
5243                     Statements         => New_List (Build_Finalization_Call),
5244                     Exception_Handlers => New_List (
5245                       Build_Exception_Handler (Finalizer_Data))));
5246          else
5247             Fin_Stmt := Build_Finalization_Call;
5248          end if;
5249
5250          --  This is the core of the loop, the dimension iterators are added
5251          --  one by one in reverse.
5252
5253          Final_Loop :=
5254            Make_If_Statement (Loc,
5255              Condition =>
5256                Make_Op_Gt (Loc,
5257                  Left_Opnd  => New_Reference_To (Counter_Id, Loc),
5258                  Right_Opnd => Make_Integer_Literal (Loc, 0)),
5259
5260              Then_Statements => New_List (
5261                Make_Assignment_Statement (Loc,
5262                  Name       => New_Reference_To (Counter_Id, Loc),
5263                  Expression =>
5264                    Make_Op_Subtract (Loc,
5265                      Left_Opnd  => New_Reference_To (Counter_Id, Loc),
5266                      Right_Opnd => Make_Integer_Literal (Loc, 1)))),
5267
5268              Else_Statements => New_List (Fin_Stmt));
5269
5270          --  Generate all finalization loops starting from the innermost
5271          --  dimension.
5272
5273          --    for Fnn in reverse V'Range (Dim) loop
5274          --       <final loop>
5275          --    end loop;
5276
5277          F := Last (Final_List);
5278          Dim := Num_Dims;
5279          while Present (F) and then Dim > 0 loop
5280             Loop_Id := F;
5281             Prev (F);
5282             Remove (Loop_Id);
5283
5284             Final_Loop :=
5285               Make_Loop_Statement (Loc,
5286                 Iteration_Scheme =>
5287                   Make_Iteration_Scheme (Loc,
5288                     Loop_Parameter_Specification =>
5289                       Make_Loop_Parameter_Specification (Loc,
5290                         Defining_Identifier => Loop_Id,
5291                         Discrete_Subtype_Definition =>
5292                           Make_Attribute_Reference (Loc,
5293                             Prefix         => Make_Identifier (Loc, Name_V),
5294                             Attribute_Name => Name_Range,
5295                             Expressions    => New_List (
5296                               Make_Integer_Literal (Loc, Dim))),
5297
5298                         Reverse_Present => True)),
5299
5300                 Statements => New_List (Final_Loop),
5301                 End_Label => Empty);
5302
5303             Dim := Dim - 1;
5304          end loop;
5305
5306          --  Generate the block which contains the finalization loops, the
5307          --  declarations of the abort flag, the exception occurrence, the
5308          --  raised flag and the conditional raise.
5309
5310          --    declare
5311          --       Abort  : constant Boolean := Triggered_By_Abort;
5312          --         <or>
5313          --       Abort  : constant Boolean := False;  --  no abort
5314
5315          --       E      : Exception_Occurrence;
5316          --       Raised : Boolean := False;
5317
5318          --    begin
5319          --       Counter :=
5320          --         V'Length (1) *
5321          --         ...
5322          --         V'Length (N) - Counter;
5323
5324          --       <final loop>
5325
5326          --       if Raised and then not Abort then  --  Exception handlers OK
5327          --          Raise_From_Controlled_Operation (E);
5328          --       end if;
5329
5330          --       raise;  --  Exception handlers OK
5331          --    end;
5332
5333          Stmts := New_List (Build_Counter_Assignment, Final_Loop);
5334
5335          if Exceptions_OK then
5336             Append_To (Stmts,
5337               Build_Raise_Statement (Finalizer_Data));
5338             Append_To (Stmts, Make_Raise_Statement (Loc));
5339          end if;
5340
5341          Final_Block :=
5342            Make_Block_Statement (Loc,
5343              Declarations               =>
5344                Finalizer_Decls,
5345              Handled_Statement_Sequence =>
5346                Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
5347
5348          --  Generate the block which contains the initialization call and
5349          --  the partial finalization code.
5350
5351          --    begin
5352          --       [Deep_]Initialize (V (J1, ..., JN));
5353
5354          --       Counter := Counter + 1;
5355
5356          --    exception
5357          --       when others =>
5358          --          <finalization code>
5359          --    end;
5360
5361          Init_Loop :=
5362            Make_Block_Statement (Loc,
5363              Handled_Statement_Sequence =>
5364                Make_Handled_Sequence_Of_Statements (Loc,
5365                  Statements         => New_List (Build_Initialization_Call),
5366                  Exception_Handlers => New_List (
5367                    Make_Exception_Handler (Loc,
5368                      Exception_Choices => New_List (Make_Others_Choice (Loc)),
5369                      Statements        => New_List (Final_Block)))));
5370
5371          Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
5372            Make_Assignment_Statement (Loc,
5373              Name       => New_Reference_To (Counter_Id, Loc),
5374              Expression =>
5375                Make_Op_Add (Loc,
5376                  Left_Opnd  => New_Reference_To (Counter_Id, Loc),
5377                  Right_Opnd => Make_Integer_Literal (Loc, 1))));
5378
5379          --  Generate all initialization loops starting from the innermost
5380          --  dimension.
5381
5382          --    for Jnn in V'Range (Dim) loop
5383          --       <init loop>
5384          --    end loop;
5385
5386          J := Last (Index_List);
5387          Dim := Num_Dims;
5388          while Present (J) and then Dim > 0 loop
5389             Loop_Id := J;
5390             Prev (J);
5391             Remove (Loop_Id);
5392
5393             Init_Loop :=
5394               Make_Loop_Statement (Loc,
5395                 Iteration_Scheme =>
5396                   Make_Iteration_Scheme (Loc,
5397                     Loop_Parameter_Specification =>
5398                       Make_Loop_Parameter_Specification (Loc,
5399                         Defining_Identifier => Loop_Id,
5400                         Discrete_Subtype_Definition =>
5401                           Make_Attribute_Reference (Loc,
5402                             Prefix         => Make_Identifier (Loc, Name_V),
5403                             Attribute_Name => Name_Range,
5404                             Expressions    => New_List (
5405                               Make_Integer_Literal (Loc, Dim))))),
5406
5407                 Statements => New_List (Init_Loop),
5408                 End_Label => Empty);
5409
5410             Dim := Dim - 1;
5411          end loop;
5412
5413          --  Generate the block which contains the counter variable and the
5414          --  initialization loops.
5415
5416          --    declare
5417          --       Counter : Integer := 0;
5418          --    begin
5419          --       <init loop>
5420          --    end;
5421
5422          return
5423            New_List (
5424              Make_Block_Statement (Loc,
5425                Declarations               => New_List (
5426                  Make_Object_Declaration (Loc,
5427                    Defining_Identifier => Counter_Id,
5428                    Object_Definition   =>
5429                      New_Reference_To (Standard_Integer, Loc),
5430                    Expression          => Make_Integer_Literal (Loc, 0))),
5431
5432                Handled_Statement_Sequence =>
5433                  Make_Handled_Sequence_Of_Statements (Loc,
5434                    Statements => New_List (Init_Loop))));
5435       end Build_Initialize_Statements;
5436
5437       -----------------------
5438       -- New_References_To --
5439       -----------------------
5440
5441       function New_References_To
5442         (L   : List_Id;
5443          Loc : Source_Ptr) return List_Id
5444       is
5445          Refs : constant List_Id := New_List;
5446          Id   : Node_Id;
5447
5448       begin
5449          Id := First (L);
5450          while Present (Id) loop
5451             Append_To (Refs, New_Reference_To (Id, Loc));
5452             Next (Id);
5453          end loop;
5454
5455          return Refs;
5456       end New_References_To;
5457
5458    --  Start of processing for Make_Deep_Array_Body
5459
5460    begin
5461       case Prim is
5462          when Address_Case =>
5463             return Make_Finalize_Address_Stmts (Typ);
5464
5465          when Adjust_Case   |
5466               Finalize_Case =>
5467             return Build_Adjust_Or_Finalize_Statements (Typ);
5468
5469          when Initialize_Case =>
5470             return Build_Initialize_Statements (Typ);
5471       end case;
5472    end Make_Deep_Array_Body;
5473
5474    --------------------
5475    -- Make_Deep_Proc --
5476    --------------------
5477
5478    function Make_Deep_Proc
5479      (Prim  : Final_Primitives;
5480       Typ   : Entity_Id;
5481       Stmts : List_Id) return Entity_Id
5482    is
5483       Loc     : constant Source_Ptr := Sloc (Typ);
5484       Formals : List_Id;
5485       Proc_Id : Entity_Id;
5486
5487    begin
5488       --  Create the object formal, generate:
5489       --    V : System.Address
5490
5491       if Prim = Address_Case then
5492          Formals := New_List (
5493            Make_Parameter_Specification (Loc,
5494              Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5495              Parameter_Type      => New_Reference_To (RTE (RE_Address), Loc)));
5496
5497       --  Default case
5498
5499       else
5500          --  V : in out Typ
5501
5502          Formals := New_List (
5503            Make_Parameter_Specification (Loc,
5504              Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
5505              In_Present          => True,
5506              Out_Present         => True,
5507              Parameter_Type      => New_Reference_To (Typ, Loc)));
5508
5509          --  F : Boolean := True
5510
5511          if Prim = Adjust_Case
5512            or else Prim = Finalize_Case
5513          then
5514             Append_To (Formals,
5515               Make_Parameter_Specification (Loc,
5516                 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
5517                 Parameter_Type      =>
5518                   New_Reference_To (Standard_Boolean, Loc),
5519                 Expression          =>
5520                   New_Reference_To (Standard_True, Loc)));
5521          end if;
5522       end if;
5523
5524       Proc_Id :=
5525         Make_Defining_Identifier (Loc,
5526           Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
5527
5528       --  Generate:
5529       --    procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
5530       --    begin
5531       --       <stmts>
5532       --    exception                --  Finalize and Adjust cases only
5533       --       raise Program_Error;
5534       --    end Deep_Initialize / Adjust / Finalize;
5535
5536       --       or
5537
5538       --    procedure Finalize_Address (V : System.Address) is
5539       --    begin
5540       --       <stmts>
5541       --    end Finalize_Address;
5542
5543       Discard_Node (
5544         Make_Subprogram_Body (Loc,
5545           Specification =>
5546             Make_Procedure_Specification (Loc,
5547               Defining_Unit_Name       => Proc_Id,
5548               Parameter_Specifications => Formals),
5549
5550           Declarations => Empty_List,
5551
5552           Handled_Statement_Sequence =>
5553             Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
5554
5555       return Proc_Id;
5556    end Make_Deep_Proc;
5557
5558    ---------------------------
5559    -- Make_Deep_Record_Body --
5560    ---------------------------
5561
5562    function Make_Deep_Record_Body
5563      (Prim     : Final_Primitives;
5564       Typ      : Entity_Id;
5565       Is_Local : Boolean := False) return List_Id
5566    is
5567       function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
5568       --  Build the statements necessary to adjust a record type. The type may
5569       --  have discriminants and contain variant parts. Generate:
5570       --
5571       --    begin
5572       --       begin
5573       --          [Deep_]Adjust (V.Comp_1);
5574       --       exception
5575       --          when Id : others =>
5576       --             if not Raised then
5577       --                Raised := True;
5578       --                Save_Occurrence (E, Get_Current_Excep.all.all);
5579       --             end if;
5580       --       end;
5581       --       .  .  .
5582       --       begin
5583       --          [Deep_]Adjust (V.Comp_N);
5584       --       exception
5585       --          when Id : others =>
5586       --             if not Raised then
5587       --                Raised := True;
5588       --                Save_Occurrence (E, Get_Current_Excep.all.all);
5589       --             end if;
5590       --       end;
5591       --
5592       --       begin
5593       --          Deep_Adjust (V._parent, False);  --  If applicable
5594       --       exception
5595       --          when Id : others =>
5596       --             if not Raised then
5597       --                Raised := True;
5598       --                Save_Occurrence (E, Get_Current_Excep.all.all);
5599       --             end if;
5600       --       end;
5601       --
5602       --       if F then
5603       --          begin
5604       --             Adjust (V);  --  If applicable
5605       --          exception
5606       --             when others =>
5607       --                if not Raised then
5608       --                   Raised := True;
5609       --                   Save_Occurence (E, Get_Current_Excep.all.all);
5610       --                end if;
5611       --          end;
5612       --       end if;
5613       --
5614       --       if Raised and then not Abort then
5615       --          Raise_From_Controlled_Operation (E);
5616       --       end if;
5617       --    end;
5618
5619       function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
5620       --  Build the statements necessary to finalize a record type. The type
5621       --  may have discriminants and contain variant parts. Generate:
5622       --
5623       --    declare
5624       --       Abort  : constant Boolean := Triggered_By_Abort;
5625       --         <or>
5626       --       Abort  : constant Boolean := False;  --  no abort
5627       --       E      : Exception_Occurence;
5628       --       Raised : Boolean := False;
5629       --
5630       --    begin
5631       --       if F then
5632       --          begin
5633       --             Finalize (V);  --  If applicable
5634       --          exception
5635       --             when others =>
5636       --                if not Raised then
5637       --                   Raised := True;
5638       --                   Save_Occurence (E, Get_Current_Excep.all.all);
5639       --                end if;
5640       --          end;
5641       --       end if;
5642       --
5643       --       case Variant_1 is
5644       --          when Value_1 =>
5645       --             case State_Counter_N =>  --  If Is_Local is enabled
5646       --                when N =>                 .
5647       --                   goto LN;               .
5648       --                ...                       .
5649       --                when 1 =>                 .
5650       --                   goto L1;               .
5651       --                when others =>            .
5652       --                   goto L0;               .
5653       --             end case;                    .
5654       --
5655       --             <<LN>>                   --  If Is_Local is enabled
5656       --             begin
5657       --                [Deep_]Finalize (V.Comp_N);
5658       --             exception
5659       --                when others =>
5660       --                   if not Raised then
5661       --                      Raised := True;
5662       --                      Save_Occurence (E, Get_Current_Excep.all.all);
5663       --                   end if;
5664       --             end;
5665       --             .  .  .
5666       --             <<L1>>
5667       --             begin
5668       --                [Deep_]Finalize (V.Comp_1);
5669       --             exception
5670       --                when others =>
5671       --                   if not Raised then
5672       --                      Raised := True;
5673       --                      Save_Occurence (E, Get_Current_Excep.all.all);
5674       --                   end if;
5675       --             end;
5676       --             <<L0>>
5677       --       end case;
5678       --
5679       --       case State_Counter_1 =>  --  If Is_Local is enabled
5680       --          when M =>                 .
5681       --             goto LM;               .
5682       --       ...
5683       --
5684       --       begin
5685       --          Deep_Finalize (V._parent, False);  --  If applicable
5686       --       exception
5687       --          when Id : others =>
5688       --             if not Raised then
5689       --                Raised := True;
5690       --                Save_Occurrence (E, Get_Current_Excep.all.all);
5691       --             end if;
5692       --       end;
5693       --
5694       --       if Raised and then not Abort then
5695       --          Raise_From_Controlled_Operation (E);
5696       --       end if;
5697       --    end;
5698
5699       function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
5700       --  Given a derived tagged type Typ, traverse all components, find field
5701       --  _parent and return its type.
5702
5703       procedure Preprocess_Components
5704         (Comps     : Node_Id;
5705          Num_Comps : out Int;
5706          Has_POC   : out Boolean);
5707       --  Examine all components in component list Comps, count all controlled
5708       --  components and determine whether at least one of them is per-object
5709       --  constrained. Component _parent is always skipped.
5710
5711       -----------------------------
5712       -- Build_Adjust_Statements --
5713       -----------------------------
5714
5715       function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
5716          Loc             : constant Source_Ptr := Sloc (Typ);
5717          Typ_Def         : constant Node_Id := Type_Definition (Parent (Typ));
5718          Bod_Stmts       : List_Id;
5719          Finalizer_Data  : Finalization_Exception_Data;
5720          Finalizer_Decls : List_Id := No_List;
5721          Rec_Def         : Node_Id;
5722          Var_Case        : Node_Id;
5723
5724          Exceptions_OK : constant Boolean :=
5725                            not Restriction_Active (No_Exception_Propagation);
5726
5727          function Process_Component_List_For_Adjust
5728            (Comps : Node_Id) return List_Id;
5729          --  Build all necessary adjust statements for a single component list
5730
5731          ---------------------------------------
5732          -- Process_Component_List_For_Adjust --
5733          ---------------------------------------
5734
5735          function Process_Component_List_For_Adjust
5736            (Comps : Node_Id) return List_Id
5737          is
5738             Stmts     : constant List_Id := New_List;
5739             Decl      : Node_Id;
5740             Decl_Id   : Entity_Id;
5741             Decl_Typ  : Entity_Id;
5742             Has_POC   : Boolean;
5743             Num_Comps : Int;
5744
5745             procedure Process_Component_For_Adjust (Decl : Node_Id);
5746             --  Process the declaration of a single controlled component
5747
5748             ----------------------------------
5749             -- Process_Component_For_Adjust --
5750             ----------------------------------
5751
5752             procedure Process_Component_For_Adjust (Decl : Node_Id) is
5753                Id       : constant Entity_Id := Defining_Identifier (Decl);
5754                Typ      : constant Entity_Id := Etype (Id);
5755                Adj_Stmt : Node_Id;
5756
5757             begin
5758                --  Generate:
5759                --    [Deep_]Adjust (V.Id);  --  No_Exception_Propagation
5760
5761                --    begin                  --  Exception handlers allowed
5762                --       [Deep_]Adjust (V.Id);
5763                --    exception
5764                --       when others =>
5765                --          if not Raised then
5766                --             Raised := True;
5767                --             Save_Occurrence (E, Get_Current_Excep.all.all);
5768                --          end if;
5769                --    end;
5770
5771                Adj_Stmt :=
5772                  Make_Adjust_Call (
5773                    Obj_Ref =>
5774                      Make_Selected_Component (Loc,
5775                        Prefix        => Make_Identifier (Loc, Name_V),
5776                        Selector_Name => Make_Identifier (Loc, Chars (Id))),
5777                    Typ     => Typ);
5778
5779                if Exceptions_OK then
5780                   Adj_Stmt :=
5781                     Make_Block_Statement (Loc,
5782                       Handled_Statement_Sequence =>
5783                         Make_Handled_Sequence_Of_Statements (Loc,
5784                           Statements         => New_List (Adj_Stmt),
5785                           Exception_Handlers => New_List (
5786                             Build_Exception_Handler (Finalizer_Data))));
5787                end if;
5788
5789                Append_To (Stmts, Adj_Stmt);
5790             end Process_Component_For_Adjust;
5791
5792          --  Start of processing for Process_Component_List_For_Adjust
5793
5794          begin
5795             --  Perform an initial check, determine the number of controlled
5796             --  components in the current list and whether at least one of them
5797             --  is per-object constrained.
5798
5799             Preprocess_Components (Comps, Num_Comps, Has_POC);
5800
5801             --  The processing in this routine is done in the following order:
5802             --    1) Regular components
5803             --    2) Per-object constrained components
5804             --    3) Variant parts
5805
5806             if Num_Comps > 0 then
5807
5808                --  Process all regular components in order of declarations
5809
5810                Decl := First_Non_Pragma (Component_Items (Comps));
5811                while Present (Decl) loop
5812                   Decl_Id  := Defining_Identifier (Decl);
5813                   Decl_Typ := Etype (Decl_Id);
5814
5815                   --  Skip _parent as well as per-object constrained components
5816
5817                   if Chars (Decl_Id) /= Name_uParent
5818                     and then Needs_Finalization (Decl_Typ)
5819                   then
5820                      if Has_Access_Constraint (Decl_Id)
5821                        and then No (Expression (Decl))
5822                      then
5823                         null;
5824                      else
5825                         Process_Component_For_Adjust (Decl);
5826                      end if;
5827                   end if;
5828
5829                   Next_Non_Pragma (Decl);
5830                end loop;
5831
5832                --  Process all per-object constrained components in order of
5833                --  declarations.
5834
5835                if Has_POC then
5836                   Decl := First_Non_Pragma (Component_Items (Comps));
5837                   while Present (Decl) loop
5838                      Decl_Id  := Defining_Identifier (Decl);
5839                      Decl_Typ := Etype (Decl_Id);
5840
5841                      --  Skip _parent
5842
5843                      if Chars (Decl_Id) /= Name_uParent
5844                        and then Needs_Finalization (Decl_Typ)
5845                        and then Has_Access_Constraint (Decl_Id)
5846                        and then No (Expression (Decl))
5847                      then
5848                         Process_Component_For_Adjust (Decl);
5849                      end if;
5850
5851                      Next_Non_Pragma (Decl);
5852                   end loop;
5853                end if;
5854             end if;
5855
5856             --  Process all variants, if any
5857
5858             Var_Case := Empty;
5859             if Present (Variant_Part (Comps)) then
5860                declare
5861                   Var_Alts : constant List_Id := New_List;
5862                   Var      : Node_Id;
5863
5864                begin
5865                   Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
5866                   while Present (Var) loop
5867
5868                      --  Generate:
5869                      --     when <discrete choices> =>
5870                      --        <adjust statements>
5871
5872                      Append_To (Var_Alts,
5873                        Make_Case_Statement_Alternative (Loc,
5874                          Discrete_Choices =>
5875                            New_Copy_List (Discrete_Choices (Var)),
5876                          Statements       =>
5877                            Process_Component_List_For_Adjust (
5878                              Component_List (Var))));
5879
5880                      Next_Non_Pragma (Var);
5881                   end loop;
5882
5883                   --  Generate:
5884                   --     case V.<discriminant> is
5885                   --        when <discrete choices 1> =>
5886                   --           <adjust statements 1>
5887                   --        ...
5888                   --        when <discrete choices N> =>
5889                   --           <adjust statements N>
5890                   --     end case;
5891
5892                   Var_Case :=
5893                     Make_Case_Statement (Loc,
5894                       Expression =>
5895                         Make_Selected_Component (Loc,
5896                           Prefix        => Make_Identifier (Loc, Name_V),
5897                           Selector_Name =>
5898                             Make_Identifier (Loc,
5899                               Chars => Chars (Name (Variant_Part (Comps))))),
5900                       Alternatives => Var_Alts);
5901                end;
5902             end if;
5903
5904             --  Add the variant case statement to the list of statements
5905
5906             if Present (Var_Case) then
5907                Append_To (Stmts, Var_Case);
5908             end if;
5909
5910             --  If the component list did not have any controlled components
5911             --  nor variants, return null.
5912
5913             if Is_Empty_List (Stmts) then
5914                Append_To (Stmts, Make_Null_Statement (Loc));
5915             end if;
5916
5917             return Stmts;
5918          end Process_Component_List_For_Adjust;
5919
5920       --  Start of processing for Build_Adjust_Statements
5921
5922       begin
5923          Finalizer_Decls := New_List;
5924          Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
5925
5926          if Nkind (Typ_Def) = N_Derived_Type_Definition then
5927             Rec_Def := Record_Extension_Part (Typ_Def);
5928          else
5929             Rec_Def := Typ_Def;
5930          end if;
5931
5932          --  Create an adjust sequence for all record components
5933
5934          if Present (Component_List (Rec_Def)) then
5935             Bod_Stmts :=
5936               Process_Component_List_For_Adjust (Component_List (Rec_Def));
5937          end if;
5938
5939          --  A derived record type must adjust all inherited components. This
5940          --  action poses the following problem:
5941
5942          --    procedure Deep_Adjust (Obj : in out Parent_Typ) is
5943          --    begin
5944          --       Adjust (Obj);
5945          --       ...
5946
5947          --    procedure Deep_Adjust (Obj : in out Derived_Typ) is
5948          --    begin
5949          --       Deep_Adjust (Obj._parent);
5950          --       ...
5951          --       Adjust (Obj);
5952          --       ...
5953
5954          --  Adjusting the derived type will invoke Adjust of the parent and
5955          --  then that of the derived type. This is undesirable because both
5956          --  routines may modify shared components. Only the Adjust of the
5957          --  derived type should be invoked.
5958
5959          --  To prevent this double adjustment of shared components,
5960          --  Deep_Adjust uses a flag to control the invocation of Adjust:
5961
5962          --    procedure Deep_Adjust
5963          --      (Obj  : in out Some_Type;
5964          --       Flag : Boolean := True)
5965          --    is
5966          --    begin
5967          --       if Flag then
5968          --          Adjust (Obj);
5969          --       end if;
5970          --       ...
5971
5972          --  When Deep_Adjust is invokes for field _parent, a value of False is
5973          --  provided for the flag:
5974
5975          --    Deep_Adjust (Obj._parent, False);
5976
5977          if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
5978             declare
5979                Par_Typ  : constant Entity_Id := Parent_Field_Type (Typ);
5980                Adj_Stmt : Node_Id;
5981                Call     : Node_Id;
5982
5983             begin
5984                if Needs_Finalization (Par_Typ) then
5985                   Call :=
5986                     Make_Adjust_Call
5987                       (Obj_Ref    =>
5988                          Make_Selected_Component (Loc,
5989                            Prefix        => Make_Identifier (Loc, Name_V),
5990                            Selector_Name =>
5991                              Make_Identifier (Loc, Name_uParent)),
5992                        Typ        => Par_Typ,
5993                        For_Parent => True);
5994
5995                   --  Generate:
5996                   --    Deep_Adjust (V._parent, False);  --  No_Except_Propagat
5997
5998                   --    begin                            --  Exceptions OK
5999                   --       Deep_Adjust (V._parent, False);
6000                   --    exception
6001                   --       when Id : others =>
6002                   --          if not Raised then
6003                   --             Raised := True;
6004                   --             Save_Occurrence (E,
6005                   --               Get_Current_Excep.all.all);
6006                   --          end if;
6007                   --    end;
6008
6009                   if Present (Call) then
6010                      Adj_Stmt := Call;
6011
6012                      if Exceptions_OK then
6013                         Adj_Stmt :=
6014                           Make_Block_Statement (Loc,
6015                             Handled_Statement_Sequence =>
6016                               Make_Handled_Sequence_Of_Statements (Loc,
6017                                 Statements         => New_List (Adj_Stmt),
6018                                 Exception_Handlers => New_List (
6019                                   Build_Exception_Handler (Finalizer_Data))));
6020                      end if;
6021
6022                      Prepend_To (Bod_Stmts, Adj_Stmt);
6023                   end if;
6024                end if;
6025             end;
6026          end if;
6027
6028          --  Adjust the object. This action must be performed last after all
6029          --  components have been adjusted.
6030
6031          if Is_Controlled (Typ) then
6032             declare
6033                Adj_Stmt : Node_Id;
6034                Proc     : Entity_Id;
6035
6036             begin
6037                Proc := Find_Prim_Op (Typ, Name_Adjust);
6038
6039                --  Generate:
6040                --    if F then
6041                --       Adjust (V);  --  No_Exception_Propagation
6042
6043                --       begin        --  Exception handlers allowed
6044                --          Adjust (V);
6045                --       exception
6046                --          when others =>
6047                --             if not Raised then
6048                --                Raised := True;
6049                --                Save_Occurrence (E,
6050                --                  Get_Current_Excep.all.all);
6051                --             end if;
6052                --       end;
6053                --    end if;
6054
6055                if Present (Proc) then
6056                   Adj_Stmt :=
6057                     Make_Procedure_Call_Statement (Loc,
6058                       Name                   => New_Reference_To (Proc, Loc),
6059                       Parameter_Associations => New_List (
6060                         Make_Identifier (Loc, Name_V)));
6061
6062                   if Exceptions_OK then
6063                      Adj_Stmt :=
6064                        Make_Block_Statement (Loc,
6065                          Handled_Statement_Sequence =>
6066                            Make_Handled_Sequence_Of_Statements (Loc,
6067                              Statements         => New_List (Adj_Stmt),
6068                              Exception_Handlers => New_List (
6069                                Build_Exception_Handler
6070                                  (Finalizer_Data))));
6071                   end if;
6072
6073                   Append_To (Bod_Stmts,
6074                     Make_If_Statement (Loc,
6075                       Condition       => Make_Identifier (Loc, Name_F),
6076                       Then_Statements => New_List (Adj_Stmt)));
6077                end if;
6078             end;
6079          end if;
6080
6081          --  At this point either all adjustment statements have been generated
6082          --  or the type is not controlled.
6083
6084          if Is_Empty_List (Bod_Stmts) then
6085             Append_To (Bod_Stmts, Make_Null_Statement (Loc));
6086
6087             return Bod_Stmts;
6088
6089          --  Generate:
6090          --    declare
6091          --       Abort  : constant Boolean := Triggered_By_Abort;
6092          --         <or>
6093          --       Abort  : constant Boolean := False;  --  no abort
6094
6095          --       E      : Exception_Occurence;
6096          --       Raised : Boolean := False;
6097
6098          --    begin
6099          --       <adjust statements>
6100
6101          --       if Raised and then not Abort then
6102          --          Raise_From_Controlled_Operation (E);
6103          --       end if;
6104          --    end;
6105
6106          else
6107             if Exceptions_OK then
6108                Append_To (Bod_Stmts,
6109                  Build_Raise_Statement (Finalizer_Data));
6110             end if;
6111
6112             return
6113               New_List (
6114                 Make_Block_Statement (Loc,
6115                   Declarations               =>
6116                     Finalizer_Decls,
6117                   Handled_Statement_Sequence =>
6118                     Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6119          end if;
6120       end Build_Adjust_Statements;
6121
6122       -------------------------------
6123       -- Build_Finalize_Statements --
6124       -------------------------------
6125
6126       function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
6127          Loc             : constant Source_Ptr := Sloc (Typ);
6128          Typ_Def         : constant Node_Id := Type_Definition (Parent (Typ));
6129          Bod_Stmts       : List_Id;
6130          Counter         : Int := 0;
6131          Finalizer_Data  : Finalization_Exception_Data;
6132          Finalizer_Decls : List_Id := No_List;
6133          Rec_Def         : Node_Id;
6134          Var_Case        : Node_Id;
6135
6136          Exceptions_OK : constant Boolean :=
6137                            not Restriction_Active (No_Exception_Propagation);
6138
6139          function Process_Component_List_For_Finalize
6140            (Comps : Node_Id) return List_Id;
6141          --  Build all necessary finalization statements for a single component
6142          --  list. The statements may include a jump circuitry if flag Is_Local
6143          --  is enabled.
6144
6145          -----------------------------------------
6146          -- Process_Component_List_For_Finalize --
6147          -----------------------------------------
6148
6149          function Process_Component_List_For_Finalize
6150            (Comps : Node_Id) return List_Id
6151          is
6152             Alts       : List_Id;
6153             Counter_Id : Entity_Id;
6154             Decl       : Node_Id;
6155             Decl_Id    : Entity_Id;
6156             Decl_Typ   : Entity_Id;
6157             Decls      : List_Id;
6158             Has_POC    : Boolean;
6159             Jump_Block : Node_Id;
6160             Label      : Node_Id;
6161             Label_Id   : Entity_Id;
6162             Num_Comps  : Int;
6163             Stmts      : List_Id;
6164
6165             procedure Process_Component_For_Finalize
6166               (Decl  : Node_Id;
6167                Alts  : List_Id;
6168                Decls : List_Id;
6169                Stmts : List_Id);
6170             --  Process the declaration of a single controlled component. If
6171             --  flag Is_Local is enabled, create the corresponding label and
6172             --  jump circuitry. Alts is the list of case alternatives, Decls
6173             --  is the top level declaration list where labels are declared
6174             --  and Stmts is the list of finalization actions.
6175
6176             ------------------------------------
6177             -- Process_Component_For_Finalize --
6178             ------------------------------------
6179
6180             procedure Process_Component_For_Finalize
6181               (Decl  : Node_Id;
6182                Alts  : List_Id;
6183                Decls : List_Id;
6184                Stmts : List_Id)
6185             is
6186                Id       : constant Entity_Id := Defining_Identifier (Decl);
6187                Typ      : constant Entity_Id := Etype (Id);
6188                Fin_Stmt : Node_Id;
6189
6190             begin
6191                if Is_Local then
6192                   declare
6193                      Label    : Node_Id;
6194                      Label_Id : Entity_Id;
6195
6196                   begin
6197                      --  Generate:
6198                      --    LN : label;
6199
6200                      Label_Id :=
6201                        Make_Identifier (Loc,
6202                          Chars => New_External_Name ('L', Num_Comps));
6203                      Set_Entity (Label_Id,
6204                        Make_Defining_Identifier (Loc, Chars (Label_Id)));
6205                      Label := Make_Label (Loc, Label_Id);
6206
6207                      Append_To (Decls,
6208                        Make_Implicit_Label_Declaration (Loc,
6209                          Defining_Identifier => Entity (Label_Id),
6210                          Label_Construct     => Label));
6211
6212                      --  Generate:
6213                      --    when N =>
6214                      --      goto LN;
6215
6216                      Append_To (Alts,
6217                        Make_Case_Statement_Alternative (Loc,
6218                          Discrete_Choices => New_List (
6219                            Make_Integer_Literal (Loc, Num_Comps)),
6220
6221                          Statements => New_List (
6222                            Make_Goto_Statement (Loc,
6223                              Name =>
6224                                New_Reference_To (Entity (Label_Id), Loc)))));
6225
6226                      --  Generate:
6227                      --    <<LN>>
6228
6229                      Append_To (Stmts, Label);
6230
6231                      --  Decrease the number of components to be processed.
6232                      --  This action yields a new Label_Id in future calls.
6233
6234                      Num_Comps := Num_Comps - 1;
6235                   end;
6236                end if;
6237
6238                --  Generate:
6239                --    [Deep_]Finalize (V.Id);  --  No_Exception_Propagation
6240
6241                --    begin                    --  Exception handlers allowed
6242                --       [Deep_]Finalize (V.Id);
6243                --    exception
6244                --       when others =>
6245                --          if not Raised then
6246                --             Raised := True;
6247                --             Save_Occurrence (E,
6248                --               Get_Current_Excep.all.all);
6249                --          end if;
6250                --    end;
6251
6252                Fin_Stmt :=
6253                  Make_Final_Call
6254                    (Obj_Ref =>
6255                       Make_Selected_Component (Loc,
6256                         Prefix        => Make_Identifier (Loc, Name_V),
6257                         Selector_Name => Make_Identifier (Loc, Chars (Id))),
6258                     Typ     => Typ);
6259
6260                if not Restriction_Active (No_Exception_Propagation) then
6261                   Fin_Stmt :=
6262                     Make_Block_Statement (Loc,
6263                       Handled_Statement_Sequence =>
6264                         Make_Handled_Sequence_Of_Statements (Loc,
6265                           Statements         => New_List (Fin_Stmt),
6266                           Exception_Handlers => New_List (
6267                             Build_Exception_Handler (Finalizer_Data))));
6268                end if;
6269
6270                Append_To (Stmts, Fin_Stmt);
6271             end Process_Component_For_Finalize;
6272
6273          --  Start of processing for Process_Component_List_For_Finalize
6274
6275          begin
6276             --  Perform an initial check, look for controlled and per-object
6277             --  constrained components.
6278
6279             Preprocess_Components (Comps, Num_Comps, Has_POC);
6280
6281             --  Create a state counter to service the current component list.
6282             --  This step is performed before the variants are inspected in
6283             --  order to generate the same state counter names as those from
6284             --  Build_Initialize_Statements.
6285
6286             if Num_Comps > 0
6287               and then Is_Local
6288             then
6289                Counter := Counter + 1;
6290
6291                Counter_Id :=
6292                  Make_Defining_Identifier (Loc,
6293                    Chars => New_External_Name ('C', Counter));
6294             end if;
6295
6296             --  Process the component in the following order:
6297             --    1) Variants
6298             --    2) Per-object constrained components
6299             --    3) Regular components
6300
6301             --  Start with the variant parts
6302
6303             Var_Case := Empty;
6304             if Present (Variant_Part (Comps)) then
6305                declare
6306                   Var_Alts : constant List_Id := New_List;
6307                   Var      : Node_Id;
6308
6309                begin
6310                   Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
6311                   while Present (Var) loop
6312
6313                      --  Generate:
6314                      --     when <discrete choices> =>
6315                      --        <finalize statements>
6316
6317                      Append_To (Var_Alts,
6318                        Make_Case_Statement_Alternative (Loc,
6319                          Discrete_Choices =>
6320                            New_Copy_List (Discrete_Choices (Var)),
6321                          Statements =>
6322                            Process_Component_List_For_Finalize (
6323                              Component_List (Var))));
6324
6325                      Next_Non_Pragma (Var);
6326                   end loop;
6327
6328                   --  Generate:
6329                   --     case V.<discriminant> is
6330                   --        when <discrete choices 1> =>
6331                   --           <finalize statements 1>
6332                   --        ...
6333                   --        when <discrete choices N> =>
6334                   --           <finalize statements N>
6335                   --     end case;
6336
6337                   Var_Case :=
6338                     Make_Case_Statement (Loc,
6339                       Expression =>
6340                         Make_Selected_Component (Loc,
6341                           Prefix        => Make_Identifier (Loc, Name_V),
6342                           Selector_Name =>
6343                             Make_Identifier (Loc,
6344                               Chars => Chars (Name (Variant_Part (Comps))))),
6345                       Alternatives => Var_Alts);
6346                end;
6347             end if;
6348
6349             --  The current component list does not have a single controlled
6350             --  component, however it may contain variants. Return the case
6351             --  statement for the variants or nothing.
6352
6353             if Num_Comps = 0 then
6354                if Present (Var_Case) then
6355                   return New_List (Var_Case);
6356                else
6357                   return New_List (Make_Null_Statement (Loc));
6358                end if;
6359             end if;
6360
6361             --  Prepare all lists
6362
6363             Alts  := New_List;
6364             Decls := New_List;
6365             Stmts := New_List;
6366
6367             --  Process all per-object constrained components in reverse order
6368
6369             if Has_POC then
6370                Decl := Last_Non_Pragma (Component_Items (Comps));
6371                while Present (Decl) loop
6372                   Decl_Id  := Defining_Identifier (Decl);
6373                   Decl_Typ := Etype (Decl_Id);
6374
6375                   --  Skip _parent
6376
6377                   if Chars (Decl_Id) /= Name_uParent
6378                     and then Needs_Finalization (Decl_Typ)
6379                     and then Has_Access_Constraint (Decl_Id)
6380                     and then No (Expression (Decl))
6381                   then
6382                      Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6383                   end if;
6384
6385                   Prev_Non_Pragma (Decl);
6386                end loop;
6387             end if;
6388
6389             --  Process the rest of the components in reverse order
6390
6391             Decl := Last_Non_Pragma (Component_Items (Comps));
6392             while Present (Decl) loop
6393                Decl_Id  := Defining_Identifier (Decl);
6394                Decl_Typ := Etype (Decl_Id);
6395
6396                --  Skip _parent
6397
6398                if Chars (Decl_Id) /= Name_uParent
6399                  and then Needs_Finalization (Decl_Typ)
6400                then
6401                   --  Skip per-object constrained components since they were
6402                   --  handled in the above step.
6403
6404                   if Has_Access_Constraint (Decl_Id)
6405                     and then No (Expression (Decl))
6406                   then
6407                      null;
6408                   else
6409                      Process_Component_For_Finalize (Decl, Alts, Decls, Stmts);
6410                   end if;
6411                end if;
6412
6413                Prev_Non_Pragma (Decl);
6414             end loop;
6415
6416             --  Generate:
6417             --    declare
6418             --       LN : label;        --  If Is_Local is enabled
6419             --       ...                    .
6420             --       L0 : label;            .
6421
6422             --    begin                     .
6423             --       case CounterX is       .
6424             --          when N =>           .
6425             --             goto LN;         .
6426             --          ...                 .
6427             --          when 1 =>           .
6428             --             goto L1;         .
6429             --          when others =>      .
6430             --             goto L0;         .
6431             --       end case;              .
6432
6433             --       <<LN>>             --  If Is_Local is enabled
6434             --          begin
6435             --             [Deep_]Finalize (V.CompY);
6436             --          exception
6437             --             when Id : others =>
6438             --                if not Raised then
6439             --                   Raised := True;
6440             --                   Save_Occurrence (E,
6441             --                     Get_Current_Excep.all.all);
6442             --                end if;
6443             --          end;
6444             --       ...
6445             --       <<L0>>  --  If Is_Local is enabled
6446             --    end;
6447
6448             if Is_Local then
6449
6450                --  Add the declaration of default jump location L0, its
6451                --  corresponding alternative and its place in the statements.
6452
6453                Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
6454                Set_Entity (Label_Id,
6455                  Make_Defining_Identifier (Loc, Chars (Label_Id)));
6456                Label := Make_Label (Loc, Label_Id);
6457
6458                Append_To (Decls,          --  declaration
6459                  Make_Implicit_Label_Declaration (Loc,
6460                    Defining_Identifier => Entity (Label_Id),
6461                    Label_Construct     => Label));
6462
6463                Append_To (Alts,           --  alternative
6464                  Make_Case_Statement_Alternative (Loc,
6465                    Discrete_Choices => New_List (
6466                      Make_Others_Choice (Loc)),
6467
6468                    Statements => New_List (
6469                      Make_Goto_Statement (Loc,
6470                        Name => New_Reference_To (Entity (Label_Id), Loc)))));
6471
6472                Append_To (Stmts, Label);  --  statement
6473
6474                --  Create the jump block
6475
6476                Prepend_To (Stmts,
6477                  Make_Case_Statement (Loc,
6478                    Expression   => Make_Identifier (Loc, Chars (Counter_Id)),
6479                    Alternatives => Alts));
6480             end if;
6481
6482             Jump_Block :=
6483               Make_Block_Statement (Loc,
6484                 Declarations               => Decls,
6485                 Handled_Statement_Sequence =>
6486                   Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6487
6488             if Present (Var_Case) then
6489                return New_List (Var_Case, Jump_Block);
6490             else
6491                return New_List (Jump_Block);
6492             end if;
6493          end Process_Component_List_For_Finalize;
6494
6495       --  Start of processing for Build_Finalize_Statements
6496
6497       begin
6498          Finalizer_Decls := New_List;
6499          Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
6500
6501          if Nkind (Typ_Def) = N_Derived_Type_Definition then
6502             Rec_Def := Record_Extension_Part (Typ_Def);
6503          else
6504             Rec_Def := Typ_Def;
6505          end if;
6506
6507          --  Create a finalization sequence for all record components
6508
6509          if Present (Component_List (Rec_Def)) then
6510             Bod_Stmts :=
6511               Process_Component_List_For_Finalize (Component_List (Rec_Def));
6512          end if;
6513
6514          --  A derived record type must finalize all inherited components. This
6515          --  action poses the following problem:
6516
6517          --    procedure Deep_Finalize (Obj : in out Parent_Typ) is
6518          --    begin
6519          --       Finalize (Obj);
6520          --       ...
6521
6522          --    procedure Deep_Finalize (Obj : in out Derived_Typ) is
6523          --    begin
6524          --       Deep_Finalize (Obj._parent);
6525          --       ...
6526          --       Finalize (Obj);
6527          --       ...
6528
6529          --  Finalizing the derived type will invoke Finalize of the parent and
6530          --  then that of the derived type. This is undesirable because both
6531          --  routines may modify shared components. Only the Finalize of the
6532          --  derived type should be invoked.
6533
6534          --  To prevent this double adjustment of shared components,
6535          --  Deep_Finalize uses a flag to control the invocation of Finalize:
6536
6537          --    procedure Deep_Finalize
6538          --      (Obj  : in out Some_Type;
6539          --       Flag : Boolean := True)
6540          --    is
6541          --    begin
6542          --       if Flag then
6543          --          Finalize (Obj);
6544          --       end if;
6545          --       ...
6546
6547          --  When Deep_Finalize is invokes for field _parent, a value of False
6548          --  is provided for the flag:
6549
6550          --    Deep_Finalize (Obj._parent, False);
6551
6552          if Is_Tagged_Type (Typ)
6553            and then Is_Derived_Type (Typ)
6554          then
6555             declare
6556                Par_Typ  : constant Entity_Id := Parent_Field_Type (Typ);
6557                Call     : Node_Id;
6558                Fin_Stmt : Node_Id;
6559
6560             begin
6561                if Needs_Finalization (Par_Typ) then
6562                   Call :=
6563                     Make_Final_Call
6564                       (Obj_Ref    =>
6565                          Make_Selected_Component (Loc,
6566                            Prefix        => Make_Identifier (Loc, Name_V),
6567                            Selector_Name =>
6568                              Make_Identifier (Loc, Name_uParent)),
6569                        Typ        => Par_Typ,
6570                        For_Parent => True);
6571
6572                   --  Generate:
6573                   --    Deep_Finalize (V._parent, False);  --  No_Except_Propag
6574
6575                   --    begin                              --  Exceptions OK
6576                   --       Deep_Finalize (V._parent, False);
6577                   --    exception
6578                   --       when Id : others =>
6579                   --          if not Raised then
6580                   --             Raised := True;
6581                   --             Save_Occurrence (E,
6582                   --               Get_Current_Excep.all.all);
6583                   --          end if;
6584                   --    end;
6585
6586                   if Present (Call) then
6587                      Fin_Stmt := Call;
6588
6589                      if Exceptions_OK then
6590                         Fin_Stmt :=
6591                           Make_Block_Statement (Loc,
6592                             Handled_Statement_Sequence =>
6593                               Make_Handled_Sequence_Of_Statements (Loc,
6594                                 Statements         => New_List (Fin_Stmt),
6595                                 Exception_Handlers => New_List (
6596                                   Build_Exception_Handler
6597                                     (Finalizer_Data))));
6598                      end if;
6599
6600                      Append_To (Bod_Stmts, Fin_Stmt);
6601                   end if;
6602                end if;
6603             end;
6604          end if;
6605
6606          --  Finalize the object. This action must be performed first before
6607          --  all components have been finalized.
6608
6609          if Is_Controlled (Typ)
6610            and then not Is_Local
6611          then
6612             declare
6613                Fin_Stmt : Node_Id;
6614                Proc     : Entity_Id;
6615
6616             begin
6617                Proc := Find_Prim_Op (Typ, Name_Finalize);
6618
6619                --  Generate:
6620                --    if F then
6621                --       Finalize (V);  --  No_Exception_Propagation
6622
6623                --       begin
6624                --          Finalize (V);
6625                --       exception
6626                --          when others =>
6627                --             if not Raised then
6628                --                Raised := True;
6629                --                Save_Occurrence (E,
6630                --                  Get_Current_Excep.all.all);
6631                --             end if;
6632                --       end;
6633                --    end if;
6634
6635                if Present (Proc) then
6636                   Fin_Stmt :=
6637                     Make_Procedure_Call_Statement (Loc,
6638                       Name                   => New_Reference_To (Proc, Loc),
6639                       Parameter_Associations => New_List (
6640                         Make_Identifier (Loc, Name_V)));
6641
6642                   if Exceptions_OK then
6643                      Fin_Stmt :=
6644                        Make_Block_Statement (Loc,
6645                          Handled_Statement_Sequence =>
6646                            Make_Handled_Sequence_Of_Statements (Loc,
6647                              Statements         => New_List (Fin_Stmt),
6648                              Exception_Handlers => New_List (
6649                                Build_Exception_Handler
6650                                  (Finalizer_Data))));
6651                   end if;
6652
6653                   Prepend_To (Bod_Stmts,
6654                     Make_If_Statement (Loc,
6655                       Condition       => Make_Identifier (Loc, Name_F),
6656                       Then_Statements => New_List (Fin_Stmt)));
6657                end if;
6658             end;
6659          end if;
6660
6661          --  At this point either all finalization statements have been
6662          --  generated or the type is not controlled.
6663
6664          if No (Bod_Stmts) then
6665             return New_List (Make_Null_Statement (Loc));
6666
6667          --  Generate:
6668          --    declare
6669          --       Abort  : constant Boolean := Triggered_By_Abort;
6670          --         <or>
6671          --       Abort  : constant Boolean := False;  --  no abort
6672
6673          --       E      : Exception_Occurence;
6674          --       Raised : Boolean := False;
6675
6676          --    begin
6677          --       <finalize statements>
6678
6679          --       if Raised and then not Abort then
6680          --          Raise_From_Controlled_Operation (E);
6681          --       end if;
6682          --    end;
6683
6684          else
6685             if Exceptions_OK then
6686                Append_To (Bod_Stmts,
6687                  Build_Raise_Statement (Finalizer_Data));
6688             end if;
6689
6690             return
6691               New_List (
6692                 Make_Block_Statement (Loc,
6693                   Declarations               =>
6694                     Finalizer_Decls,
6695                   Handled_Statement_Sequence =>
6696                     Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
6697          end if;
6698       end Build_Finalize_Statements;
6699
6700       -----------------------
6701       -- Parent_Field_Type --
6702       -----------------------
6703
6704       function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
6705          Field : Entity_Id;
6706
6707       begin
6708          Field := First_Entity (Typ);
6709          while Present (Field) loop
6710             if Chars (Field) = Name_uParent then
6711                return Etype (Field);
6712             end if;
6713
6714             Next_Entity (Field);
6715          end loop;
6716
6717          --  A derived tagged type should always have a parent field
6718
6719          raise Program_Error;
6720       end Parent_Field_Type;
6721
6722       ---------------------------
6723       -- Preprocess_Components --
6724       ---------------------------
6725
6726       procedure Preprocess_Components
6727         (Comps     : Node_Id;
6728          Num_Comps : out Int;
6729          Has_POC   : out Boolean)
6730       is
6731          Decl : Node_Id;
6732          Id   : Entity_Id;
6733          Typ  : Entity_Id;
6734
6735       begin
6736          Num_Comps := 0;
6737          Has_POC   := False;
6738
6739          Decl := First_Non_Pragma (Component_Items (Comps));
6740          while Present (Decl) loop
6741             Id  := Defining_Identifier (Decl);
6742             Typ := Etype (Id);
6743
6744             --  Skip field _parent
6745
6746             if Chars (Id) /= Name_uParent
6747               and then Needs_Finalization (Typ)
6748             then
6749                Num_Comps := Num_Comps + 1;
6750
6751                if Has_Access_Constraint (Id)
6752                  and then No (Expression (Decl))
6753                then
6754                   Has_POC := True;
6755                end if;
6756             end if;
6757
6758             Next_Non_Pragma (Decl);
6759          end loop;
6760       end Preprocess_Components;
6761
6762    --  Start of processing for Make_Deep_Record_Body
6763
6764    begin
6765       case Prim is
6766          when Address_Case =>
6767             return Make_Finalize_Address_Stmts (Typ);
6768
6769          when Adjust_Case =>
6770             return Build_Adjust_Statements (Typ);
6771
6772          when Finalize_Case =>
6773             return Build_Finalize_Statements (Typ);
6774
6775          when Initialize_Case =>
6776             declare
6777                Loc : constant Source_Ptr := Sloc (Typ);
6778
6779             begin
6780                if Is_Controlled (Typ) then
6781                   return New_List (
6782                     Make_Procedure_Call_Statement (Loc,
6783                       Name                   =>
6784                         New_Reference_To
6785                           (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
6786                       Parameter_Associations => New_List (
6787                         Make_Identifier (Loc, Name_V))));
6788                else
6789                   return Empty_List;
6790                end if;
6791             end;
6792       end case;
6793    end Make_Deep_Record_Body;
6794
6795    ----------------------
6796    -- Make_Final_Call --
6797    ----------------------
6798
6799    function Make_Final_Call
6800      (Obj_Ref    : Node_Id;
6801       Typ        : Entity_Id;
6802       For_Parent : Boolean := False) return Node_Id
6803    is
6804       Loc    : constant Source_Ptr := Sloc (Obj_Ref);
6805       Atyp   : Entity_Id;
6806       Fin_Id : Entity_Id := Empty;
6807       Ref    : Node_Id;
6808       Utyp   : Entity_Id;
6809
6810    begin
6811       --  Recover the proper type which contains [Deep_]Finalize
6812
6813       if Is_Class_Wide_Type (Typ) then
6814          Utyp := Root_Type (Typ);
6815          Atyp := Utyp;
6816          Ref  := Obj_Ref;
6817
6818       elsif Is_Concurrent_Type (Typ) then
6819          Utyp := Corresponding_Record_Type (Typ);
6820          Atyp := Empty;
6821          Ref  := Convert_Concurrent (Obj_Ref, Typ);
6822
6823       elsif Is_Private_Type (Typ)
6824         and then Present (Full_View (Typ))
6825         and then Is_Concurrent_Type (Full_View (Typ))
6826       then
6827          Utyp := Corresponding_Record_Type (Full_View (Typ));
6828          Atyp := Typ;
6829          Ref  := Convert_Concurrent (Obj_Ref, Full_View (Typ));
6830
6831       else
6832          Utyp := Typ;
6833          Atyp := Typ;
6834          Ref  := Obj_Ref;
6835       end if;
6836
6837       Utyp := Underlying_Type (Base_Type (Utyp));
6838       Set_Assignment_OK (Ref);
6839
6840       --  Deal with non-tagged derivation of private views. If the parent type
6841       --  is a protected type, Deep_Finalize is found on the corresponding
6842       --  record of the ancestor.
6843
6844       if Is_Untagged_Derivation (Typ) then
6845          if Is_Protected_Type (Typ) then
6846             Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
6847          else
6848             Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6849
6850             if Is_Protected_Type (Utyp) then
6851                Utyp := Corresponding_Record_Type (Utyp);
6852             end if;
6853          end if;
6854
6855          Ref := Unchecked_Convert_To (Utyp, Ref);
6856          Set_Assignment_OK (Ref);
6857       end if;
6858
6859       --  Deal with derived private types which do not inherit primitives from
6860       --  their parents. In this case, [Deep_]Finalize can be found in the full
6861       --  view of the parent type.
6862
6863       if Is_Tagged_Type (Utyp)
6864         and then Is_Derived_Type (Utyp)
6865         and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
6866         and then Is_Private_Type (Etype (Utyp))
6867         and then Present (Full_View (Etype (Utyp)))
6868       then
6869          Utyp := Full_View (Etype (Utyp));
6870          Ref  := Unchecked_Convert_To (Utyp, Ref);
6871          Set_Assignment_OK (Ref);
6872       end if;
6873
6874       --  When dealing with the completion of a private type, use the base type
6875       --  instead.
6876
6877       if Utyp /= Base_Type (Utyp) then
6878          pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
6879
6880          Utyp := Base_Type (Utyp);
6881          Ref  := Unchecked_Convert_To (Utyp, Ref);
6882          Set_Assignment_OK (Ref);
6883       end if;
6884
6885       --  Select the appropriate version of Finalize
6886
6887       if For_Parent then
6888          if Has_Controlled_Component (Utyp) then
6889             Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6890          end if;
6891
6892       --  Class-wide types, interfaces and types with controlled components
6893
6894       elsif Is_Class_Wide_Type (Typ)
6895         or else Is_Interface (Typ)
6896         or else Has_Controlled_Component (Utyp)
6897       then
6898          if Is_Tagged_Type (Utyp) then
6899             Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6900          else
6901             Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
6902          end if;
6903
6904       --  Derivations from [Limited_]Controlled
6905
6906       elsif Is_Controlled (Utyp) then
6907          if Has_Controlled_Component (Utyp) then
6908             Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6909          else
6910             Fin_Id := Find_Prim_Op (Utyp, Name_Of (Finalize_Case));
6911          end if;
6912
6913       --  Tagged types
6914
6915       elsif Is_Tagged_Type (Utyp) then
6916          Fin_Id := Find_Prim_Op (Utyp, TSS_Deep_Finalize);
6917
6918       else
6919          raise Program_Error;
6920       end if;
6921
6922       if Present (Fin_Id) then
6923
6924          --  When finalizing a class-wide object, do not convert to the root
6925          --  type in order to produce a dispatching call.
6926
6927          if Is_Class_Wide_Type (Typ) then
6928             null;
6929
6930          --  Ensure that a finalization routine is at least decorated in order
6931          --  to inspect the object parameter.
6932
6933          elsif Analyzed (Fin_Id)
6934            or else Ekind (Fin_Id) = E_Procedure
6935          then
6936             --  In certain cases, such as the creation of Stream_Read, the
6937             --  visible entity of the type is its full view. Since Stream_Read
6938             --  will have to create an object of type Typ, the local object
6939             --  will be finalzed by the scope finalizer generated later on. The
6940             --  object parameter of Deep_Finalize will always use the private
6941             --  view of the type. To avoid such a clash between a private and a
6942             --  full view, perform an unchecked conversion of the object
6943             --  reference to the private view.
6944
6945             declare
6946                Formal_Typ : constant Entity_Id :=
6947                               Etype (First_Formal (Fin_Id));
6948             begin
6949                if Is_Private_Type (Formal_Typ)
6950                  and then Present (Full_View (Formal_Typ))
6951                  and then Full_View (Formal_Typ) = Utyp
6952                then
6953                   Ref := Unchecked_Convert_To (Formal_Typ, Ref);
6954                end if;
6955             end;
6956
6957             Ref := Convert_View (Fin_Id, Ref);
6958          end if;
6959
6960          return Make_Call (Loc, Fin_Id, New_Copy_Tree (Ref), For_Parent);
6961       else
6962          return Empty;
6963       end if;
6964    end Make_Final_Call;
6965
6966    --------------------------------
6967    -- Make_Finalize_Address_Body --
6968    --------------------------------
6969
6970    procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
6971       Is_Task : constant Boolean :=
6972                   Ekind (Typ) = E_Record_Type
6973                     and then Is_Concurrent_Record_Type (Typ)
6974                     and then Ekind (Corresponding_Concurrent_Type (Typ)) =
6975                                E_Task_Type;
6976       Loc     : constant Source_Ptr := Sloc (Typ);
6977       Proc_Id : Entity_Id;
6978       Stmts   : List_Id;
6979
6980    begin
6981       --  The corresponding records of task types are not controlled by design.
6982       --  For the sake of completeness, create an empty Finalize_Address to be
6983       --  used in task class-wide allocations.
6984
6985       if Is_Task then
6986          null;
6987
6988       --  Nothing to do if the type is not controlled or it already has a
6989       --  TSS entry for Finalize_Address. Skip class-wide subtypes which do not
6990       --  come from source. These are usually generated for completeness and
6991       --  do not need the Finalize_Address primitive.
6992
6993       elsif not Needs_Finalization (Typ)
6994         or else Is_Abstract_Type (Typ)
6995         or else Present (TSS (Typ, TSS_Finalize_Address))
6996         or else
6997           (Is_Class_Wide_Type (Typ)
6998             and then Ekind (Root_Type (Typ)) = E_Record_Subtype
6999             and then not Comes_From_Source (Root_Type (Typ)))
7000       then
7001          return;
7002       end if;
7003
7004       Proc_Id :=
7005         Make_Defining_Identifier (Loc,
7006           Make_TSS_Name (Typ, TSS_Finalize_Address));
7007
7008       --  Generate:
7009
7010       --    procedure <Typ>FD (V : System.Address) is
7011       --    begin
7012       --       null;                            --  for tasks
7013
7014       --       declare                          --  for all other types
7015       --          type Pnn is access all Typ;
7016       --          for Pnn'Storage_Size use 0;
7017       --       begin
7018       --          [Deep_]Finalize (Pnn (V).all);
7019       --       end;
7020       --    end TypFD;
7021
7022       if Is_Task then
7023          Stmts := New_List (Make_Null_Statement (Loc));
7024       else
7025          Stmts := Make_Finalize_Address_Stmts (Typ);
7026       end if;
7027
7028       Discard_Node (
7029         Make_Subprogram_Body (Loc,
7030           Specification =>
7031             Make_Procedure_Specification (Loc,
7032               Defining_Unit_Name => Proc_Id,
7033
7034               Parameter_Specifications => New_List (
7035                 Make_Parameter_Specification (Loc,
7036                   Defining_Identifier =>
7037                     Make_Defining_Identifier (Loc, Name_V),
7038                   Parameter_Type =>
7039                     New_Reference_To (RTE (RE_Address), Loc)))),
7040
7041           Declarations => No_List,
7042
7043           Handled_Statement_Sequence =>
7044             Make_Handled_Sequence_Of_Statements (Loc,
7045               Statements => Stmts)));
7046
7047       Set_TSS (Typ, Proc_Id);
7048    end Make_Finalize_Address_Body;
7049
7050    ---------------------------------
7051    -- Make_Finalize_Address_Stmts --
7052    ---------------------------------
7053
7054    function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
7055       Loc      : constant Source_Ptr := Sloc (Typ);
7056       Ptr_Typ  : constant Entity_Id  := Make_Temporary (Loc, 'P');
7057       Decls    : List_Id;
7058       Desg_Typ : Entity_Id;
7059       Obj_Expr : Node_Id;
7060
7061    begin
7062       if Is_Array_Type (Typ) then
7063          if Is_Constrained (First_Subtype (Typ)) then
7064             Desg_Typ := First_Subtype (Typ);
7065          else
7066             Desg_Typ := Base_Type (Typ);
7067          end if;
7068
7069       --  Class-wide types of constrained root types
7070
7071       elsif Is_Class_Wide_Type (Typ)
7072         and then Has_Discriminants (Root_Type (Typ))
7073         and then not
7074           Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
7075       then
7076          declare
7077             Parent_Typ : Entity_Id;
7078
7079          begin
7080             --  Climb the parent type chain looking for a non-constrained type
7081
7082             Parent_Typ := Root_Type (Typ);
7083             while Parent_Typ /= Etype (Parent_Typ)
7084               and then Has_Discriminants (Parent_Typ)
7085               and then not
7086                 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
7087             loop
7088                Parent_Typ := Etype (Parent_Typ);
7089             end loop;
7090
7091             --  Handle views created for tagged types with unknown
7092             --  discriminants.
7093
7094             if Is_Underlying_Record_View (Parent_Typ) then
7095                Parent_Typ := Underlying_Record_View (Parent_Typ);
7096             end if;
7097
7098             Desg_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
7099          end;
7100
7101       --  General case
7102
7103       else
7104          Desg_Typ := Typ;
7105       end if;
7106
7107       --  Generate:
7108       --    type Ptr_Typ is access all Typ;
7109       --    for Ptr_Typ'Storage_Size use 0;
7110
7111       Decls := New_List (
7112         Make_Full_Type_Declaration (Loc,
7113           Defining_Identifier => Ptr_Typ,
7114           Type_Definition     =>
7115             Make_Access_To_Object_Definition (Loc,
7116               All_Present        => True,
7117               Subtype_Indication => New_Reference_To (Desg_Typ, Loc))),
7118
7119         Make_Attribute_Definition_Clause (Loc,
7120           Name       => New_Reference_To (Ptr_Typ, Loc),
7121           Chars      => Name_Storage_Size,
7122           Expression => Make_Integer_Literal (Loc, 0)));
7123
7124       Obj_Expr := Make_Identifier (Loc, Name_V);
7125
7126       --  Unconstrained arrays require special processing in order to retrieve
7127       --  the elements. To achieve this, we have to skip the dope vector which
7128       --  lays in front of the elements and then use a thin pointer to perform
7129       --  the address-to-access conversion.
7130
7131       if Is_Array_Type (Typ)
7132         and then not Is_Constrained (First_Subtype (Typ))
7133       then
7134          declare
7135             Dope_Id : Entity_Id;
7136
7137          begin
7138             --  Ensure that Ptr_Typ a thin pointer, generate:
7139             --    for Ptr_Typ'Size use System.Address'Size;
7140
7141             Append_To (Decls,
7142               Make_Attribute_Definition_Clause (Loc,
7143                 Name       => New_Reference_To (Ptr_Typ, Loc),
7144                 Chars      => Name_Size,
7145                 Expression =>
7146                   Make_Integer_Literal (Loc, System_Address_Size)));
7147
7148             --  Generate:
7149             --    Dnn : constant Storage_Offset :=
7150             --            Desg_Typ'Descriptor_Size / Storage_Unit;
7151
7152             Dope_Id := Make_Temporary (Loc, 'D');
7153
7154             Append_To (Decls,
7155               Make_Object_Declaration (Loc,
7156                 Defining_Identifier => Dope_Id,
7157                 Constant_Present    => True,
7158                 Object_Definition   =>
7159                   New_Reference_To (RTE (RE_Storage_Offset), Loc),
7160                 Expression          =>
7161                   Make_Op_Divide (Loc,
7162                     Left_Opnd  =>
7163                       Make_Attribute_Reference (Loc,
7164                         Prefix         => New_Reference_To (Desg_Typ, Loc),
7165                         Attribute_Name => Name_Descriptor_Size),
7166                     Right_Opnd =>
7167                       Make_Integer_Literal (Loc, System_Storage_Unit))));
7168
7169             --  Shift the address from the start of the dope vector to the
7170             --  start of the elements:
7171             --
7172             --    V + Dnn
7173             --
7174             --  Note that this is done through a wrapper routine since RTSfind
7175             --  cannot retrieve operations with string names of the form "+".
7176
7177             Obj_Expr :=
7178               Make_Function_Call (Loc,
7179                 Name                   =>
7180                   New_Reference_To (RTE (RE_Add_Offset_To_Address), Loc),
7181                 Parameter_Associations => New_List (
7182                   Obj_Expr,
7183                   New_Reference_To (Dope_Id, Loc)));
7184          end;
7185       end if;
7186
7187       --  Create the block and the finalization call
7188
7189       return New_List (
7190         Make_Block_Statement (Loc,
7191           Declarations => Decls,
7192
7193           Handled_Statement_Sequence =>
7194             Make_Handled_Sequence_Of_Statements (Loc,
7195               Statements => New_List (
7196                 Make_Final_Call (
7197                   Obj_Ref =>
7198                     Make_Explicit_Dereference (Loc,
7199                       Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
7200                   Typ => Desg_Typ)))));
7201    end Make_Finalize_Address_Stmts;
7202
7203    -------------------------------------
7204    -- Make_Handler_For_Ctrl_Operation --
7205    -------------------------------------
7206
7207    --  Generate:
7208
7209    --    when E : others =>
7210    --      Raise_From_Controlled_Operation (E);
7211
7212    --  or:
7213
7214    --    when others =>
7215    --      raise Program_Error [finalize raised exception];
7216
7217    --  depending on whether Raise_From_Controlled_Operation is available
7218
7219    function Make_Handler_For_Ctrl_Operation
7220      (Loc : Source_Ptr) return Node_Id
7221    is
7222       E_Occ : Entity_Id;
7223       --  Choice parameter (for the first case above)
7224
7225       Raise_Node : Node_Id;
7226       --  Procedure call or raise statement
7227
7228    begin
7229       --  Standard run-time, .NET/JVM targets: add choice parameter E and pass
7230       --  it to Raise_From_Controlled_Operation so that the original exception
7231       --  name and message can be recorded in the exception message for
7232       --  Program_Error.
7233
7234       if RTE_Available (RE_Raise_From_Controlled_Operation) then
7235          E_Occ := Make_Defining_Identifier (Loc, Name_E);
7236          Raise_Node :=
7237            Make_Procedure_Call_Statement (Loc,
7238              Name                   =>
7239                New_Reference_To
7240                  (RTE (RE_Raise_From_Controlled_Operation), Loc),
7241              Parameter_Associations => New_List (
7242                New_Reference_To (E_Occ, Loc)));
7243
7244       --  Restricted run-time: exception messages are not supported
7245
7246       else
7247          E_Occ := Empty;
7248          Raise_Node :=
7249            Make_Raise_Program_Error (Loc,
7250              Reason => PE_Finalize_Raised_Exception);
7251       end if;
7252
7253       return
7254         Make_Implicit_Exception_Handler (Loc,
7255           Exception_Choices => New_List (Make_Others_Choice (Loc)),
7256           Choice_Parameter  => E_Occ,
7257           Statements        => New_List (Raise_Node));
7258    end Make_Handler_For_Ctrl_Operation;
7259
7260    --------------------
7261    -- Make_Init_Call --
7262    --------------------
7263
7264    function Make_Init_Call
7265      (Obj_Ref : Node_Id;
7266       Typ     : Entity_Id) return Node_Id
7267    is
7268       Loc     : constant Source_Ptr := Sloc (Obj_Ref);
7269       Is_Conc : Boolean;
7270       Proc    : Entity_Id;
7271       Ref     : Node_Id;
7272       Utyp    : Entity_Id;
7273
7274    begin
7275       --  Deal with the type and object reference. Depending on the context, an
7276       --  object reference may need several conversions.
7277
7278       if Is_Concurrent_Type (Typ) then
7279          Is_Conc := True;
7280          Utyp    := Corresponding_Record_Type (Typ);
7281          Ref     := Convert_Concurrent (Obj_Ref, Typ);
7282
7283       elsif Is_Private_Type (Typ)
7284         and then Present (Full_View (Typ))
7285         and then Is_Concurrent_Type (Underlying_Type (Typ))
7286       then
7287          Is_Conc := True;
7288          Utyp    := Corresponding_Record_Type (Underlying_Type (Typ));
7289          Ref     := Convert_Concurrent (Obj_Ref, Underlying_Type (Typ));
7290
7291       else
7292          Is_Conc := False;
7293          Utyp    := Typ;
7294          Ref     := Obj_Ref;
7295       end if;
7296
7297       Set_Assignment_OK (Ref);
7298
7299       Utyp := Underlying_Type (Base_Type (Utyp));
7300
7301       --  Deal with non-tagged derivation of private views
7302
7303       if Is_Untagged_Derivation (Typ)
7304         and then not Is_Conc
7305       then
7306          Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7307          Ref  := Unchecked_Convert_To (Utyp, Ref);
7308
7309          --  The following is to prevent problems with UC see 1.156 RH ???
7310
7311          Set_Assignment_OK (Ref);
7312       end if;
7313
7314       --  If the underlying_type is a subtype, then we are dealing with the
7315       --  completion of a private type. We need to access the base type and
7316       --  generate a conversion to it.
7317
7318       if Utyp /= Base_Type (Utyp) then
7319          pragma Assert (Is_Private_Type (Typ));
7320          Utyp := Base_Type (Utyp);
7321          Ref  := Unchecked_Convert_To (Utyp, Ref);
7322       end if;
7323
7324       --  Select the appropriate version of initialize
7325
7326       if Has_Controlled_Component (Utyp) then
7327          Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
7328       else
7329          Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
7330          Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
7331       end if;
7332
7333       --  The object reference may need another conversion depending on the
7334       --  type of the formal and that of the actual.
7335
7336       Ref := Convert_View (Proc, Ref);
7337
7338       --  Generate:
7339       --    [Deep_]Initialize (Ref);
7340
7341       return
7342         Make_Procedure_Call_Statement (Loc,
7343           Name =>
7344             New_Reference_To (Proc, Loc),
7345           Parameter_Associations => New_List (Ref));
7346    end Make_Init_Call;
7347
7348    ------------------------------
7349    -- Make_Local_Deep_Finalize --
7350    ------------------------------
7351
7352    function Make_Local_Deep_Finalize
7353      (Typ : Entity_Id;
7354       Nam : Entity_Id) return Node_Id
7355    is
7356       Loc : constant Source_Ptr := Sloc (Typ);
7357       Formals : List_Id;
7358
7359    begin
7360       Formals := New_List (
7361
7362          --  V : in out Typ
7363
7364         Make_Parameter_Specification (Loc,
7365           Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
7366           In_Present          => True,
7367           Out_Present         => True,
7368           Parameter_Type      => New_Reference_To (Typ, Loc)),
7369
7370          --  F : Boolean := True
7371
7372         Make_Parameter_Specification (Loc,
7373           Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
7374           Parameter_Type      => New_Reference_To (Standard_Boolean, Loc),
7375           Expression          => New_Reference_To (Standard_True, Loc)));
7376
7377       --  Add the necessary number of counters to represent the initialization
7378       --  state of an object.
7379
7380       return
7381         Make_Subprogram_Body (Loc,
7382           Specification =>
7383             Make_Procedure_Specification (Loc,
7384               Defining_Unit_Name       => Nam,
7385               Parameter_Specifications => Formals),
7386
7387           Declarations => No_List,
7388
7389           Handled_Statement_Sequence =>
7390             Make_Handled_Sequence_Of_Statements (Loc,
7391               Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
7392    end Make_Local_Deep_Finalize;
7393
7394    ------------------------------------
7395    -- Make_Set_Finalize_Address_Call --
7396    ------------------------------------
7397
7398    function Make_Set_Finalize_Address_Call
7399      (Loc     : Source_Ptr;
7400       Typ     : Entity_Id;
7401       Ptr_Typ : Entity_Id) return Node_Id
7402    is
7403       Desig_Typ   : constant Entity_Id :=
7404                       Available_View (Designated_Type (Ptr_Typ));
7405       Fin_Mas_Id  : constant Entity_Id := Finalization_Master (Ptr_Typ);
7406       Fin_Mas_Ref : Node_Id;
7407       Utyp        : Entity_Id;
7408
7409    begin
7410       --  If the context is a class-wide allocator, we use the class-wide type
7411       --  to obtain the proper Finalize_Address routine.
7412
7413       if Is_Class_Wide_Type (Desig_Typ) then
7414          Utyp := Desig_Typ;
7415
7416       else
7417          Utyp := Typ;
7418
7419          if Is_Private_Type (Utyp) and then Present (Full_View (Utyp)) then
7420             Utyp := Full_View (Utyp);
7421          end if;
7422
7423          if Is_Concurrent_Type (Utyp) then
7424             Utyp := Corresponding_Record_Type (Utyp);
7425          end if;
7426       end if;
7427
7428       Utyp := Underlying_Type (Base_Type (Utyp));
7429
7430       --  Deal with non-tagged derivation of private views. If the parent is
7431       --  now known to be protected, the finalization routine is the one
7432       --  defined on the corresponding record of the ancestor (corresponding
7433       --  records do not automatically inherit operations, but maybe they
7434       --  should???)
7435
7436       if Is_Untagged_Derivation (Typ) then
7437          if Is_Protected_Type (Typ) then
7438             Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
7439          else
7440             Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
7441
7442             if Is_Protected_Type (Utyp) then
7443                Utyp := Corresponding_Record_Type (Utyp);
7444             end if;
7445          end if;
7446       end if;
7447
7448       --  If the underlying_type is a subtype, we are dealing with the
7449       --  completion of a private type. We need to access the base type and
7450       --  generate a conversion to it.
7451
7452       if Utyp /= Base_Type (Utyp) then
7453          pragma Assert (Is_Private_Type (Typ));
7454
7455          Utyp := Base_Type (Utyp);
7456       end if;
7457
7458       Fin_Mas_Ref := New_Occurrence_Of (Fin_Mas_Id, Loc);
7459
7460       --  If the call is from a build-in-place function, the Master parameter
7461       --  is actually a pointer. Dereference it for the call.
7462
7463       if Is_Access_Type (Etype (Fin_Mas_Id)) then
7464          Fin_Mas_Ref := Make_Explicit_Dereference (Loc, Fin_Mas_Ref);
7465       end if;
7466
7467       --  Generate:
7468       --    Set_Finalize_Address (<Ptr_Typ>FM, <Utyp>FD'Unrestricted_Access);
7469
7470       return
7471         Make_Procedure_Call_Statement (Loc,
7472           Name                   =>
7473             New_Reference_To (RTE (RE_Set_Finalize_Address), Loc),
7474           Parameter_Associations => New_List (
7475             Fin_Mas_Ref,
7476             Make_Attribute_Reference (Loc,
7477               Prefix         =>
7478                 New_Reference_To (TSS (Utyp, TSS_Finalize_Address), Loc),
7479               Attribute_Name => Name_Unrestricted_Access)));
7480    end Make_Set_Finalize_Address_Call;
7481
7482    --------------------------
7483    -- Make_Transient_Block --
7484    --------------------------
7485
7486    function Make_Transient_Block
7487      (Loc    : Source_Ptr;
7488       Action : Node_Id;
7489       Par    : Node_Id) return Node_Id
7490    is
7491       Decls  : constant List_Id := New_List;
7492       Instrs : constant List_Id := New_List (Action);
7493       Block  : Node_Id;
7494       Insert : Node_Id;
7495
7496    begin
7497       --  Case where only secondary stack use is involved
7498
7499       if VM_Target = No_VM
7500         and then Uses_Sec_Stack (Current_Scope)
7501         and then Nkind (Action) /= N_Simple_Return_Statement
7502         and then Nkind (Par) /= N_Exception_Handler
7503       then
7504          declare
7505             S : Entity_Id;
7506
7507          begin
7508             S := Scope (Current_Scope);
7509             loop
7510                --  At the outer level, no need to release the sec stack
7511
7512                if S = Standard_Standard then
7513                   Set_Uses_Sec_Stack (Current_Scope, False);
7514                   exit;
7515
7516                --  In a function, only release the sec stack if the function
7517                --  does not return on the sec stack otherwise the result may
7518                --  be lost. The caller is responsible for releasing.
7519
7520                elsif Ekind (S) = E_Function then
7521                   Set_Uses_Sec_Stack (Current_Scope, False);
7522
7523                   if not Requires_Transient_Scope (Etype (S)) then
7524                      Set_Uses_Sec_Stack (S, True);
7525                      Check_Restriction (No_Secondary_Stack, Action);
7526                   end if;
7527
7528                   exit;
7529
7530                --  In a loop or entry we should install a block encompassing
7531                --  all the construct. For now just release right away.
7532
7533                elsif Ekind_In (S, E_Entry, E_Loop) then
7534                   exit;
7535
7536                --  In a procedure or a block, we release on exit of the
7537                --  procedure or block. ??? memory leak can be created by
7538                --  recursive calls.
7539
7540                elsif Ekind_In (S, E_Block, E_Procedure) then
7541                   Set_Uses_Sec_Stack (S, True);
7542                   Check_Restriction (No_Secondary_Stack, Action);
7543                   Set_Uses_Sec_Stack (Current_Scope, False);
7544                   exit;
7545
7546                else
7547                   S := Scope (S);
7548                end if;
7549             end loop;
7550          end;
7551       end if;
7552
7553       --  Create the transient block. Set the parent now since the block itself
7554       --  is not part of the tree.
7555
7556       Block :=
7557         Make_Block_Statement (Loc,
7558           Identifier                 => New_Reference_To (Current_Scope, Loc),
7559           Declarations               => Decls,
7560           Handled_Statement_Sequence =>
7561             Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
7562           Has_Created_Identifier     => True);
7563       Set_Parent (Block, Par);
7564
7565       --  Insert actions stuck in the transient scopes as well as all freezing
7566       --  nodes needed by those actions.
7567
7568       Insert_Actions_In_Scope_Around (Action);
7569
7570       Insert := Prev (Action);
7571       if Present (Insert) then
7572          Freeze_All (First_Entity (Current_Scope), Insert);
7573       end if;
7574
7575       --  When the transient scope was established, we pushed the entry for the
7576       --  transient scope onto the scope stack, so that the scope was active
7577       --  for the installation of finalizable entities etc. Now we must remove
7578       --  this entry, since we have constructed a proper block.
7579
7580       Pop_Scope;
7581
7582       return Block;
7583    end Make_Transient_Block;
7584
7585    ------------------------
7586    -- Node_To_Be_Wrapped --
7587    ------------------------
7588
7589    function Node_To_Be_Wrapped return Node_Id is
7590    begin
7591       return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
7592    end Node_To_Be_Wrapped;
7593
7594    ----------------------------
7595    -- Set_Node_To_Be_Wrapped --
7596    ----------------------------
7597
7598    procedure Set_Node_To_Be_Wrapped (N : Node_Id) is
7599    begin
7600       Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := N;
7601    end Set_Node_To_Be_Wrapped;
7602
7603    ----------------------------------
7604    -- Store_After_Actions_In_Scope --
7605    ----------------------------------
7606
7607    procedure Store_After_Actions_In_Scope (L : List_Id) is
7608       SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7609
7610    begin
7611       if Present (SE.Actions_To_Be_Wrapped_After) then
7612          Insert_List_Before_And_Analyze (
7613           First (SE.Actions_To_Be_Wrapped_After), L);
7614
7615       else
7616          SE.Actions_To_Be_Wrapped_After := L;
7617
7618          if Is_List_Member (SE.Node_To_Be_Wrapped) then
7619             Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7620          else
7621             Set_Parent (L, SE.Node_To_Be_Wrapped);
7622          end if;
7623
7624          Analyze_List (L);
7625       end if;
7626    end Store_After_Actions_In_Scope;
7627
7628    -----------------------------------
7629    -- Store_Before_Actions_In_Scope --
7630    -----------------------------------
7631
7632    procedure Store_Before_Actions_In_Scope (L : List_Id) is
7633       SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
7634
7635    begin
7636       if Present (SE.Actions_To_Be_Wrapped_Before) then
7637          Insert_List_After_And_Analyze (
7638            Last (SE.Actions_To_Be_Wrapped_Before), L);
7639
7640       else
7641          SE.Actions_To_Be_Wrapped_Before := L;
7642
7643          if Is_List_Member (SE.Node_To_Be_Wrapped) then
7644             Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
7645          else
7646             Set_Parent (L, SE.Node_To_Be_Wrapped);
7647          end if;
7648
7649          Analyze_List (L);
7650       end if;
7651    end Store_Before_Actions_In_Scope;
7652
7653    --------------------------------
7654    -- Wrap_Transient_Declaration --
7655    --------------------------------
7656
7657    --  If a transient scope has been established during the processing of the
7658    --  Expression of an Object_Declaration, it is not possible to wrap the
7659    --  declaration into a transient block as usual case, otherwise the object
7660    --  would be itself declared in the wrong scope. Therefore, all entities (if
7661    --  any) defined in the transient block are moved to the proper enclosing
7662    --  scope, furthermore, if they are controlled variables they are finalized
7663    --  right after the declaration. The finalization list of the transient
7664    --  scope is defined as a renaming of the enclosing one so during their
7665    --  initialization they will be attached to the proper finalization list.
7666    --  For instance, the following declaration :
7667
7668    --        X : Typ := F (G (A), G (B));
7669
7670    --  (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
7671    --  is expanded into :
7672
7673    --    X : Typ := [ complex Expression-Action ];
7674    --    [Deep_]Finalize (_v1);
7675    --    [Deep_]Finalize (_v2);
7676
7677    procedure Wrap_Transient_Declaration (N : Node_Id) is
7678       Encl_S  : Entity_Id;
7679       S       : Entity_Id;
7680       Uses_SS : Boolean;
7681
7682    begin
7683       S := Current_Scope;
7684       Encl_S := Scope (S);
7685
7686       --  Insert Actions kept in the Scope stack
7687
7688       Insert_Actions_In_Scope_Around (N);
7689
7690       --  If the declaration is consuming some secondary stack, mark the
7691       --  enclosing scope appropriately.
7692
7693       Uses_SS := Uses_Sec_Stack (S);
7694       Pop_Scope;
7695
7696       --  Put the local entities back in the enclosing scope, and set the
7697       --  Is_Public flag appropriately.
7698
7699       Transfer_Entities (S, Encl_S);
7700
7701       --  Mark the enclosing dynamic scope so that the sec stack will be
7702       --  released upon its exit unless this is a function that returns on
7703       --  the sec stack in which case this will be done by the caller.
7704
7705       if VM_Target = No_VM and then Uses_SS then
7706          S := Enclosing_Dynamic_Scope (S);
7707
7708          if Ekind (S) = E_Function
7709            and then Requires_Transient_Scope (Etype (S))
7710          then
7711             null;
7712          else
7713             Set_Uses_Sec_Stack (S);
7714             Check_Restriction (No_Secondary_Stack, N);
7715          end if;
7716       end if;
7717    end Wrap_Transient_Declaration;
7718
7719    -------------------------------
7720    -- Wrap_Transient_Expression --
7721    -------------------------------
7722
7723    procedure Wrap_Transient_Expression (N : Node_Id) is
7724       Expr : constant Node_Id    := Relocate_Node (N);
7725       Loc  : constant Source_Ptr := Sloc (N);
7726       Temp : constant Entity_Id  := Make_Temporary (Loc, 'E', N);
7727       Typ  : constant Entity_Id  := Etype (N);
7728
7729    begin
7730       --  Generate:
7731
7732       --    Temp : Typ;
7733       --    declare
7734       --       M : constant Mark_Id := SS_Mark;
7735       --       procedure Finalizer is ...  (See Build_Finalizer)
7736
7737       --    begin
7738       --       Temp := <Expr>;
7739       --
7740       --    at end
7741       --       Finalizer;
7742       --    end;
7743
7744       Insert_Actions (N, New_List (
7745         Make_Object_Declaration (Loc,
7746           Defining_Identifier => Temp,
7747           Object_Definition   => New_Reference_To (Typ, Loc)),
7748
7749         Make_Transient_Block (Loc,
7750           Action =>
7751             Make_Assignment_Statement (Loc,
7752               Name       => New_Reference_To (Temp, Loc),
7753               Expression => Expr),
7754           Par    => Parent (N))));
7755
7756       Rewrite (N, New_Reference_To (Temp, Loc));
7757       Analyze_And_Resolve (N, Typ);
7758    end Wrap_Transient_Expression;
7759
7760    ------------------------------
7761    -- Wrap_Transient_Statement --
7762    ------------------------------
7763
7764    procedure Wrap_Transient_Statement (N : Node_Id) is
7765       Loc      : constant Source_Ptr := Sloc (N);
7766       New_Stmt : constant Node_Id    := Relocate_Node (N);
7767
7768    begin
7769       --  Generate:
7770       --    declare
7771       --       M : constant Mark_Id := SS_Mark;
7772       --       procedure Finalizer is ...  (See Build_Finalizer)
7773       --
7774       --    begin
7775       --       <New_Stmt>;
7776       --
7777       --    at end
7778       --       Finalizer;
7779       --    end;
7780
7781       Rewrite (N,
7782         Make_Transient_Block (Loc,
7783           Action => New_Stmt,
7784           Par    => Parent (N)));
7785
7786       --  With the scope stack back to normal, we can call analyze on the
7787       --  resulting block. At this point, the transient scope is being
7788       --  treated like a perfectly normal scope, so there is nothing
7789       --  special about it.
7790
7791       --  Note: Wrap_Transient_Statement is called with the node already
7792       --  analyzed (i.e. Analyzed (N) is True). This is important, since
7793       --  otherwise we would get a recursive processing of the node when
7794       --  we do this Analyze call.
7795
7796       Analyze (N);
7797    end Wrap_Transient_Statement;
7798
7799 end Exp_Ch7;