]> gcc.gnu.org Git - gcc.git/blame - gcc/ada/exp_ch7.adb
ada: Refactor: replace uses of `not Present(X)` with `No (X)`
[gcc.git] / gcc / ada / exp_ch7.adb
CommitLineData
70482933
RK
1------------------------------------------------------------------------------
2-- --
3-- GNAT COMPILER COMPONENTS --
4-- --
5-- E X P _ C H 7 --
6-- --
7-- B o d y --
8-- --
bc0b26b9 9-- Copyright (C) 1992-2022, Free Software Foundation, Inc. --
70482933
RK
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- --
b5c84c3c 13-- ware Foundation; either version 3, or (at your option) any later ver- --
70482933
RK
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 --
b5c84c3c
RD
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. --
70482933
RK
20-- --
21-- GNAT was originally developed by the GNAT team at New York University. --
71ff80dc 22-- Extensive contributions were provided by Ada Core Technologies Inc. --
70482933
RK
23-- --
24------------------------------------------------------------------------------
25
26-- This package contains virtually all expansion mechanisms related to
27-- - controlled types
28-- - transient scopes
29
104f58db 30with Atree; use Atree;
104f58db
BD
31with Debug; use Debug;
32with Einfo; use Einfo;
76f9c7f4 33with Einfo.Entities; use Einfo.Entities;
104f58db
BD
34with Einfo.Utils; use Einfo.Utils;
35with Elists; use Elists;
36with Errout; use Errout;
37with Exp_Ch6; use Exp_Ch6;
38with Exp_Ch9; use Exp_Ch9;
39with Exp_Ch11; use Exp_Ch11;
40with Exp_Dbug; use Exp_Dbug;
41with Exp_Dist; use Exp_Dist;
42with Exp_Disp; use Exp_Disp;
43with Exp_Prag; use Exp_Prag;
44with Exp_Tss; use Exp_Tss;
45with Exp_Util; use Exp_Util;
46with Freeze; use Freeze;
47with GNAT_CUDA; use GNAT_CUDA;
48with Lib; use Lib;
49with Nlists; use Nlists;
50with Nmake; use Nmake;
51with Opt; use Opt;
52with Output; use Output;
53with Restrict; use Restrict;
54with Rident; use Rident;
55with Rtsfind; use Rtsfind;
56with Sinfo; use Sinfo;
57with Sinfo.Nodes; use Sinfo.Nodes;
58with Sinfo.Utils; use Sinfo.Utils;
59with Sem; use Sem;
60with Sem_Aux; use Sem_Aux;
104f58db
BD
61with Sem_Ch7; use Sem_Ch7;
62with Sem_Ch8; use Sem_Ch8;
63with Sem_Res; use Sem_Res;
64with Sem_Util; use Sem_Util;
65with Snames; use Snames;
66with Stand; use Stand;
67with Tbuild; use Tbuild;
68with Ttypes; use Ttypes;
69with Uintp; use Uintp;
70482933
RK
70
71package body Exp_Ch7 is
72
73 --------------------------------
74 -- Transient Scope Management --
75 --------------------------------
76
89e037d0
EB
77 -- A transient scope is needed when certain temporary objects are created
78 -- by the compiler. These temporary objects are allocated on the secondary
79 -- stack and/or need finalization, and the transient scope is responsible
80 -- for finalizing the objects and reclaiming the memory of the secondary
81 -- stack at the appropriate time. They are generally objects allocated to
82 -- store the result of a function returning an unconstrained or controlled
83 -- value. Expressions needing to be wrapped in a transient scope may appear
84 -- in three different contexts which lead to different kinds of transient
85 -- scope expansion:
70482933 86
886b5a18
AC
87 -- 1. In a simple statement (procedure call, assignment, ...). In this
88 -- case the instruction is wrapped into a transient block. See
89 -- Wrap_Transient_Statement for details.
70482933
RK
90
91 -- 2. In an expression of a control structure (test in a IF statement,
886b5a18
AC
92 -- expression in a CASE statement, ...). See Wrap_Transient_Expression
93 -- for details.
70482933
RK
94
95 -- 3. In a expression of an object_declaration. No wrapping is possible
36c73552 96 -- here, so the finalization actions, if any, are done right after the
70482933 97 -- declaration and the secondary stack deallocation is done in the
886b5a18 98 -- proper enclosing scope. See Wrap_Transient_Declaration for details.
70482933 99
70482933
RK
100 --------------------------------------------------
101 -- Transient Blocks and Finalization Management --
102 --------------------------------------------------
103
8e888920
AC
104 procedure Insert_Actions_In_Scope_Around
105 (N : Node_Id;
106 Clean : Boolean;
107 Manage_SS : Boolean);
70482933 108 -- Insert the before-actions kept in the scope stack before N, and the
8e888920
AC
109 -- after-actions after N, which must be a member of a list. If flag Clean
110 -- is set, insert any cleanup actions. If flag Manage_SS is set, insert
111 -- calls to mark and release the secondary stack.
70482933
RK
112
113 function Make_Transient_Block
114 (Loc : Source_Ptr;
df3e68b1
HK
115 Action : Node_Id;
116 Par : Node_Id) return Node_Id;
117 -- Action is a single statement or object declaration. Par is the proper
118 -- parent of the generated block. Create a transient block whose name is
119 -- the current scope and the only handled statement is Action. If Action
120 -- involves controlled objects or secondary stack usage, the corresponding
121 -- cleanup actions are performed at the end of the block.
70482933 122
36295779
AC
123 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id);
124 -- Shared processing for Store_xxx_Actions_In_Scope
125
70482933
RK
126 -----------------------------
127 -- Finalization Management --
128 -----------------------------
129
98208e36
MP
130 -- This part describes how Initialization/Adjustment/Finalization
131 -- procedures are generated and called. Two cases must be considered: types
132 -- that are Controlled (Is_Controlled flag set) and composite types that
133 -- contain controlled components (Has_Controlled_Component flag set). In
134 -- the first case the procedures to call are the user-defined primitive
135 -- operations Initialize/Adjust/Finalize. In the second case, GNAT
136 -- generates Deep_Initialize, Deep_Adjust and Deep_Finalize that are in
137 -- charge of calling the former procedures on the controlled components.
70482933
RK
138
139 -- For records with Has_Controlled_Component set, a hidden "controller"
140 -- component is inserted. This controller component contains its own
141 -- finalization list on which all controlled components are attached
142 -- creating an indirection on the upper-level Finalization list. This
143 -- technique facilitates the management of objects whose number of
144 -- controlled components changes during execution. This controller
145 -- component is itself controlled and is attached to the upper-level
dbe13a37 146 -- finalization chain. Its adjust primitive is in charge of calling adjust
8fc789c8 147 -- on the components and adjusting the finalization pointer to match their
dbe13a37 148 -- new location (see a-finali.adb).
70482933
RK
149
150 -- It is not possible to use a similar technique for arrays that have
151 -- Has_Controlled_Component set. In this case, deep procedures are
152 -- generated that call initialize/adjust/finalize + attachment or
153 -- detachment on the finalization list for all component.
154
155 -- Initialize calls: they are generated for declarations or dynamic
dbe13a37
ES
156 -- allocations of Controlled objects with no initial value. They are always
157 -- followed by an attachment to the current Finalization Chain. For the
158 -- dynamic allocation case this the chain attached to the scope of the
159 -- access type definition otherwise, this is the chain of the current
160 -- scope.
70482933 161
886b5a18
AC
162 -- Adjust Calls: They are generated on 2 occasions: (1) for declarations
163 -- or dynamic allocations of Controlled objects with an initial value.
164 -- (2) after an assignment. In the first case they are followed by an
165 -- attachment to the final chain, in the second case they are not.
70482933
RK
166
167 -- Finalization Calls: They are generated on (1) scope exit, (2)
168 -- assignments, (3) unchecked deallocations. In case (3) they have to
169 -- be detached from the final chain, in case (2) they must not and in
dbe13a37 170 -- case (1) this is not important since we are exiting the scope anyway.
70482933 171
fbf5a39b 172 -- Other details:
dbe13a37
ES
173
174 -- Type extensions will have a new record controller at each derivation
175 -- level containing controlled components. The record controller for
176 -- the parent/ancestor is attached to the finalization list of the
177 -- extension's record controller (i.e. the parent is like a component
178 -- of the extension).
179
180 -- For types that are both Is_Controlled and Has_Controlled_Components,
181 -- the record controller and the object itself are handled separately.
182 -- It could seem simpler to attach the object at the end of its record
183 -- controller but this would not tackle view conversions properly.
184
185 -- A classwide type can always potentially have controlled components
186 -- but the record controller of the corresponding actual type may not
187 -- be known at compile time so the dispatch table contains a special
6782b1ef 188 -- field that allows computation of the offset of the record controller
dbe13a37 189 -- dynamically. See s-finimp.Deep_Tag_Attach and a-tags.RC_Offset.
fbf5a39b 190
70482933
RK
191 -- Here is a simple example of the expansion of a controlled block :
192
193 -- declare
33c423c8 194 -- X : Controlled;
70482933
RK
195 -- Y : Controlled := Init;
196 --
197 -- type R is record
198 -- C : Controlled;
199 -- end record;
200 -- W : R;
201 -- Z : R := (C => X);
886b5a18 202
70482933
RK
203 -- begin
204 -- X := Y;
205 -- W := Z;
206 -- end;
207 --
208 -- is expanded into
209 --
210 -- declare
211 -- _L : System.FI.Finalizable_Ptr;
212
213 -- procedure _Clean is
214 -- begin
215 -- Abort_Defer;
216 -- System.FI.Finalize_List (_L);
217 -- Abort_Undefer;
218 -- end _Clean;
219
220 -- X : Controlled;
fbf5a39b
AC
221 -- begin
222 -- Abort_Defer;
223 -- Initialize (X);
224 -- Attach_To_Final_List (_L, Finalizable (X), 1);
225 -- at end: Abort_Undefer;
70482933
RK
226 -- Y : Controlled := Init;
227 -- Adjust (Y);
228 -- Attach_To_Final_List (_L, Finalizable (Y), 1);
229 --
230 -- type R is record
70482933
RK
231 -- C : Controlled;
232 -- end record;
233 -- W : R;
fbf5a39b
AC
234 -- begin
235 -- Abort_Defer;
236 -- Deep_Initialize (W, _L, 1);
237 -- at end: Abort_Under;
70482933
RK
238 -- Z : R := (C => X);
239 -- Deep_Adjust (Z, _L, 1);
240
241 -- begin
fbf5a39b 242 -- _Assign (X, Y);
70482933 243 -- Deep_Finalize (W, False);
fbf5a39b 244 -- <save W's final pointers>
70482933 245 -- W := Z;
fbf5a39b 246 -- <restore W's final pointers>
70482933
RK
247 -- Deep_Adjust (W, _L, 0);
248 -- at end
249 -- _Clean;
250 -- end;
251
df3e68b1
HK
252 type Final_Primitives is
253 (Initialize_Case, Adjust_Case, Finalize_Case, Address_Case);
254 -- This enumeration type is defined in order to ease sharing code for
255 -- building finalization procedures for composite types.
256
257 Name_Of : constant array (Final_Primitives) of Name_Id :=
258 (Initialize_Case => Name_Initialize,
259 Adjust_Case => Name_Adjust,
260 Finalize_Case => Name_Finalize,
261 Address_Case => Name_Finalize_Address);
df3e68b1
HK
262 Deep_Name_Of : constant array (Final_Primitives) of TSS_Name_Type :=
263 (Initialize_Case => TSS_Deep_Initialize,
264 Adjust_Case => TSS_Deep_Adjust,
265 Finalize_Case => TSS_Deep_Finalize,
266 Address_Case => TSS_Finalize_Address);
267
32b794c8
AC
268 function Allows_Finalization_Master (Typ : Entity_Id) return Boolean;
269 -- Determine whether access type Typ may have a finalization master
270
df3e68b1
HK
271 procedure Build_Array_Deep_Procs (Typ : Entity_Id);
272 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
273 -- Has_Controlled_Component set and store them using the TSS mechanism.
274
36295779
AC
275 function Build_Cleanup_Statements
276 (N : Node_Id;
277 Additional_Cleanup : List_Id) return List_Id;
40c21e91 278 -- Create the cleanup calls for an asynchronous call block, task master,
36295779
AC
279 -- protected subprogram body, task allocation block or task body, or
280 -- additional cleanup actions parked on a transient block. If the context
281 -- does not contain the above constructs, the routine returns an empty
282 -- list.
df3e68b1 283
df3e68b1
HK
284 procedure Build_Finalizer
285 (N : Node_Id;
286 Clean_Stmts : List_Id;
287 Mark_Id : Entity_Id;
288 Top_Decls : List_Id;
289 Defer_Abort : Boolean;
290 Fin_Id : out Entity_Id);
291 -- N may denote an accept statement, block, entry body, package body,
7b56a91b 292 -- package spec, protected body, subprogram body, or a task body. Create
df3e68b1
HK
293 -- a procedure which contains finalization calls for all controlled objects
294 -- declared in the declarative or statement region of N. The calls are
295 -- built in reverse order relative to the original declarations. In the
7b56a91b 296 -- case of a task body, the routine delays the creation of the finalizer
df3e68b1
HK
297 -- until all statements have been moved to the task body procedure.
298 -- Clean_Stmts may contain additional context-dependent code used to abort
299 -- asynchronous calls or complete tasks (see Build_Cleanup_Statements).
300 -- Mark_Id is the secondary stack used in the current context or Empty if
301 -- missing. Top_Decls is the list on which the declaration of the finalizer
302 -- is attached in the non-package case. Defer_Abort indicates that the
303 -- statements passed in perform actions that require abort to be deferred,
304 -- such as for task termination. Fin_Id is the finalizer declaration
305 -- entity.
306
307 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id);
6a91be29
BD
308 -- N is a construct that contains a handled sequence of statements, Fin_Id
309 -- is the entity of a finalizer. Create an At_End handler that covers the
df3e68b1
HK
310 -- statements of N and calls Fin_Id. If the handled statement sequence has
311 -- an exception handler, the statements will be wrapped in a block to avoid
312 -- unwanted interaction with the new At_End handler.
313
df3e68b1
HK
314 procedure Build_Record_Deep_Procs (Typ : Entity_Id);
315 -- Build the deep Initialize/Adjust/Finalize for a record Typ with
316 -- Has_Component_Component set and store them using the TSS mechanism.
317
e60c10b3
ES
318 -------------------------------------------
319 -- Unnesting procedures for CCG and LLVM --
320 -------------------------------------------
321
322 -- Expansion generates subprograms for controlled types management that
323 -- may appear in declarative lists in package declarations and bodies.
324 -- These subprograms appear within generated blocks that contain local
325 -- declarations and a call to finalization procedures. To ensure that
326 -- such subprograms get activation records when needed, we transform the
327 -- block into a procedure body, followed by a call to it in the same
328 -- declarative list.
329
86f32857
ES
330 procedure Check_Unnesting_Elaboration_Code (N : Node_Id);
331 -- The statement part of a package body that is a compilation unit may
f68289d8 332 -- contain blocks that declare local subprograms. In Subprogram_Unnesting_
86f32857
ES
333 -- Mode such subprograms must be handled as nested inside the (implicit)
334 -- elaboration procedure that executes that statement part. To handle
335 -- properly uplevel references we construct that subprogram explicitly,
e8bb6ff9 336 -- to contain blocks and inner subprograms, the statement part becomes
86f32857 337 -- a call to this subprogram. This is only done if blocks are present
f68289d8
GD
338 -- in the statement list of the body. (It would be nice to unify this
339 -- procedure with Check_Unnesting_In_Decls_Or_Stmts, if possible, since
340 -- they're doing very similar work, but are structured differently. ???)
341
342 procedure Check_Unnesting_In_Decls_Or_Stmts (Decls_Or_Stmts : List_Id);
343 -- Similarly, the declarations or statements in library-level packages may
604801a4 344 -- have created blocks with nested subprograms. Such a block must be
f68289d8
GD
345 -- transformed into a procedure followed by a call to it, so that unnesting
346 -- can handle uplevel references within these nested subprograms (typically
347 -- subprograms that handle finalization actions). This also applies to
348 -- nested packages, including instantiations, in which case it must
349 -- recursively process inner bodies.
350
351 procedure Check_Unnesting_In_Handlers (N : Node_Id);
352 -- Similarly, check for blocks with nested subprograms occurring within
353 -- a set of exception handlers associated with a package body N.
354
355 procedure Unnest_Block (Decl : Node_Id);
356 -- Blocks that contain nested subprograms with up-level references need to
357 -- create activation records for them. We do this by rewriting the block as
358 -- a procedure, followed by a call to it in the same declarative list, to
359 -- replicate the semantics of the original block.
360 --
361 -- A common source for such block is a transient block created for a
362 -- construct (declaration, assignment, etc.) that involves controlled
363 -- actions or secondary-stack management, in which case the nested
364 -- subprogram is a finalizer.
302319e0 365
05746958
GD
366 procedure Unnest_If_Statement (If_Stmt : Node_Id);
367 -- The separate statement lists associated with an if-statement (then part,
368 -- elsif parts, else part) may require unnesting if they directly contain
369 -- a subprogram body that references up-level objects. Each statement list
370 -- is traversed to locate such subprogram bodies, and if a part's statement
371 -- list contains a body, then the list is replaced with a new procedure
372 -- containing the part's statements followed by a call to the procedure.
373 -- Furthermore, any nested blocks, loops, or if statements will also be
374 -- traversed to determine the need for further unnesting transformations.
375
376 procedure Unnest_Statement_List (Stmts : in out List_Id);
377 -- A list of statements that directly contains a subprogram at its outer
378 -- level, that may reference objects declared in that same statement list,
379 -- is rewritten as a procedure containing the statement list Stmts (which
380 -- includes any such objects as well as the nested subprogram), followed by
381 -- a call to the new procedure, and Stmts becomes the list containing the
382 -- procedure and the call. This ensures that Unnest_Subprogram will later
383 -- properly handle up-level references from the nested subprogram to
384 -- objects declared earlier in statement list, by creating an activation
385 -- record and passing it to the nested subprogram. This procedure also
386 -- resets the Scope of objects declared in the statement list, as well as
387 -- the Scope of the nested subprogram, to refer to the new procedure.
388 -- Also, the new procedure is marked Has_Nested_Subprogram, so this should
389 -- only be called when known that the statement list contains a subprogram.
390
7e536bfd
GD
391 procedure Unnest_Loop (Loop_Stmt : Node_Id);
392 -- Top-level Loops that contain nested subprograms with up-level references
393 -- need to have activation records. We do this by rewriting the loop as a
394 -- procedure containing the loop, followed by a call to the procedure in
395 -- the same library-level declarative list, to replicate the semantics of
396 -- the original loop. Such loops can occur due to aggregate expansions and
397 -- other constructs.
398
df3e68b1
HK
399 procedure Check_Visibly_Controlled
400 (Prim : Final_Primitives;
401 Typ : Entity_Id;
402 E : in out Entity_Id;
403 Cref : in out Node_Id);
404 -- The controlled operation declared for a derived type may not be
405 -- overriding, if the controlled operations of the parent type are hidden,
406 -- for example when the parent is a private type whose full view is
407 -- controlled. For other primitive operations we modify the name of the
408 -- operation to indicate that it is not overriding, but this is not
409 -- possible for Initialize, etc. because they have to be retrievable by
410 -- name. Before generating the proper call to one of these operations we
411 -- check whether Typ is known to be controlled at the point of definition.
412 -- If it is not then we must retrieve the hidden operation of the parent
64ac53f4 413 -- and use it instead. This is one case that might be solved more cleanly
df3e68b1
HK
414 -- once Overriding pragmas or declarations are in place.
415
68f27c97
HK
416 function Contains_Subprogram (Blk : Entity_Id) return Boolean;
417 -- Check recursively whether a loop or block contains a subprogram that
418 -- may need an activation record.
419
df3e68b1
HK
420 function Convert_View
421 (Proc : Entity_Id;
422 Arg : Node_Id;
423 Ind : Pos := 1) return Node_Id;
424 -- Proc is one of the Initialize/Adjust/Finalize operations, and Arg is the
425 -- argument being passed to it. Ind indicates which formal of procedure
426 -- Proc we are trying to match. This function will, if necessary, generate
427 -- a conversion between the partial and full view of Arg to match the type
428 -- of the formal of Proc, or force a conversion to the class-wide type in
429 -- the case where the operation is abstract.
430
df3e68b1 431 function Make_Call
4ac2bbbd
AC
432 (Loc : Source_Ptr;
433 Proc_Id : Entity_Id;
434 Param : Node_Id;
435 Skip_Self : Boolean := False) return Node_Id;
df3e68b1 436 -- Subsidiary to Make_Adjust_Call and Make_Final_Call. Given the entity of
4ac2bbbd 437 -- routine [Deep_]Adjust or [Deep_]Finalize and an object parameter, create
7c092960 438 -- an adjust or finalization call. When flag Skip_Self is set, the related
4ac2bbbd 439 -- action has an effect on the components only (if any).
df3e68b1
HK
440
441 function Make_Deep_Proc
442 (Prim : Final_Primitives;
443 Typ : Entity_Id;
c0471c61 444 Stmts : List_Id) return Entity_Id;
df3e68b1 445 -- This function generates the tree for Deep_Initialize, Deep_Adjust or
c0471c61
BD
446 -- Deep_Finalize procedures according to the first parameter. These
447 -- procedures operate on the type Typ. The Stmts parameter gives the
448 -- body of the procedure.
df3e68b1
HK
449
450 function Make_Deep_Array_Body
451 (Prim : Final_Primitives;
452 Typ : Entity_Id) return List_Id;
453 -- This function generates the list of statements for implementing
454 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
455 -- the first parameter, these procedures operate on the array type Typ.
456
457 function Make_Deep_Record_Body
458 (Prim : Final_Primitives;
459 Typ : Entity_Id;
460 Is_Local : Boolean := False) return List_Id;
461 -- This function generates the list of statements for implementing
462 -- Deep_Initialize, Deep_Adjust or Deep_Finalize procedures according to
463 -- the first parameter, these procedures operate on the record type Typ.
464 -- Flag Is_Local is used in conjunction with Deep_Finalize to designate
465 -- whether the inner logic should be dictated by state counters.
70482933 466
df3e68b1 467 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id;
d3f70b35
AC
468 -- Subsidiary to Make_Finalize_Address_Body, Make_Deep_Array_Body and
469 -- Make_Deep_Record_Body. Generate the following statements:
df3e68b1
HK
470 --
471 -- declare
472 -- type Acc_Typ is access all Typ;
473 -- for Acc_Typ'Storage_Size use 0;
474 -- begin
475 -- [Deep_]Finalize (Acc_Typ (V).all);
476 -- end;
fbf5a39b 477
32b794c8
AC
478 --------------------------------
479 -- Allows_Finalization_Master --
480 --------------------------------
481
482 function Allows_Finalization_Master (Typ : Entity_Id) return Boolean is
483 function In_Deallocation_Instance (E : Entity_Id) return Boolean;
484 -- Determine whether entity E is inside a wrapper package created for
485 -- an instance of Ada.Unchecked_Deallocation.
486
487 ------------------------------
488 -- In_Deallocation_Instance --
489 ------------------------------
490
491 function In_Deallocation_Instance (E : Entity_Id) return Boolean is
492 Pkg : constant Entity_Id := Scope (E);
493 Par : Node_Id := Empty;
494
495 begin
496 if Ekind (Pkg) = E_Package
497 and then Present (Related_Instance (Pkg))
498 and then Ekind (Related_Instance (Pkg)) = E_Procedure
499 then
500 Par := Generic_Parent (Parent (Related_Instance (Pkg)));
501
502 return
503 Present (Par)
504 and then Chars (Par) = Name_Unchecked_Deallocation
505 and then Chars (Scope (Par)) = Name_Ada
506 and then Scope (Scope (Par)) = Standard_Standard;
507 end if;
508
509 return False;
510 end In_Deallocation_Instance;
511
512 -- Local variables
513
514 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
515 Ptr_Typ : constant Entity_Id :=
516 Root_Type_Of_Full_View (Base_Type (Typ));
517
518 -- Start of processing for Allows_Finalization_Master
519
520 begin
521 -- Certain run-time configurations and targets do not provide support
522 -- for controlled types and therefore do not need masters.
523
524 if Restriction_Active (No_Finalization) then
525 return False;
526
527 -- Do not consider C and C++ types since it is assumed that the non-Ada
40c21e91 528 -- side will handle their cleanup.
32b794c8
AC
529
530 elsif Convention (Desig_Typ) = Convention_C
531 or else Convention (Desig_Typ) = Convention_CPP
532 then
533 return False;
534
ded462b0 535 -- Do not consider an access type that returns on the secondary stack
32b794c8
AC
536
537 elsif Present (Associated_Storage_Pool (Ptr_Typ))
538 and then Is_RTE (Associated_Storage_Pool (Ptr_Typ), RE_SS_Pool)
539 then
540 return False;
541
ded462b0 542 -- Do not consider an access type that can never allocate an object
32b794c8
AC
543
544 elsif No_Pool_Assigned (Ptr_Typ) then
545 return False;
546
d1eb8a82
AC
547 -- Do not consider an access type coming from an Unchecked_Deallocation
548 -- instance. Even though the designated type may be controlled, the
549 -- access type will never participate in any allocations.
32b794c8
AC
550
551 elsif In_Deallocation_Instance (Ptr_Typ) then
552 return False;
553
d1eb8a82
AC
554 -- Do not consider a non-library access type when No_Nested_Finalization
555 -- is in effect since finalization masters are controlled objects and if
556 -- created will violate the restriction.
32b794c8
AC
557
558 elsif Restriction_Active (No_Nested_Finalization)
559 and then not Is_Library_Level_Entity (Ptr_Typ)
560 then
561 return False;
562
d1eb8a82
AC
563 -- Do not consider an access type subject to pragma No_Heap_Finalization
564 -- because objects allocated through such a type are not to be finalized
565 -- when the access type goes out of scope.
566
567 elsif No_Heap_Finalization (Ptr_Typ) then
568 return False;
569
32b794c8
AC
570 -- Do not create finalization masters in GNATprove mode because this
571 -- causes unwanted extra expansion. A compilation in this mode must
572 -- keep the tree as close as possible to the original sources.
573
574 elsif GNATprove_Mode then
575 return False;
576
577 -- Otherwise the access type may use a finalization master
578
579 else
580 return True;
581 end if;
582 end Allows_Finalization_Master;
583
584 ----------------------------
585 -- Build_Anonymous_Master --
586 ----------------------------
587
588 procedure Build_Anonymous_Master (Ptr_Typ : Entity_Id) is
589 function Create_Anonymous_Master
590 (Desig_Typ : Entity_Id;
591 Unit_Id : Entity_Id;
592 Unit_Decl : Node_Id) return Entity_Id;
5b42c035
AC
593 -- Create a new anonymous master for access type Ptr_Typ with designated
594 -- type Desig_Typ. The declaration of the master and its initialization
595 -- are inserted in the declarative part of unit Unit_Decl. Unit_Id is
596 -- the entity of Unit_Decl.
32b794c8 597
5b42c035
AC
598 function Current_Anonymous_Master
599 (Desig_Typ : Entity_Id;
600 Unit_Id : Entity_Id) return Entity_Id;
601 -- Find an anonymous master declared within unit Unit_Id which services
602 -- designated type Desig_Typ. If there is no such master, return Empty.
32b794c8
AC
603
604 -----------------------------
605 -- Create_Anonymous_Master --
606 -----------------------------
607
608 function Create_Anonymous_Master
609 (Desig_Typ : Entity_Id;
610 Unit_Id : Entity_Id;
611 Unit_Decl : Node_Id) return Entity_Id
612 is
5b42c035
AC
613 Loc : constant Source_Ptr := Sloc (Unit_Id);
614
615 All_FMs : Elist_Id;
32b794c8
AC
616 Decls : List_Id;
617 FM_Decl : Node_Id;
618 FM_Id : Entity_Id;
619 FM_Init : Node_Id;
32b794c8
AC
620 Unit_Spec : Node_Id;
621
622 begin
5b42c035
AC
623 -- Generate:
624 -- <FM_Id> : Finalization_Master;
625
626 FM_Id := Make_Temporary (Loc, 'A');
627
628 FM_Decl :=
629 Make_Object_Declaration (Loc,
630 Defining_Identifier => FM_Id,
631 Object_Definition =>
632 New_Occurrence_Of (RTE (RE_Finalization_Master), Loc));
633
634 -- Generate:
635 -- Set_Base_Pool
636 -- (<FM_Id>, Global_Pool_Object'Unrestricted_Access);
637
638 FM_Init :=
639 Make_Procedure_Call_Statement (Loc,
640 Name =>
641 New_Occurrence_Of (RTE (RE_Set_Base_Pool), Loc),
642 Parameter_Associations => New_List (
643 New_Occurrence_Of (FM_Id, Loc),
644 Make_Attribute_Reference (Loc,
645 Prefix =>
646 New_Occurrence_Of (RTE (RE_Global_Pool_Object), Loc),
647 Attribute_Name => Name_Unrestricted_Access)));
648
32b794c8
AC
649 -- Find the declarative list of the unit
650
651 if Nkind (Unit_Decl) = N_Package_Declaration then
652 Unit_Spec := Specification (Unit_Decl);
653 Decls := Visible_Declarations (Unit_Spec);
654
655 if No (Decls) then
656 Decls := New_List;
657 Set_Visible_Declarations (Unit_Spec, Decls);
658 end if;
659
660 -- Package body or subprogram case
661
662 -- ??? A subprogram spec or body that acts as a compilation unit may
663 -- contain a formal parameter of an anonymous access-to-controlled
664 -- type initialized by an allocator.
665
666 -- procedure Comp_Unit_Proc (Param : access Ctrl := new Ctrl);
667
5b42c035
AC
668 -- There is no suitable place to create the master as the subprogram
669 -- is not in a declarative list.
32b794c8
AC
670
671 else
672 Decls := Declarations (Unit_Decl);
673
674 if No (Decls) then
675 Decls := New_List;
676 Set_Declarations (Unit_Decl, Decls);
677 end if;
678 end if;
679
5b42c035
AC
680 Prepend_To (Decls, FM_Init);
681 Prepend_To (Decls, FM_Decl);
32b794c8 682
5b42c035
AC
683 -- Use the scope of the unit when analyzing the declaration of the
684 -- master and its initialization actions.
32b794c8 685
5b42c035
AC
686 Push_Scope (Unit_Id);
687 Analyze (FM_Decl);
688 Analyze (FM_Init);
689 Pop_Scope;
32b794c8 690
5b42c035 691 -- Mark the master as servicing this specific designated type
32b794c8 692
5b42c035 693 Set_Anonymous_Designated_Type (FM_Id, Desig_Typ);
32b794c8 694
5b42c035
AC
695 -- Include the anonymous master in the list of existing masters which
696 -- appear in this unit. This effectively creates a mapping between a
c9d2e84b
GD
697 -- master and a designated type which in turn allows for the reuse of
698 -- masters on a per-unit basis.
32b794c8 699
5b42c035 700 All_FMs := Anonymous_Masters (Unit_Id);
32b794c8 701
5b42c035
AC
702 if No (All_FMs) then
703 All_FMs := New_Elmt_List;
704 Set_Anonymous_Masters (Unit_Id, All_FMs);
705 end if;
32b794c8 706
5b42c035 707 Prepend_Elmt (FM_Id, All_FMs);
32b794c8
AC
708
709 return FM_Id;
710 end Create_Anonymous_Master;
711
5b42c035
AC
712 ------------------------------
713 -- Current_Anonymous_Master --
714 ------------------------------
32b794c8 715
5b42c035
AC
716 function Current_Anonymous_Master
717 (Desig_Typ : Entity_Id;
718 Unit_Id : Entity_Id) return Entity_Id
719 is
720 All_FMs : constant Elist_Id := Anonymous_Masters (Unit_Id);
721 FM_Elmt : Elmt_Id;
722 FM_Id : Entity_Id;
32b794c8
AC
723
724 begin
5b42c035
AC
725 -- Inspect the list of anonymous masters declared within the unit
726 -- looking for an existing master which services the same designated
727 -- type.
32b794c8 728
5b42c035
AC
729 if Present (All_FMs) then
730 FM_Elmt := First_Elmt (All_FMs);
731 while Present (FM_Elmt) loop
732 FM_Id := Node (FM_Elmt);
32b794c8 733
5b42c035
AC
734 -- The currect master services the same designated type. As a
735 -- result the master can be reused and associated with another
736 -- anonymous access-to-controlled type.
32b794c8 737
5b42c035
AC
738 if Anonymous_Designated_Type (FM_Id) = Desig_Typ then
739 return FM_Id;
740 end if;
741
742 Next_Elmt (FM_Elmt);
743 end loop;
744 end if;
745
746 return Empty;
747 end Current_Anonymous_Master;
32b794c8
AC
748
749 -- Local variables
750
751 Desig_Typ : Entity_Id;
752 FM_Id : Entity_Id;
753 Priv_View : Entity_Id;
754 Unit_Decl : Node_Id;
755 Unit_Id : Entity_Id;
756
757 -- Start of processing for Build_Anonymous_Master
758
759 begin
760 -- Nothing to do if the circumstances do not allow for a finalization
761 -- master.
762
763 if not Allows_Finalization_Master (Ptr_Typ) then
764 return;
765 end if;
766
767 Unit_Decl := Unit (Cunit (Current_Sem_Unit));
5b42c035 768 Unit_Id := Unique_Defining_Entity (Unit_Decl);
32b794c8
AC
769
770 -- The compilation unit is a package instantiation. In this case the
771 -- anonymous master is associated with the package spec as both the
772 -- spec and body appear at the same level.
773
774 if Nkind (Unit_Decl) = N_Package_Body
775 and then Nkind (Original_Node (Unit_Decl)) = N_Package_Instantiation
776 then
777 Unit_Id := Corresponding_Spec (Unit_Decl);
778 Unit_Decl := Unit_Declaration_Node (Unit_Id);
779 end if;
780
781 -- Use the initial declaration of the designated type when it denotes
782 -- the full view of an incomplete or private type. This ensures that
783 -- types with one and two views are treated the same.
784
785 Desig_Typ := Directly_Designated_Type (Ptr_Typ);
786 Priv_View := Incomplete_Or_Partial_View (Desig_Typ);
787
788 if Present (Priv_View) then
789 Desig_Typ := Priv_View;
790 end if;
791
5b42c035
AC
792 -- Determine whether the current semantic unit already has an anonymous
793 -- master which services the designated type.
32b794c8 794
5b42c035 795 FM_Id := Current_Anonymous_Master (Desig_Typ, Unit_Id);
32b794c8 796
5b42c035 797 -- If this is not the case, create a new master
32b794c8 798
5b42c035 799 if No (FM_Id) then
32b794c8
AC
800 FM_Id := Create_Anonymous_Master (Desig_Typ, Unit_Id, Unit_Decl);
801 end if;
802
803 Set_Finalization_Master (Ptr_Typ, FM_Id);
804 end Build_Anonymous_Master;
805
70482933
RK
806 ----------------------------
807 -- Build_Array_Deep_Procs --
808 ----------------------------
809
810 procedure Build_Array_Deep_Procs (Typ : Entity_Id) is
811 begin
812 Set_TSS (Typ,
cfae2bed
AC
813 Make_Deep_Proc
814 (Prim => Initialize_Case,
815 Typ => Typ,
816 Stmts => Make_Deep_Array_Body (Initialize_Case, Typ)));
70482933 817
51245e2d 818 if not Is_Limited_View (Typ) then
70482933 819 Set_TSS (Typ,
cfae2bed
AC
820 Make_Deep_Proc
821 (Prim => Adjust_Case,
822 Typ => Typ,
823 Stmts => Make_Deep_Array_Body (Adjust_Case, Typ)));
70482933
RK
824 end if;
825
d2b4b3da
AC
826 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
827 -- suppressed since these routine will not be used.
70482933 828
d2b4b3da 829 if not Restriction_Active (No_Finalization) then
df3e68b1 830 Set_TSS (Typ,
2c1b72d7 831 Make_Deep_Proc
d2b4b3da 832 (Prim => Finalize_Case,
2c1b72d7 833 Typ => Typ,
d2b4b3da
AC
834 Stmts => Make_Deep_Array_Body (Finalize_Case, Typ)));
835
94295b25 836 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
d2b4b3da 837
89b6c83e
AC
838 if not CodePeer_Mode then
839 Set_TSS (Typ,
840 Make_Deep_Proc
841 (Prim => Address_Case,
842 Typ => Typ,
843 Stmts => Make_Deep_Array_Body (Address_Case, Typ)));
844 end if;
70482933 845 end if;
df3e68b1 846 end Build_Array_Deep_Procs;
70482933 847
df3e68b1
HK
848 ------------------------------
849 -- Build_Cleanup_Statements --
850 ------------------------------
70482933 851
36295779
AC
852 function Build_Cleanup_Statements
853 (N : Node_Id;
854 Additional_Cleanup : List_Id) return List_Id
855 is
df3e68b1 856 Is_Asynchronous_Call : constant Boolean :=
dba07790
BD
857 Nkind (N) = N_Block_Statement and then Is_Asynchronous_Call_Block (N);
858 Is_Master : constant Boolean :=
859 Nkind (N) /= N_Entry_Body and then Is_Task_Master (N);
860 Is_Protected_Subp_Body : constant Boolean :=
861 Nkind (N) = N_Subprogram_Body
862 and then Is_Protected_Subprogram_Body (N);
863 Is_Task_Allocation : constant Boolean :=
864 Nkind (N) = N_Block_Statement and then Is_Task_Allocation_Block (N);
865 Is_Task_Body : constant Boolean :=
866 Nkind (Original_Node (N)) = N_Task_Body;
2c1b72d7 867
df3e68b1
HK
868 Loc : constant Source_Ptr := Sloc (N);
869 Stmts : constant List_Id := New_List;
70482933
RK
870
871 begin
df3e68b1
HK
872 if Is_Task_Body then
873 if Restricted_Profile then
874 Append_To (Stmts,
875 Build_Runtime_Call (Loc, RE_Complete_Restricted_Task));
876 else
877 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Task));
878 end if;
70482933 879
df3e68b1
HK
880 elsif Is_Master then
881 if Restriction_Active (No_Task_Hierarchy) = False then
882 Append_To (Stmts, Build_Runtime_Call (Loc, RE_Complete_Master));
883 end if;
66713d62 884
df3e68b1
HK
885 -- Add statements to unlock the protected object parameter and to
886 -- undefer abort. If the context is a protected procedure and the object
887 -- has entries, call the entry service routine.
07fc65c4 888
df3e68b1 889 -- NOTE: The generated code references _object, a parameter to the
886b5a18 890 -- procedure.
b603e37b 891
dba07790 892 elsif Is_Protected_Subp_Body then
df3e68b1
HK
893 declare
894 Spec : constant Node_Id := Parent (Corresponding_Spec (N));
a6b13d32 895 Conc_Typ : Entity_Id := Empty;
df3e68b1
HK
896 Param : Node_Id;
897 Param_Typ : Entity_Id;
70482933 898
df3e68b1
HK
899 begin
900 -- Find the _object parameter representing the protected object
07fc65c4 901
df3e68b1
HK
902 Param := First (Parameter_Specifications (Spec));
903 loop
904 Param_Typ := Etype (Parameter_Type (Param));
07fc65c4 905
df3e68b1
HK
906 if Ekind (Param_Typ) = E_Record_Type then
907 Conc_Typ := Corresponding_Concurrent_Type (Param_Typ);
908 end if;
70482933 909
df3e68b1
HK
910 exit when No (Param) or else Present (Conc_Typ);
911 Next (Param);
912 end loop;
70482933 913
df3e68b1 914 pragma Assert (Present (Param));
a6b13d32 915 pragma Assert (Present (Conc_Typ));
70482933 916
29077c18
AC
917 Build_Protected_Subprogram_Call_Cleanup
918 (Specification (N), Conc_Typ, Loc, Stmts);
df3e68b1 919 end;
fbf5a39b 920
df3e68b1
HK
921 -- Add a call to Expunge_Unactivated_Tasks for dynamically allocated
922 -- tasks. Other unactivated tasks are completed by Complete_Task or
923 -- Complete_Master.
fbf5a39b 924
df3e68b1 925 -- NOTE: The generated code references _chain, a local object
fbf5a39b 926
df3e68b1 927 elsif Is_Task_Allocation then
fbf5a39b 928
df3e68b1
HK
929 -- Generate:
930 -- Expunge_Unactivated_Tasks (_chain);
fbf5a39b 931
df3e68b1
HK
932 -- where _chain is the list of tasks created by the allocator but not
933 -- yet activated. This list will be empty unless the block completes
934 -- abnormally.
fbf5a39b 935
df3e68b1
HK
936 Append_To (Stmts,
937 Make_Procedure_Call_Statement (Loc,
938 Name =>
e4494292 939 New_Occurrence_Of
2c1b72d7 940 (RTE (RE_Expunge_Unactivated_Tasks), Loc),
df3e68b1 941 Parameter_Associations => New_List (
e4494292 942 New_Occurrence_Of (Activation_Chain_Entity (N), Loc))));
fbf5a39b 943
df3e68b1
HK
944 -- Attempt to cancel an asynchronous entry call whenever the block which
945 -- contains the abortable part is exited.
fbf5a39b 946
df3e68b1 947 -- NOTE: The generated code references Cnn, a local object
fbf5a39b 948
df3e68b1
HK
949 elsif Is_Asynchronous_Call then
950 declare
951 Cancel_Param : constant Entity_Id :=
952 Entry_Cancel_Parameter (Entity (Identifier (N)));
fbf5a39b 953
df3e68b1
HK
954 begin
955 -- If it is of type Communication_Block, this must be a protected
956 -- entry call. Generate:
957
958 -- if Enqueued (Cancel_Param) then
959 -- Cancel_Protected_Entry_Call (Cancel_Param);
960 -- end if;
961
962 if Is_RTE (Etype (Cancel_Param), RE_Communication_Block) then
963 Append_To (Stmts,
964 Make_If_Statement (Loc,
965 Condition =>
966 Make_Function_Call (Loc,
2c1b72d7 967 Name =>
e4494292 968 New_Occurrence_Of (RTE (RE_Enqueued), Loc),
df3e68b1 969 Parameter_Associations => New_List (
e4494292 970 New_Occurrence_Of (Cancel_Param, Loc))),
fbf5a39b 971
df3e68b1
HK
972 Then_Statements => New_List (
973 Make_Procedure_Call_Statement (Loc,
974 Name =>
e4494292 975 New_Occurrence_Of
2c1b72d7 976 (RTE (RE_Cancel_Protected_Entry_Call), Loc),
df3e68b1 977 Parameter_Associations => New_List (
e4494292 978 New_Occurrence_Of (Cancel_Param, Loc))))));
fbf5a39b 979
df3e68b1
HK
980 -- Asynchronous delay, generate:
981 -- Cancel_Async_Delay (Cancel_Param);
fbf5a39b 982
df3e68b1
HK
983 elsif Is_RTE (Etype (Cancel_Param), RE_Delay_Block) then
984 Append_To (Stmts,
985 Make_Procedure_Call_Statement (Loc,
2c1b72d7 986 Name =>
e4494292 987 New_Occurrence_Of (RTE (RE_Cancel_Async_Delay), Loc),
df3e68b1
HK
988 Parameter_Associations => New_List (
989 Make_Attribute_Reference (Loc,
2c1b72d7 990 Prefix =>
e4494292 991 New_Occurrence_Of (Cancel_Param, Loc),
df3e68b1
HK
992 Attribute_Name => Name_Unchecked_Access))));
993
994 -- Task entry call, generate:
995 -- Cancel_Task_Entry_Call (Cancel_Param);
996
997 else
998 Append_To (Stmts,
999 Make_Procedure_Call_Statement (Loc,
2c1b72d7 1000 Name =>
e4494292 1001 New_Occurrence_Of (RTE (RE_Cancel_Task_Entry_Call), Loc),
df3e68b1 1002 Parameter_Associations => New_List (
e4494292 1003 New_Occurrence_Of (Cancel_Param, Loc))));
df3e68b1
HK
1004 end if;
1005 end;
fbf5a39b
AC
1006 end if;
1007
36295779 1008 Append_List_To (Stmts, Additional_Cleanup);
df3e68b1
HK
1009 return Stmts;
1010 end Build_Cleanup_Statements;
fbf5a39b 1011
df3e68b1
HK
1012 -----------------------------
1013 -- Build_Controlling_Procs --
1014 -----------------------------
fbf5a39b 1015
df3e68b1
HK
1016 procedure Build_Controlling_Procs (Typ : Entity_Id) is
1017 begin
1018 if Is_Array_Type (Typ) then
1019 Build_Array_Deep_Procs (Typ);
df3e68b1
HK
1020 else pragma Assert (Is_Record_Type (Typ));
1021 Build_Record_Deep_Procs (Typ);
1022 end if;
1023 end Build_Controlling_Procs;
fbf5a39b 1024
df3e68b1
HK
1025 -----------------------------
1026 -- Build_Exception_Handler --
1027 -----------------------------
fbf5a39b 1028
df3e68b1 1029 function Build_Exception_Handler
36b8f95f 1030 (Data : Finalization_Exception_Data;
df3e68b1
HK
1031 For_Library : Boolean := False) return Node_Id
1032 is
1033 Actuals : List_Id;
1034 Proc_To_Call : Entity_Id;
e5a22243 1035 Except : Node_Id;
23adb371 1036 Stmts : List_Id;
fbf5a39b 1037
df3e68b1 1038 begin
36b8f95f 1039 pragma Assert (Present (Data.Raised_Id));
fbf5a39b 1040
23adb371 1041 if Exception_Extra_Info
799d0e05 1042 or else (For_Library and not Restricted_Profile)
23adb371
AC
1043 then
1044 if Exception_Extra_Info then
799d0e05 1045
23adb371 1046 -- Generate:
fbf5a39b 1047
23adb371 1048 -- Get_Current_Excep.all
e5a22243 1049
23adb371
AC
1050 Except :=
1051 Make_Function_Call (Data.Loc,
1052 Name =>
1053 Make_Explicit_Dereference (Data.Loc,
1054 Prefix =>
e4494292 1055 New_Occurrence_Of
799d0e05
AC
1056 (RTE (RE_Get_Current_Excep), Data.Loc)));
1057
23adb371
AC
1058 else
1059 -- Generate:
e5a22243 1060
23adb371
AC
1061 -- null
1062
1063 Except := Make_Null (Data.Loc);
1064 end if;
1065
1066 if For_Library and then not Restricted_Profile then
1067 Proc_To_Call := RTE (RE_Save_Library_Occurrence);
1068 Actuals := New_List (Except);
799d0e05 1069
23adb371
AC
1070 else
1071 Proc_To_Call := RTE (RE_Save_Occurrence);
1072
1073 -- The dereference occurs only when Exception_Extra_Info is true,
1074 -- and therefore Except is not null.
1075
799d0e05
AC
1076 Actuals :=
1077 New_List (
e4494292 1078 New_Occurrence_Of (Data.E_Id, Data.Loc),
799d0e05 1079 Make_Explicit_Dereference (Data.Loc, Except));
23adb371
AC
1080 end if;
1081
1082 -- Generate:
1083
1084 -- when others =>
1085 -- if not Raised_Id then
1086 -- Raised_Id := True;
1087
1088 -- Save_Occurrence (E_Id, Get_Current_Excep.all.all);
1089 -- or
1090 -- Save_Library_Occurrence (Get_Current_Excep.all);
1091 -- end if;
1092
1093 Stmts :=
1094 New_List (
1095 Make_If_Statement (Data.Loc,
1096 Condition =>
1097 Make_Op_Not (Data.Loc,
e4494292 1098 Right_Opnd => New_Occurrence_Of (Data.Raised_Id, Data.Loc)),
23adb371
AC
1099
1100 Then_Statements => New_List (
1101 Make_Assignment_Statement (Data.Loc,
e4494292
RD
1102 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1103 Expression => New_Occurrence_Of (Standard_True, Data.Loc)),
23adb371
AC
1104
1105 Make_Procedure_Call_Statement (Data.Loc,
1106 Name =>
e4494292 1107 New_Occurrence_Of (Proc_To_Call, Data.Loc),
23adb371
AC
1108 Parameter_Associations => Actuals))));
1109
1110 else
1111 -- Generate:
1112
1113 -- Raised_Id := True;
1114
1115 Stmts := New_List (
1116 Make_Assignment_Statement (Data.Loc,
e4494292
RD
1117 Name => New_Occurrence_Of (Data.Raised_Id, Data.Loc),
1118 Expression => New_Occurrence_Of (Standard_True, Data.Loc)));
df3e68b1 1119 end if;
fbf5a39b 1120
df3e68b1 1121 -- Generate:
e5a22243 1122
df3e68b1 1123 -- when others =>
fbf5a39b 1124
df3e68b1 1125 return
36b8f95f 1126 Make_Exception_Handler (Data.Loc,
23adb371
AC
1127 Exception_Choices => New_List (Make_Others_Choice (Data.Loc)),
1128 Statements => Stmts);
df3e68b1 1129 end Build_Exception_Handler;
fbf5a39b 1130
d3f70b35
AC
1131 -------------------------------
1132 -- Build_Finalization_Master --
1133 -------------------------------
fbf5a39b 1134
d3f70b35 1135 procedure Build_Finalization_Master
760804f3 1136 (Typ : Entity_Id;
8434cfc7 1137 For_Lib_Level : Boolean := False;
760804f3
AC
1138 For_Private : Boolean := False;
1139 Context_Scope : Entity_Id := Empty;
1140 Insertion_Node : Node_Id := Empty)
df3e68b1 1141 is
760804f3
AC
1142 procedure Add_Pending_Access_Type
1143 (Typ : Entity_Id;
1144 Ptr_Typ : Entity_Id);
1145 -- Add access type Ptr_Typ to the pending access type list for type Typ
1146
760804f3
AC
1147 -----------------------------
1148 -- Add_Pending_Access_Type --
1149 -----------------------------
1150
1151 procedure Add_Pending_Access_Type
1152 (Typ : Entity_Id;
1153 Ptr_Typ : Entity_Id)
1154 is
1155 List : Elist_Id;
1156
1157 begin
1158 if Present (Pending_Access_Types (Typ)) then
1159 List := Pending_Access_Types (Typ);
1160 else
1161 List := New_Elmt_List;
1162 Set_Pending_Access_Types (Typ, List);
1163 end if;
1164
1165 Prepend_Elmt (Ptr_Typ, List);
1166 end Add_Pending_Access_Type;
1167
8a5e4b2a
AC
1168 -- Local variables
1169
760804f3 1170 Desig_Typ : constant Entity_Id := Designated_Type (Typ);
8a5e4b2a
AC
1171
1172 Ptr_Typ : constant Entity_Id := Root_Type_Of_Full_View (Base_Type (Typ));
1173 -- A finalization master created for a named access type is associated
1174 -- with the full view (if applicable) as a consequence of freezing. The
1175 -- full view criteria does not apply to anonymous access types because
1176 -- those cannot have a private and a full view.
1177
d3f70b35 1178 -- Start of processing for Build_Finalization_Master
fbf5a39b 1179
df3e68b1 1180 begin
32b794c8
AC
1181 -- Nothing to do if the circumstances do not allow for a finalization
1182 -- master.
f553e7bc 1183
32b794c8 1184 if not Allows_Finalization_Master (Typ) then
ca5af305
AC
1185 return;
1186
f553e7bc 1187 -- Various machinery such as freezing may have already created a
d3f70b35 1188 -- finalization master.
f553e7bc 1189
ca5af305 1190 elsif Present (Finalization_Master (Ptr_Typ)) then
df3e68b1 1191 return;
fbf5a39b 1192 end if;
fbf5a39b 1193
df3e68b1 1194 declare
760804f3 1195 Actions : constant List_Id := New_List;
ca5af305 1196 Loc : constant Source_Ptr := Sloc (Ptr_Typ);
d3f70b35
AC
1197 Fin_Mas_Id : Entity_Id;
1198 Pool_Id : Entity_Id;
fbf5a39b 1199
df3e68b1 1200 begin
d3f70b35
AC
1201 -- Source access types use fixed master names since the master is
1202 -- inserted in the same source unit only once. The only exception to
1203 -- this are instances using the same access type as generic actual.
df3e68b1 1204
36295779 1205 if Comes_From_Source (Ptr_Typ) and then not Inside_A_Generic then
d3f70b35 1206 Fin_Mas_Id :=
df3e68b1 1207 Make_Defining_Identifier (Loc,
d3f70b35
AC
1208 Chars => New_External_Name (Chars (Ptr_Typ), "FM"));
1209
1210 -- Internally generated access types use temporaries as their names
1211 -- due to possible collision with identical names coming from other
1212 -- packages.
1213
df3e68b1 1214 else
d3f70b35 1215 Fin_Mas_Id := Make_Temporary (Loc, 'F');
df3e68b1 1216 end if;
fbf5a39b 1217
760804f3
AC
1218 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
1219
1220 -- Generate:
1221 -- <Ptr_Typ>FM : aliased Finalization_Master;
1222
df3e68b1
HK
1223 Append_To (Actions,
1224 Make_Object_Declaration (Loc,
d3f70b35
AC
1225 Defining_Identifier => Fin_Mas_Id,
1226 Aliased_Present => True,
cfae2bed 1227 Object_Definition =>
e4494292 1228 New_Occurrence_Of (RTE (RE_Finalization_Master), Loc)));
fbf5a39b 1229
bbf14e13
AC
1230 if Debug_Generated_Code then
1231 Set_Debug_Info_Needed (Fin_Mas_Id);
1232 end if;
1233
760804f3 1234 -- Set the associated pool and primitive Finalize_Address of the new
535a8637 1235 -- finalization master.
fbf5a39b 1236
535a8637 1237 -- The access type has a user-defined storage pool, use it
fbf5a39b 1238
535a8637
AC
1239 if Present (Associated_Storage_Pool (Ptr_Typ)) then
1240 Pool_Id := Associated_Storage_Pool (Ptr_Typ);
fbf5a39b 1241
535a8637 1242 -- Otherwise the default choice is the global storage pool
df3e68b1 1243
535a8637
AC
1244 else
1245 Pool_Id := RTE (RE_Global_Pool_Object);
1246 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
1247 end if;
deb8dacc 1248
535a8637
AC
1249 -- Generate:
1250 -- Set_Base_Pool (<Ptr_Typ>FM, Pool_Id'Unchecked_Access);
deb8dacc 1251
535a8637
AC
1252 Append_To (Actions,
1253 Make_Procedure_Call_Statement (Loc,
1254 Name =>
1255 New_Occurrence_Of (RTE (RE_Set_Base_Pool), Loc),
1256 Parameter_Associations => New_List (
1257 New_Occurrence_Of (Fin_Mas_Id, Loc),
1258 Make_Attribute_Reference (Loc,
1259 Prefix => New_Occurrence_Of (Pool_Id, Loc),
1260 Attribute_Name => Name_Unrestricted_Access))));
760804f3 1261
535a8637
AC
1262 -- Finalize_Address is not generated in CodePeer mode because the
1263 -- body contains address arithmetic. Skip this step.
760804f3 1264
535a8637
AC
1265 if CodePeer_Mode then
1266 null;
760804f3 1267
535a8637
AC
1268 -- Associate the Finalize_Address primitive of the designated type
1269 -- with the finalization master of the access type. The designated
1270 -- type must be forzen as Finalize_Address is generated when the
1271 -- freeze node is expanded.
760804f3 1272
535a8637
AC
1273 elsif Is_Frozen (Desig_Typ)
1274 and then Present (Finalize_Address (Desig_Typ))
760804f3 1275
535a8637
AC
1276 -- The finalization master of an anonymous access type may need
1277 -- to be inserted in a specific place in the tree. For instance:
760804f3 1278
535a8637 1279 -- type Comp_Typ;
760804f3 1280
535a8637 1281 -- <finalization master of "access Comp_Typ">
760804f3 1282
535a8637
AC
1283 -- type Rec_Typ is record
1284 -- Comp : access Comp_Typ;
1285 -- end record;
760804f3 1286
535a8637
AC
1287 -- <freeze node for Comp_Typ>
1288 -- <freeze node for Rec_Typ>
760804f3 1289
535a8637
AC
1290 -- Due to this oddity, the anonymous access type is stored for
1291 -- later processing (see below).
760804f3 1292
535a8637
AC
1293 and then Ekind (Ptr_Typ) /= E_Anonymous_Access_Type
1294 then
1295 -- Generate:
1296 -- Set_Finalize_Address
1297 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
760804f3 1298
535a8637
AC
1299 Append_To (Actions,
1300 Make_Set_Finalize_Address_Call
1301 (Loc => Loc,
1302 Ptr_Typ => Ptr_Typ));
760804f3 1303
535a8637
AC
1304 -- Otherwise the designated type is either anonymous access or a
1305 -- Taft-amendment type and has not been frozen. Store the access
1306 -- type for later processing (see Freeze_Type).
760804f3 1307
535a8637
AC
1308 else
1309 Add_Pending_Access_Type (Desig_Typ, Ptr_Typ);
deb8dacc 1310 end if;
df3e68b1 1311
32b794c8
AC
1312 -- A finalization master created for an access designating a type
1313 -- with private components is inserted before a context-dependent
1314 -- node.
df3e68b1 1315
32b794c8 1316 if For_Private then
df3e68b1 1317
760804f3
AC
1318 -- At this point both the scope of the context and the insertion
1319 -- mode must be known.
1320
1321 pragma Assert (Present (Context_Scope));
1322 pragma Assert (Present (Insertion_Node));
1323
1324 Push_Scope (Context_Scope);
df3e68b1
HK
1325
1326 -- Treat use clauses as declarations and insert directly in front
1327 -- of them.
1328
4a08c95c
AC
1329 if Nkind (Insertion_Node) in
1330 N_Use_Package_Clause | N_Use_Type_Clause
df3e68b1 1331 then
760804f3 1332 Insert_List_Before_And_Analyze (Insertion_Node, Actions);
fbf5a39b 1333 else
760804f3 1334 Insert_Actions (Insertion_Node, Actions);
fbf5a39b 1335 end if;
df3e68b1
HK
1336
1337 Pop_Scope;
1338
8434cfc7
AC
1339 -- The finalization master belongs to an access result type related
1340 -- to a build-in-place function call used to initialize a library
1341 -- level object. The master must be inserted in front of the access
1342 -- result type declaration denoted by Insertion_Node.
1343
1344 elsif For_Lib_Level then
1345 pragma Assert (Present (Insertion_Node));
1346 Insert_Actions (Insertion_Node, Actions);
1347
760804f3
AC
1348 -- Otherwise the finalization master and its initialization become a
1349 -- part of the freeze node.
df3e68b1
HK
1350
1351 else
760804f3 1352 Append_Freeze_Actions (Ptr_Typ, Actions);
fbf5a39b 1353 end if;
a1023434
JS
1354
1355 Analyze_List (Actions);
1356
1357 -- When the type the finalization master is being generated for was
1358 -- created to store a 'Old object, then mark it as such so its
1359 -- finalization can be delayed until after postconditions have been
1360 -- checked.
1361
1362 if Stores_Attribute_Old_Prefix (Ptr_Typ) then
1363 Set_Stores_Attribute_Old_Prefix (Fin_Mas_Id);
1364 end if;
df3e68b1 1365 end;
d3f70b35 1366 end Build_Finalization_Master;
fbf5a39b 1367
a968d80d
JS
1368 ---------------------
1369 -- Build_Finalizer --
1370 ---------------------
afe4375b 1371
a968d80d 1372 procedure Build_Finalizer
c0ffadd6
JS
1373 (N : Node_Id;
1374 Clean_Stmts : List_Id;
1375 Mark_Id : Entity_Id;
1376 Top_Decls : List_Id;
1377 Defer_Abort : Boolean;
a968d80d 1378 Fin_Id : out Entity_Id)
df3e68b1
HK
1379 is
1380 Acts_As_Clean : constant Boolean :=
1381 Present (Mark_Id)
1382 or else
1383 (Present (Clean_Stmts)
cfae2bed 1384 and then Is_Non_Empty_List (Clean_Stmts));
640ad9c2 1385
df3e68b1
HK
1386 For_Package_Body : constant Boolean := Nkind (N) = N_Package_Body;
1387 For_Package_Spec : constant Boolean := Nkind (N) = N_Package_Declaration;
1388 For_Package : constant Boolean :=
1389 For_Package_Body or else For_Package_Spec;
1390 Loc : constant Source_Ptr := Sloc (N);
1391
1392 -- NOTE: Local variable declarations are conservative and do not create
1393 -- structures right from the start. Entities and lists are created once
1394 -- it has been established that N has at least one controlled object.
1395
1396 Components_Built : Boolean := False;
1397 -- A flag used to avoid double initialization of entities and lists. If
1398 -- the flag is set then the following variables have been initialized:
df3e68b1 1399 -- Counter_Id
df3e68b1
HK
1400 -- Finalizer_Decls
1401 -- Finalizer_Stmts
1402 -- Jump_Alts
df3e68b1
HK
1403
1404 Counter_Id : Entity_Id := Empty;
16e764a7 1405 Counter_Val : Nat := 0;
df3e68b1
HK
1406 -- Name and value of the state counter
1407
1408 Decls : List_Id := No_List;
1409 -- Declarative region of N (if available). If N is a package declaration
1410 -- Decls denotes the visible declarations.
1411
36b8f95f
AC
1412 Finalizer_Data : Finalization_Exception_Data;
1413 -- Data for the exception
df3e68b1
HK
1414
1415 Finalizer_Decls : List_Id := No_List;
1416 -- Local variable declarations. This list holds the label declarations
1417 -- of all jump block alternatives as well as the declaration of the
7f37fff1 1418 -- local exception occurrence and the raised flag:
df3e68b1
HK
1419 -- E : Exception_Occurrence;
1420 -- Raised : Boolean := False;
1421 -- L<counter value> : label;
1422
1423 Finalizer_Insert_Nod : Node_Id := Empty;
1424 -- Insertion point for the finalizer body. Depending on the context
1425 -- (Nkind of N) and the individual grouping of controlled objects, this
1426 -- node may denote a package declaration or body, package instantiation,
1427 -- block statement or a counter update statement.
1428
1429 Finalizer_Stmts : List_Id := No_List;
1430 -- The statement list of the finalizer body. It contains the following:
1431 --
1432 -- Abort_Defer; -- Added if abort is allowed
1433 -- <call to Prev_At_End> -- Added if exists
1434 -- <cleanup statements> -- Added if Acts_As_Clean
1435 -- <jump block> -- Added if Has_Ctrl_Objs
1436 -- <finalization statements> -- Added if Has_Ctrl_Objs
1437 -- <stack release> -- Added if Mark_Id exists
1438 -- Abort_Undefer; -- Added if abort is allowed
1439
1440 Has_Ctrl_Objs : Boolean := False;
1441 -- A general flag which denotes whether N has at least one controlled
1442 -- object.
1443
26e7e1a0 1444 Has_Tagged_Types : Boolean := False;
0319cacc
AC
1445 -- A general flag which indicates whether N has at least one library-
1446 -- level tagged type declaration.
26e7e1a0 1447
df3e68b1
HK
1448 HSS : Node_Id := Empty;
1449 -- The sequence of statements of N (if available)
1450
1451 Jump_Alts : List_Id := No_List;
1452 -- Jump block alternatives. Depending on the value of the state counter,
d34cd274 1453 -- the control flow jumps to a sequence of finalization statements. This
df3e68b1
HK
1454 -- list contains the following:
1455 --
1456 -- when <counter value> =>
1457 -- goto L<counter value>;
1458
1459 Jump_Block_Insert_Nod : Node_Id := Empty;
1460 -- Specific point in the finalizer statements where the jump block is
1461 -- inserted.
1462
1463 Last_Top_Level_Ctrl_Construct : Node_Id := Empty;
1464 -- The last controlled construct encountered when processing the top
1465 -- level lists of N. This can be a nested package, an instantiation or
1466 -- an object declaration.
1467
1468 Prev_At_End : Entity_Id := Empty;
1469 -- The previous at end procedure of the handled statements block of N
1470
1471 Priv_Decls : List_Id := No_List;
1472 -- The private declarations of N if N is a package declaration
1473
df3e68b1
HK
1474 Spec_Id : Entity_Id := Empty;
1475 Spec_Decls : List_Id := Top_Decls;
1476 Stmts : List_Id := No_List;
1477
26e7e1a0
AC
1478 Tagged_Type_Stmts : List_Id := No_List;
1479 -- Contains calls to Ada.Tags.Unregister_Tag for all library-level
1480 -- tagged types found in N.
1481
df3e68b1
HK
1482 -----------------------
1483 -- Local subprograms --
1484 -----------------------
1485
1486 procedure Build_Components;
1487 -- Create all entites and initialize all lists used in the creation of
1488 -- the finalizer.
1489
1490 procedure Create_Finalizer;
1491 -- Create the spec and body of the finalizer and insert them in the
1492 -- proper place in the tree depending on the context.
1493
213c9dc7
AC
1494 function New_Finalizer_Name
1495 (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id;
1496 -- Create a fully qualified name of a package spec or body finalizer.
1497 -- The generated name is of the form: xx__yy__finalize_[spec|body].
1498
df3e68b1
HK
1499 procedure Process_Declarations
1500 (Decls : List_Id;
1501 Preprocess : Boolean := False;
1502 Top_Level : Boolean := False);
1503 -- Inspect a list of declarations or statements which may contain
1504 -- objects that need finalization. When flag Preprocess is set, the
1505 -- routine will simply count the total number of controlled objects in
213c9dc7
AC
1506 -- Decls and set Counter_Val accordingly. Top_Level is only relevant
1507 -- when Preprocess is set and if True, the processing is performed for
f46faa08 1508 -- objects in nested package declarations or instances.
df3e68b1
HK
1509
1510 procedure Process_Object_Declaration
1511 (Decl : Node_Id;
1512 Has_No_Init : Boolean := False;
1513 Is_Protected : Boolean := False);
1514 -- Generate all the machinery associated with the finalization of a
1515 -- single object. Flag Has_No_Init is used to denote certain contexts
1516 -- where Decl does not have initialization call(s). Flag Is_Protected
1517 -- is set when Decl denotes a simple protected object.
1518
26e7e1a0
AC
1519 procedure Process_Tagged_Type_Declaration (Decl : Node_Id);
1520 -- Generate all the code necessary to unregister the external tag of a
1521 -- tagged type.
1522
df3e68b1
HK
1523 ----------------------
1524 -- Build_Components --
1525 ----------------------
1526
1527 procedure Build_Components is
1528 Counter_Decl : Node_Id;
1529 Counter_Typ : Entity_Id;
1530 Counter_Typ_Decl : Node_Id;
afe4375b 1531
df3e68b1
HK
1532 begin
1533 pragma Assert (Present (Decls));
70482933 1534
df3e68b1
HK
1535 -- This routine might be invoked several times when dealing with
1536 -- constructs that have two lists (either two declarative regions
1537 -- or declarations and statements). Avoid double initialization.
70482933 1538
df3e68b1
HK
1539 if Components_Built then
1540 return;
1541 end if;
70482933 1542
df3e68b1 1543 Components_Built := True;
70482933 1544
df3e68b1 1545 if Has_Ctrl_Objs then
70482933 1546
df3e68b1
HK
1547 -- Create entities for the counter, its type, the local exception
1548 -- and the raised flag.
70482933 1549
df3e68b1
HK
1550 Counter_Id := Make_Temporary (Loc, 'C');
1551 Counter_Typ := Make_Temporary (Loc, 'T');
70482933 1552
36b8f95f
AC
1553 Finalizer_Decls := New_List;
1554
2d1debf8
AC
1555 Build_Object_Declarations
1556 (Finalizer_Data, Finalizer_Decls, Loc, For_Package);
70482933 1557
df3e68b1
HK
1558 -- Since the total number of controlled objects is always known,
1559 -- build a subtype of Natural with precise bounds. This allows
1560 -- the backend to optimize the case statement. Generate:
1561 --
1562 -- subtype Tnn is Natural range 0 .. Counter_Val;
1563
1564 Counter_Typ_Decl :=
1565 Make_Subtype_Declaration (Loc,
1566 Defining_Identifier => Counter_Typ,
cfae2bed 1567 Subtype_Indication =>
df3e68b1 1568 Make_Subtype_Indication (Loc,
e4494292 1569 Subtype_Mark => New_Occurrence_Of (Standard_Natural, Loc),
cfae2bed 1570 Constraint =>
df3e68b1
HK
1571 Make_Range_Constraint (Loc,
1572 Range_Expression =>
1573 Make_Range (Loc,
cfae2bed 1574 Low_Bound =>
df3e68b1
HK
1575 Make_Integer_Literal (Loc, Uint_0),
1576 High_Bound =>
1577 Make_Integer_Literal (Loc, Counter_Val)))));
1578
1579 -- Generate the declaration of the counter itself:
1580 --
1581 -- Counter : Integer := 0;
1582
1583 Counter_Decl :=
1584 Make_Object_Declaration (Loc,
1585 Defining_Identifier => Counter_Id,
e4494292 1586 Object_Definition => New_Occurrence_Of (Counter_Typ, Loc),
cfae2bed 1587 Expression => Make_Integer_Literal (Loc, 0));
df3e68b1
HK
1588
1589 -- Set the type of the counter explicitly to prevent errors when
1590 -- examining object declarations later on.
1591
1592 Set_Etype (Counter_Id, Counter_Typ);
1593
bbf14e13
AC
1594 if Debug_Generated_Code then
1595 Set_Debug_Info_Needed (Counter_Id);
1596 end if;
1597
df3e68b1
HK
1598 -- The counter and its type are inserted before the source
1599 -- declarations of N.
1600
1601 Prepend_To (Decls, Counter_Decl);
1602 Prepend_To (Decls, Counter_Typ_Decl);
1603
75b87c16 1604 -- The counter and its associated type must be manually analyzed
df3e68b1
HK
1605 -- since N has already been analyzed. Use the scope of the spec
1606 -- when inserting in a package.
1607
1608 if For_Package then
1609 Push_Scope (Spec_Id);
1610 Analyze (Counter_Typ_Decl);
1611 Analyze (Counter_Decl);
1612 Pop_Scope;
70482933 1613
df3e68b1
HK
1614 else
1615 Analyze (Counter_Typ_Decl);
1616 Analyze (Counter_Decl);
70482933 1617 end if;
df3e68b1 1618
df3e68b1 1619 Jump_Alts := New_List;
70482933
RK
1620 end if;
1621
40c21e91
PMR
1622 -- If the context requires additional cleanup, the finalization
1623 -- machinery is added after the cleanup code.
70482933 1624
df3e68b1
HK
1625 if Acts_As_Clean then
1626 Finalizer_Stmts := Clean_Stmts;
1627 Jump_Block_Insert_Nod := Last (Finalizer_Stmts);
1628 else
1629 Finalizer_Stmts := New_List;
1630 end if;
26e7e1a0
AC
1631
1632 if Has_Tagged_Types then
1633 Tagged_Type_Stmts := New_List;
1634 end if;
df3e68b1
HK
1635 end Build_Components;
1636
1637 ----------------------
1638 -- Create_Finalizer --
1639 ----------------------
1640
1641 procedure Create_Finalizer is
7bf911b5
HK
1642 Body_Id : Entity_Id;
1643 Fin_Body : Node_Id;
1644 Fin_Spec : Node_Id;
1645 Jump_Block : Node_Id;
1646 Label : Node_Id;
1647 Label_Id : Entity_Id;
1648
df3e68b1
HK
1649 begin
1650 -- Step 1: Creation of the finalizer name
70482933 1651
df3e68b1 1652 -- Packages must use a distinct name for their finalizers since the
cfae2bed
AC
1653 -- binder will have to generate calls to them by name. The name is
1654 -- of the following form:
70482933 1655
cfae2bed 1656 -- xx__yy__finalize_[spec|body]
dbe13a37 1657
cfae2bed 1658 if For_Package then
213c9dc7
AC
1659 Fin_Id := Make_Defining_Identifier
1660 (Loc, New_Finalizer_Name (Spec_Id, For_Package_Spec));
cfae2bed
AC
1661 Set_Has_Qualified_Name (Fin_Id);
1662 Set_Has_Fully_Qualified_Name (Fin_Id);
70482933 1663
df3e68b1 1664 -- The default name is _finalizer
70482933 1665
df3e68b1 1666 else
a1023434
JS
1667 -- Generation of a finalization procedure exclusively for 'Old
1668 -- interally generated constants requires different name since
1669 -- there will need to be multiple finalization routines in the
1670 -- same scope. See Build_Finalizer for details.
1671
a968d80d
JS
1672 Fin_Id :=
1673 Make_Defining_Identifier (Loc,
1674 Chars => New_External_Name (Name_uFinalizer));
31af8899
AC
1675
1676 -- The visibility semantics of AT_END handlers force a strange
1677 -- separation of spec and body for stack-related finalizers:
1678
1679 -- declare : Enclosing_Scope
1680 -- procedure _finalizer;
1681 -- begin
1682 -- <controlled objects>
1683 -- procedure _finalizer is
1684 -- ...
1685 -- at end
1686 -- _finalizer;
1687 -- end;
1688
1689 -- Both spec and body are within the same construct and scope, but
1690 -- the body is part of the handled sequence of statements. This
1691 -- placement confuses the elaboration mechanism on targets where
1692 -- AT_END handlers are expanded into "when all others" handlers:
1693
1694 -- exception
1695 -- when all others =>
1696 -- _finalizer; -- appears to require elab checks
1697 -- at end
1698 -- _finalizer;
1699 -- end;
1700
1701 -- Since the compiler guarantees that the body of a _finalizer is
1702 -- always inserted in the same construct where the AT_END handler
1703 -- resides, there is no need for elaboration checks.
1704
1705 Set_Kill_Elaboration_Checks (Fin_Id);
7d9880c9
AC
1706
1707 -- Inlining the finalizer produces a substantial speedup at -O2.
1708 -- It is inlined by default at -O3. Either way, it is called
1709 -- exactly twice (once on the normal path, and once for
1710 -- exceptions/abort), so this won't bloat the code too much.
1711
bbf14e13
AC
1712 Set_Is_Inlined (Fin_Id);
1713 end if;
1714
1715 if Debug_Generated_Code then
1716 Set_Debug_Info_Needed (Fin_Id);
df3e68b1 1717 end if;
70482933 1718
cfae2bed 1719 -- Step 2: Creation of the finalizer specification
df3e68b1
HK
1720
1721 -- Generate:
1722 -- procedure Fin_Id;
1723
cfae2bed
AC
1724 Fin_Spec :=
1725 Make_Subprogram_Declaration (Loc,
1726 Specification =>
1727 Make_Procedure_Specification (Loc,
1728 Defining_Unit_Name => Fin_Id));
70482933 1729
213c9dc7
AC
1730 if For_Package then
1731 Set_Is_Exported (Fin_Id);
1732 Set_Interface_Name (Fin_Id,
1733 Make_String_Literal (Loc,
1734 Strval => Get_Name_String (Chars (Fin_Id))));
1735 end if;
1736
df3e68b1 1737 -- Step 3: Creation of the finalizer body
70482933 1738
213c9dc7
AC
1739 -- Has_Ctrl_Objs might be set because of a generic package body having
1740 -- controlled objects. In this case, Jump_Alts may be empty and no
1741 -- case nor goto statements are needed.
70482933 1742
213c9dc7
AC
1743 if Has_Ctrl_Objs
1744 and then not Is_Empty_List (Jump_Alts)
1745 then
df3e68b1 1746 -- Add L0, the default destination to the jump block
70482933 1747
cfae2bed 1748 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
df3e68b1
HK
1749 Set_Entity (Label_Id,
1750 Make_Defining_Identifier (Loc, Chars (Label_Id)));
1751 Label := Make_Label (Loc, Label_Id);
a9f4e3d2 1752
df3e68b1
HK
1753 -- Generate:
1754 -- L0 : label;
70482933 1755
df3e68b1
HK
1756 Prepend_To (Finalizer_Decls,
1757 Make_Implicit_Label_Declaration (Loc,
1758 Defining_Identifier => Entity (Label_Id),
cfae2bed 1759 Label_Construct => Label));
70482933 1760
df3e68b1
HK
1761 -- Generate:
1762 -- when others =>
1763 -- goto L0;
1764
1765 Append_To (Jump_Alts,
1766 Make_Case_Statement_Alternative (Loc,
cfae2bed
AC
1767 Discrete_Choices => New_List (Make_Others_Choice (Loc)),
1768 Statements => New_List (
df3e68b1 1769 Make_Goto_Statement (Loc,
e4494292 1770 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
df3e68b1
HK
1771
1772 -- Generate:
1773 -- <<L0>>
1774
1775 Append_To (Finalizer_Stmts, Label);
1776
df3e68b1
HK
1777 -- Create the jump block which controls the finalization flow
1778 -- depending on the value of the state counter.
1779
1780 Jump_Block :=
1781 Make_Case_Statement (Loc,
cfae2bed 1782 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
df3e68b1
HK
1783 Alternatives => Jump_Alts);
1784
36295779 1785 if Acts_As_Clean and then Present (Jump_Block_Insert_Nod) then
df3e68b1
HK
1786 Insert_After (Jump_Block_Insert_Nod, Jump_Block);
1787 else
1788 Prepend_To (Finalizer_Stmts, Jump_Block);
1789 end if;
70482933
RK
1790 end if;
1791
26e7e1a0
AC
1792 -- Add the library-level tagged type unregistration machinery before
1793 -- the jump block circuitry. This ensures that external tags will be
1794 -- removed even if a finalization exception occurs at some point.
1795
1796 if Has_Tagged_Types then
1797 Prepend_List_To (Finalizer_Stmts, Tagged_Type_Stmts);
1798 end if;
1799
df3e68b1
HK
1800 -- Add a call to the previous At_End handler if it exists. The call
1801 -- must always precede the jump block.
70482933 1802
df3e68b1
HK
1803 if Present (Prev_At_End) then
1804 Prepend_To (Finalizer_Stmts,
1805 Make_Procedure_Call_Statement (Loc, Prev_At_End));
1806
1807 -- Clear the At_End handler since we have already generated the
1808 -- proper replacement call for it.
1809
1810 Set_At_End_Proc (HSS, Empty);
70482933 1811 end if;
70482933 1812
9a975bfc 1813 -- Release the secondary stack
70482933 1814
df3e68b1 1815 if Present (Mark_Id) then
9a975bfc 1816 declare
b6784d90
HK
1817 Release : Node_Id := Build_SS_Release_Call (Loc, Mark_Id);
1818
9a975bfc 1819 begin
b6784d90
HK
1820 -- If the context is a build-in-place function, the secondary
1821 -- stack must be released, unless the build-in-place function
1822 -- itself is returning on the secondary stack. Generate:
1823 --
1824 -- if BIP_Alloc_Form /= Secondary_Stack then
1825 -- SS_Release (Mark_Id);
1826 -- end if;
1827 --
1828 -- Note that if the function returns on the secondary stack,
1829 -- then the responsibility of reclaiming the space is always
1830 -- left to the caller (recursively if needed).
9a975bfc
BD
1831
1832 if Nkind (N) = N_Subprogram_Body then
1833 declare
1834 Spec_Id : constant Entity_Id :=
1835 Unique_Defining_Entity (N);
1836 BIP_SS : constant Boolean :=
1837 Is_Build_In_Place_Function (Spec_Id)
1838 and then Needs_BIP_Alloc_Form (Spec_Id);
1839 begin
1840 if BIP_SS then
1841 Release :=
1842 Make_If_Statement (Loc,
b6784d90 1843 Condition =>
9a975bfc
BD
1844 Make_Op_Ne (Loc,
1845 Left_Opnd =>
1846 New_Occurrence_Of
1847 (Build_In_Place_Formal
1848 (Spec_Id, BIP_Alloc_Form), Loc),
1849 Right_Opnd =>
1850 Make_Integer_Literal (Loc,
b6784d90
HK
1851 UI_From_Int
1852 (BIP_Allocation_Form'Pos
1853 (Secondary_Stack)))),
9a975bfc
BD
1854
1855 Then_Statements => New_List (Release));
1856 end if;
1857 end;
1858 end if;
1859
1860 Append_To (Finalizer_Stmts, Release);
1861 end;
df3e68b1 1862 end if;
dbe13a37 1863
df3e68b1 1864 -- Protect the statements with abort defer/undefer. This is only when
40c21e91 1865 -- aborts are allowed and the cleanup statements require deferral or
7bf911b5
HK
1866 -- there are controlled objects to be finalized. Note that the abort
1867 -- defer/undefer pair does not require an extra block because each
1868 -- finalization exception is caught in its corresponding finalization
1869 -- block. As a result, the call to Abort_Defer always takes place.
70482933 1870
36295779 1871 if Abort_Allowed and then (Defer_Abort or Has_Ctrl_Objs) then
df3e68b1 1872 Prepend_To (Finalizer_Stmts,
7bf911b5 1873 Build_Runtime_Call (Loc, RE_Abort_Defer));
dcfa065d 1874
df3e68b1 1875 Append_To (Finalizer_Stmts,
7bf911b5 1876 Build_Runtime_Call (Loc, RE_Abort_Undefer));
df3e68b1 1877 end if;
70482933 1878
3235dc87
AC
1879 -- The local exception does not need to be reraised for library-level
1880 -- finalizers. Note that this action must be carried out after object
40c21e91 1881 -- cleanup, secondary stack release, and abort undeferral. Generate:
3235dc87
AC
1882
1883 -- if Raised and then not Abort then
1884 -- Raise_From_Controlled_Operation (E);
1885 -- end if;
1886
36295779 1887 if Has_Ctrl_Objs and Exceptions_OK and not For_Package then
3235dc87
AC
1888 Append_To (Finalizer_Stmts,
1889 Build_Raise_Statement (Finalizer_Data));
1890 end if;
1891
df3e68b1
HK
1892 -- Generate:
1893 -- procedure Fin_Id is
14848f57 1894 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
1895 -- <or>
1896 -- Abort : constant Boolean := False; -- no abort
1897
df3e68b1
HK
1898 -- E : Exception_Occurrence; -- All added if flag
1899 -- Raised : Boolean := False; -- Has_Ctrl_Objs is set
1900 -- L0 : label;
1901 -- ...
1902 -- Lnn : label;
f9ad6b62 1903
df3e68b1
HK
1904 -- begin
1905 -- Abort_Defer; -- Added if abort is allowed
1906 -- <call to Prev_At_End> -- Added if exists
1907 -- <cleanup statements> -- Added if Acts_As_Clean
1908 -- <jump block> -- Added if Has_Ctrl_Objs
1909 -- <finalization statements> -- Added if Has_Ctrl_Objs
1910 -- <stack release> -- Added if Mark_Id exists
1911 -- Abort_Undefer; -- Added if abort is allowed
3235dc87 1912 -- <exception propagation> -- Added if Has_Ctrl_Objs
df3e68b1
HK
1913 -- end Fin_Id;
1914
df3e68b1 1915 -- Create the body of the finalizer
70482933 1916
cfae2bed
AC
1917 Body_Id := Make_Defining_Identifier (Loc, Chars (Fin_Id));
1918
bbf14e13
AC
1919 if Debug_Generated_Code then
1920 Set_Debug_Info_Needed (Body_Id);
1921 end if;
1922
cfae2bed
AC
1923 if For_Package then
1924 Set_Has_Qualified_Name (Body_Id);
1925 Set_Has_Fully_Qualified_Name (Body_Id);
1926 end if;
1927
df3e68b1
HK
1928 Fin_Body :=
1929 Make_Subprogram_Body (Loc,
886b5a18 1930 Specification =>
df3e68b1 1931 Make_Procedure_Specification (Loc,
cfae2bed 1932 Defining_Unit_Name => Body_Id),
886b5a18 1933 Declarations => Finalizer_Decls,
df3e68b1 1934 Handled_Statement_Sequence =>
7bf911b5
HK
1935 Make_Handled_Sequence_Of_Statements (Loc,
1936 Statements => Finalizer_Stmts));
70482933 1937
df3e68b1 1938 -- Step 4: Spec and body insertion, analysis
70482933 1939
df3e68b1 1940 if For_Package then
70482933 1941
df3e68b1
HK
1942 -- If the package spec has private declarations, the finalizer
1943 -- body must be added to the end of the list in order to have
b37d5bc6 1944 -- visibility of all private controlled objects.
70482933 1945
df3e68b1 1946 if For_Package_Spec then
df3e68b1 1947 if Present (Priv_Decls) then
b37d5bc6 1948 Append_To (Priv_Decls, Fin_Spec);
df3e68b1
HK
1949 Append_To (Priv_Decls, Fin_Body);
1950 else
b37d5bc6 1951 Append_To (Decls, Fin_Spec);
df3e68b1
HK
1952 Append_To (Decls, Fin_Body);
1953 end if;
70482933 1954
b37d5bc6
AC
1955 -- For package bodies, both the finalizer spec and body are
1956 -- inserted at the end of the package declarations.
70482933 1957
df3e68b1 1958 else
b37d5bc6
AC
1959 Append_To (Decls, Fin_Spec);
1960 Append_To (Decls, Fin_Body);
df3e68b1 1961 end if;
70482933 1962
df3e68b1 1963 -- Push the name of the package
70482933 1964
df3e68b1 1965 Push_Scope (Spec_Id);
cfae2bed 1966 Analyze (Fin_Spec);
df3e68b1
HK
1967 Analyze (Fin_Body);
1968 Pop_Scope;
70482933 1969
df3e68b1 1970 -- Non-package case
70482933 1971
df3e68b1
HK
1972 else
1973 -- Create the spec for the finalizer. The At_End handler must be
1974 -- able to call the body which resides in a nested structure.
1975
1976 -- Generate:
1977 -- declare
1978 -- procedure Fin_Id; -- Spec
1979 -- begin
1980 -- <objects and possibly statements>
1981 -- procedure Fin_Id is ... -- Body
1982 -- <statements>
1983 -- at end
1984 -- Fin_Id; -- At_End handler
1985 -- end;
1986
df3e68b1
HK
1987 pragma Assert (Present (Spec_Decls));
1988
a1023434
JS
1989 -- It maybe possible that we are finalizing 'Old objects which
1990 -- exist in the spec declarations. When this is the case the
1991 -- Finalizer_Insert_Node will come before the end of the
1992 -- Spec_Decls. So, to mitigate this, we insert the finalizer spec
1993 -- earlier at the Finalizer_Insert_Nod instead of appending to the
1994 -- end of Spec_Decls to prevent its body appearing before its
1995 -- corresponding spec.
1996
1997 if Present (Finalizer_Insert_Nod)
1998 and then List_Containing (Finalizer_Insert_Nod) = Spec_Decls
1999 then
2000 Insert_After_And_Analyze (Finalizer_Insert_Nod, Fin_Spec);
2001 Finalizer_Insert_Nod := Fin_Spec;
2002
2003 -- Otherwise, Finalizer_Insert_Nod is not in Spec_Decls
2004
2005 else
2006 Append_To (Spec_Decls, Fin_Spec);
2007 Analyze (Fin_Spec);
2008 end if;
df3e68b1 2009
40c21e91 2010 -- When the finalizer acts solely as a cleanup routine, the body
df3e68b1
HK
2011 -- is inserted right after the spec.
2012
41c79d60 2013 if Acts_As_Clean and not Has_Ctrl_Objs then
df3e68b1
HK
2014 Insert_After (Fin_Spec, Fin_Body);
2015
2016 -- In all other cases the body is inserted after either:
2017 --
2018 -- 1) The counter update statement of the last controlled object
2019 -- 2) The last top level nested controlled package
2020 -- 3) The last top level controlled instantiation
70482933 2021
df3e68b1
HK
2022 else
2023 -- Manually freeze the spec. This is somewhat of a hack because
2024 -- a subprogram is frozen when its body is seen and the freeze
2025 -- node appears right before the body. However, in this case,
2026 -- the spec must be frozen earlier since the At_End handler
2027 -- must be able to call it.
2028 --
2029 -- declare
2030 -- procedure Fin_Id; -- Spec
2031 -- [Fin_Id] -- Freeze node
2032 -- begin
2033 -- ...
2034 -- at end
2035 -- Fin_Id; -- At_End handler
2036 -- end;
2037
2038 Ensure_Freeze_Node (Fin_Id);
2039 Insert_After (Fin_Spec, Freeze_Node (Fin_Id));
2040 Set_Is_Frozen (Fin_Id);
2041
2042 -- In the case where the last construct to contain a controlled
1cdfa9be
AC
2043 -- object is either a nested package, an instantiation or a
2044 -- freeze node, the body must be inserted directly after the
6d16658d
BD
2045 -- construct, except if the insertion point is already placed
2046 -- after the construct, typically in the statement list.
df3e68b1 2047
4a08c95c
AC
2048 if Nkind (Last_Top_Level_Ctrl_Construct) in
2049 N_Freeze_Entity | N_Package_Declaration | N_Package_Body
6d16658d
BD
2050 and then not
2051 (List_Containing (Last_Top_Level_Ctrl_Construct) = Spec_Decls
2052 and then Present (Stmts)
2053 and then List_Containing (Finalizer_Insert_Nod) = Stmts)
df3e68b1
HK
2054 then
2055 Finalizer_Insert_Nod := Last_Top_Level_Ctrl_Construct;
2056 end if;
70482933 2057
df3e68b1
HK
2058 Insert_After (Finalizer_Insert_Nod, Fin_Body);
2059 end if;
2060
b3db0949 2061 Analyze (Fin_Body, Suppress => All_Checks);
df3e68b1 2062 end if;
39c20502
YM
2063
2064 -- Never consider that the finalizer procedure is enabled Ghost, even
2065 -- when the corresponding unit is Ghost, as this would lead to an
2066 -- an external name with a ___ghost_ prefix that the binder cannot
2067 -- generate, as it has no knowledge of the Ghost status of units.
2068
2069 Set_Is_Checked_Ghost_Entity (Fin_Id, False);
df3e68b1
HK
2070 end Create_Finalizer;
2071
213c9dc7
AC
2072 ------------------------
2073 -- New_Finalizer_Name --
2074 ------------------------
2075
2076 function New_Finalizer_Name
2077 (Spec_Id : Node_Id; For_Spec : Boolean) return Name_Id
2078 is
2079 procedure New_Finalizer_Name (Id : Entity_Id);
2080 -- Place "__<name-of-Id>" in the name buffer. If the identifier
2081 -- has a non-standard scope, process the scope first.
2082
2083 ------------------------
2084 -- New_Finalizer_Name --
2085 ------------------------
2086
2087 procedure New_Finalizer_Name (Id : Entity_Id) is
2088 begin
2089 if Scope (Id) = Standard_Standard then
2090 Get_Name_String (Chars (Id));
2091
2092 else
2093 New_Finalizer_Name (Scope (Id));
2094 Add_Str_To_Name_Buffer ("__");
2095 Get_Name_String_And_Append (Chars (Id));
2096 end if;
2097 end New_Finalizer_Name;
2098
2099 -- Start of processing for New_Finalizer_Name
2100
2101 begin
2102 -- Create the fully qualified name of the enclosing scope
2103
2104 New_Finalizer_Name (Spec_Id);
2105
2106 -- Generate:
2107 -- __finalize_[spec|body]
2108
2109 Add_Str_To_Name_Buffer ("__finalize_");
2110
2111 if For_Spec then
2112 Add_Str_To_Name_Buffer ("spec");
2113 else
2114 Add_Str_To_Name_Buffer ("body");
2115 end if;
2116
2117 return Name_Find;
2118 end New_Finalizer_Name;
2119
df3e68b1
HK
2120 --------------------------
2121 -- Process_Declarations --
2122 --------------------------
2123
2124 procedure Process_Declarations
2125 (Decls : List_Id;
2126 Preprocess : Boolean := False;
2127 Top_Level : Boolean := False)
2128 is
2129 Decl : Node_Id;
2130 Expr : Node_Id;
2131 Obj_Id : Entity_Id;
2132 Obj_Typ : Entity_Id;
2133 Pack_Id : Entity_Id;
2134 Spec : Node_Id;
2135 Typ : Entity_Id;
2136
16e764a7 2137 Old_Counter_Val : Nat;
df3e68b1
HK
2138 -- This variable is used to determine whether a nested package or
2139 -- instance contains at least one controlled object.
2140
2141 procedure Processing_Actions
2142 (Has_No_Init : Boolean := False;
2143 Is_Protected : Boolean := False);
2144 -- Depending on the mode of operation of Process_Declarations, either
2145 -- increment the controlled object counter, set the controlled object
2146 -- flag and store the last top level construct or process the current
2147 -- declaration. Flag Has_No_Init is used to propagate scenarios where
2148 -- the current declaration may not have initialization proc(s). Flag
2149 -- Is_Protected should be set when the current declaration denotes a
2150 -- simple protected object.
2151
2152 ------------------------
2153 -- Processing_Actions --
2154 ------------------------
2155
2156 procedure Processing_Actions
2157 (Has_No_Init : Boolean := False;
2158 Is_Protected : Boolean := False)
2159 is
2160 begin
26e7e1a0 2161 -- Library-level tagged type
df3e68b1 2162
26e7e1a0
AC
2163 if Nkind (Decl) = N_Full_Type_Declaration then
2164 if Preprocess then
2165 Has_Tagged_Types := True;
2166
36295779 2167 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
26e7e1a0
AC
2168 Last_Top_Level_Ctrl_Construct := Decl;
2169 end if;
0319cacc 2170
0590ed72
BD
2171 -- Unregister tagged type, unless No_Tagged_Type_Registration
2172 -- is active.
2173
2174 elsif not Restriction_Active (No_Tagged_Type_Registration) then
26e7e1a0 2175 Process_Tagged_Type_Declaration (Decl);
df3e68b1 2176 end if;
26e7e1a0
AC
2177
2178 -- Controlled object declaration
2179
df3e68b1 2180 else
26e7e1a0
AC
2181 if Preprocess then
2182 Counter_Val := Counter_Val + 1;
2183 Has_Ctrl_Objs := True;
2184
36295779 2185 if Top_Level and then No (Last_Top_Level_Ctrl_Construct) then
26e7e1a0
AC
2186 Last_Top_Level_Ctrl_Construct := Decl;
2187 end if;
0319cacc 2188
26e7e1a0
AC
2189 else
2190 Process_Object_Declaration (Decl, Has_No_Init, Is_Protected);
2191 end if;
df3e68b1
HK
2192 end if;
2193 end Processing_Actions;
2194
2195 -- Start of processing for Process_Declarations
2196
2197 begin
9d4a5ddc 2198 if Is_Empty_List (Decls) then
df3e68b1
HK
2199 return;
2200 end if;
2201
2202 -- Process all declarations in reverse order
2203
2204 Decl := Last_Non_Pragma (Decls);
2205 while Present (Decl) loop
26e7e1a0
AC
2206 -- Library-level tagged types
2207
a968d80d 2208 if Nkind (Decl) = N_Full_Type_Declaration then
26e7e1a0
AC
2209 Typ := Defining_Identifier (Decl);
2210
8636f52f
HK
2211 -- Ignored Ghost types do not need any cleanup actions because
2212 -- they will not appear in the final tree.
2213
2214 if Is_Ignored_Ghost_Entity (Typ) then
2215 null;
2216
2217 elsif Is_Tagged_Type (Typ)
26e7e1a0
AC
2218 and then Is_Library_Level_Entity (Typ)
2219 and then Convention (Typ) = Convention_Ada
2220 and then Present (Access_Disp_Table (Typ))
26e7e1a0 2221 and then not Is_Abstract_Type (Typ)
8636f52f 2222 and then not No_Run_Time_Mode
0590ed72
BD
2223 and then not Restriction_Active (No_Tagged_Type_Registration)
2224 and then RTE_Available (RE_Register_Tag)
26e7e1a0
AC
2225 then
2226 Processing_Actions;
2227 end if;
2228
df3e68b1
HK
2229 -- Regular object declarations
2230
26e7e1a0 2231 elsif Nkind (Decl) = N_Object_Declaration then
df3e68b1
HK
2232 Obj_Id := Defining_Identifier (Decl);
2233 Obj_Typ := Base_Type (Etype (Obj_Id));
2234 Expr := Expression (Decl);
2235
2236 -- Bypass any form of processing for objects which have their
2237 -- finalization disabled. This applies only to objects at the
2238 -- library level.
2239
36295779 2240 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
df3e68b1
HK
2241 null;
2242
937e9676
AC
2243 -- Finalization of transient objects are treated separately in
2244 -- order to handle sensitive cases. These include:
df3e68b1 2245
937e9676
AC
2246 -- * Aggregate expansion
2247 -- * If, case, and expression with actions expansion
2248 -- * Transient scopes
2249
2250 -- If one of those contexts has marked the transient object as
2251 -- ignored, do not generate finalization actions for it.
2252
2253 elsif Is_Finalized_Transient (Obj_Id)
2254 or else Is_Ignored_Transient (Obj_Id)
2255 then
df3e68b1
HK
2256 null;
2257
8636f52f
HK
2258 -- Ignored Ghost objects do not need any cleanup actions
2259 -- because they will not appear in the final tree.
2260
2261 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2262 null;
2263
df3e68b1 2264 -- The object is of the form:
3386e3ae 2265 -- Obj : [constant] Typ [:= Expr];
886b5a18 2266
3386e3ae
AC
2267 -- Do not process tag-to-class-wide conversions because they do
2268 -- not yield an object. Do not process the incomplete view of a
2269 -- deferred constant. Note that an object initialized by means
2270 -- of a build-in-place function call may appear as a deferred
2271 -- constant after expansion activities. These kinds of objects
2272 -- must be finalized.
df3e68b1
HK
2273
2274 elsif not Is_Imported (Obj_Id)
2275 and then Needs_Finalization (Obj_Typ)
aab08130 2276 and then not Is_Tag_To_Class_Wide_Conversion (Obj_Id)
3386e3ae
AC
2277 and then not (Ekind (Obj_Id) = E_Constant
2278 and then not Has_Completion (Obj_Id)
2279 and then No (BIP_Initialization_Call (Obj_Id)))
df3e68b1
HK
2280 then
2281 Processing_Actions;
2282
2283 -- The object is of the form:
2284 -- Obj : Access_Typ := Non_BIP_Function_Call'reference;
886b5a18 2285
df3e68b1 2286 -- Obj : Access_Typ :=
cdc96e3e 2287 -- BIP_Function_Call (BIPalloc => 2, ...)'reference;
df3e68b1
HK
2288
2289 elsif Is_Access_Type (Obj_Typ)
2290 and then Needs_Finalization
2291 (Available_View (Designated_Type (Obj_Typ)))
2292 and then Present (Expr)
2293 and then
cdc96e3e 2294 (Is_Secondary_Stack_BIP_Func_Call (Expr)
57a3fca9
AC
2295 or else
2296 (Is_Non_BIP_Func_Call (Expr)
2297 and then not Is_Related_To_Func_Return (Obj_Id)))
df3e68b1
HK
2298 then
2299 Processing_Actions (Has_No_Init => True);
2300
937e9676
AC
2301 -- Processing for "hook" objects generated for transient
2302 -- objects declared inside an Expression_With_Actions.
2d395256 2303
35a1c212 2304 elsif Is_Access_Type (Obj_Typ)
3cebd1c0
AC
2305 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2306 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
41c79d60 2307 N_Object_Declaration
3cebd1c0
AC
2308 then
2309 Processing_Actions (Has_No_Init => True);
2310
9b16cb57
RD
2311 -- Process intermediate results of an if expression with one
2312 -- of the alternatives using a controlled function call.
3cebd1c0
AC
2313
2314 elsif Is_Access_Type (Obj_Typ)
2315 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
2316 and then Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
2a290fec 2317 N_Defining_Identifier
3cebd1c0
AC
2318 and then Present (Expr)
2319 and then Nkind (Expr) = N_Null
35a1c212
AC
2320 then
2321 Processing_Actions (Has_No_Init => True);
2322
df3e68b1
HK
2323 -- Simple protected objects which use type System.Tasking.
2324 -- Protected_Objects.Protection to manage their locks should
2325 -- be treated as controlled since they require manual cleanup.
2326 -- The only exception is illustrated in the following example:
2327
2328 -- package Pkg is
2329 -- type Ctrl is new Controlled ...
2330 -- procedure Finalize (Obj : in out Ctrl);
2331 -- Lib_Obj : Ctrl;
2332 -- end Pkg;
2333
2334 -- package body Pkg is
2335 -- protected Prot is
2336 -- procedure Do_Something (Obj : in out Ctrl);
2337 -- end Prot;
886b5a18 2338
df3e68b1
HK
2339 -- protected body Prot is
2340 -- procedure Do_Something (Obj : in out Ctrl) is ...
2341 -- end Prot;
886b5a18 2342
df3e68b1
HK
2343 -- procedure Finalize (Obj : in out Ctrl) is
2344 -- begin
2345 -- Prot.Do_Something (Obj);
2346 -- end Finalize;
2347 -- end Pkg;
2348
2349 -- Since for the most part entities in package bodies depend on
2350 -- those in package specs, Prot's lock should be cleaned up
2351 -- first. The subsequent cleanup of the spec finalizes Lib_Obj.
2352 -- This act however attempts to invoke Do_Something and fails
2353 -- because the lock has disappeared.
2354
2355 elsif Ekind (Obj_Id) = E_Variable
2356 and then not In_Library_Level_Package_Body (Obj_Id)
41c79d60
AC
2357 and then (Is_Simple_Protected_Type (Obj_Typ)
2358 or else Has_Simple_Protected_Object (Obj_Typ))
df3e68b1
HK
2359 then
2360 Processing_Actions (Is_Protected => True);
2361 end if;
2362
2363 -- Specific cases of object renamings
2364
aab08130 2365 elsif Nkind (Decl) = N_Object_Renaming_Declaration then
df3e68b1
HK
2366 Obj_Id := Defining_Identifier (Decl);
2367 Obj_Typ := Base_Type (Etype (Obj_Id));
2368
2369 -- Bypass any form of processing for objects which have their
2370 -- finalization disabled. This applies only to objects at the
2371 -- library level.
2372
36295779 2373 if For_Package and then Finalize_Storage_Only (Obj_Typ) then
df3e68b1
HK
2374 null;
2375
8636f52f
HK
2376 -- Ignored Ghost object renamings do not need any cleanup
2377 -- actions because they will not appear in the final tree.
2378
2379 elsif Is_Ignored_Ghost_Entity (Obj_Id) then
2380 null;
2381
df3e68b1
HK
2382 -- Return object of a build-in-place function. This case is
2383 -- recognized and marked by the expansion of an extended return
2384 -- statement (see Expand_N_Extended_Return_Statement).
2385
2386 elsif Needs_Finalization (Obj_Typ)
2387 and then Is_Return_Object (Obj_Id)
3cebd1c0 2388 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
df3e68b1
HK
2389 then
2390 Processing_Actions (Has_No_Init => True);
aab08130
AC
2391
2392 -- Detect a case where a source object has been initialized by
a429e6b3
AC
2393 -- a controlled function call or another object which was later
2394 -- rewritten as a class-wide conversion of Ada.Tags.Displace.
aab08130 2395
a429e6b3
AC
2396 -- Obj1 : CW_Type := Src_Obj;
2397 -- Obj2 : CW_Type := Function_Call (...);
aab08130 2398
a429e6b3
AC
2399 -- Obj1 : CW_Type renames (... Ada.Tags.Displace (Src_Obj));
2400 -- Tmp : ... := Function_Call (...)'reference;
2401 -- Obj2 : CW_Type renames (... Ada.Tags.Displace (Tmp));
aab08130 2402
a429e6b3 2403 elsif Is_Displacement_Of_Object_Or_Function_Result (Obj_Id) then
aab08130 2404 Processing_Actions (Has_No_Init => True);
df3e68b1
HK
2405 end if;
2406
2407 -- Inspect the freeze node of an access-to-controlled type and
d3f70b35
AC
2408 -- look for a delayed finalization master. This case arises when
2409 -- the freeze actions are inserted at a later time than the
df3e68b1 2410 -- expansion of the context. Since Build_Finalizer is never called
d3f70b35 2411 -- on a single construct twice, the master will be ultimately
df3e68b1
HK
2412 -- left out and never finalized. This is also needed for freeze
2413 -- actions of designated types themselves, since in some cases the
d3f70b35 2414 -- finalization master is associated with a designated type's
df3e68b1 2415 -- freeze node rather than that of the access type (see handling
d3f70b35 2416 -- for freeze actions in Build_Finalization_Master).
df3e68b1
HK
2417
2418 elsif Nkind (Decl) = N_Freeze_Entity
2419 and then Present (Actions (Decl))
2420 then
2421 Typ := Entity (Decl);
2422
8636f52f
HK
2423 -- Freeze nodes for ignored Ghost types do not need cleanup
2424 -- actions because they will never appear in the final tree.
2425
2426 if Is_Ignored_Ghost_Entity (Typ) then
2427 null;
2428
5af3a22a 2429 elsif (Is_Access_Object_Type (Typ)
8636f52f
HK
2430 and then Needs_Finalization
2431 (Available_View (Designated_Type (Typ))))
2432 or else (Is_Type (Typ) and then Needs_Finalization (Typ))
df3e68b1 2433 then
1cdfa9be
AC
2434 Old_Counter_Val := Counter_Val;
2435
2436 -- Freeze nodes are considered to be identical to packages
2437 -- and blocks in terms of nesting. The difference is that
d3f70b35
AC
2438 -- a finalization master created inside the freeze node is
2439 -- at the same nesting level as the node itself.
1cdfa9be 2440
df3e68b1 2441 Process_Declarations (Actions (Decl), Preprocess);
1cdfa9be 2442
d3f70b35 2443 -- The freeze node contains a finalization master
1cdfa9be
AC
2444
2445 if Preprocess
2446 and then Top_Level
2447 and then No (Last_Top_Level_Ctrl_Construct)
2448 and then Counter_Val > Old_Counter_Val
2449 then
2450 Last_Top_Level_Ctrl_Construct := Decl;
2451 end if;
df3e68b1
HK
2452 end if;
2453
2454 -- Nested package declarations, avoid generics
2455
2456 elsif Nkind (Decl) = N_Package_Declaration then
8636f52f
HK
2457 Pack_Id := Defining_Entity (Decl);
2458 Spec := Specification (Decl);
df3e68b1 2459
8636f52f
HK
2460 -- Do not inspect an ignored Ghost package because all code
2461 -- found within will not appear in the final tree.
2462
2463 if Is_Ignored_Ghost_Entity (Pack_Id) then
2464 null;
df3e68b1 2465
8636f52f 2466 elsif Ekind (Pack_Id) /= E_Generic_Package then
df3e68b1
HK
2467 Old_Counter_Val := Counter_Val;
2468 Process_Declarations
2469 (Private_Declarations (Spec), Preprocess);
2470 Process_Declarations
2471 (Visible_Declarations (Spec), Preprocess);
2472
2473 -- Either the visible or the private declarations contain a
2474 -- controlled object. The nested package declaration is the
2475 -- last such construct.
2476
2477 if Preprocess
2478 and then Top_Level
2479 and then No (Last_Top_Level_Ctrl_Construct)
2480 and then Counter_Val > Old_Counter_Val
2481 then
2482 Last_Top_Level_Ctrl_Construct := Decl;
2483 end if;
2484 end if;
2485
213c9dc7
AC
2486 -- Call the xxx__finalize_body procedure of a library level
2487 -- package instantiation if the body contains finalization
2488 -- statements.
2489
2490 if Present (Generic_Parent (Spec))
2491 and then Is_Library_Level_Entity (Pack_Id)
2492 and then Present (Body_Entity (Generic_Parent (Spec)))
2493 then
2494 if Preprocess then
2495 declare
2496 P : Node_Id;
2497 begin
2498 P := Parent (Body_Entity (Generic_Parent (Spec)));
2499 while Present (P)
2500 and then Nkind (P) /= N_Package_Body
2501 loop
2502 P := Parent (P);
2503 end loop;
2504
2505 if Present (P) then
2506 Old_Counter_Val := Counter_Val;
2507 Process_Declarations (Declarations (P), Preprocess);
2508
2509 -- Note that we are processing the generic body
2510 -- template and not the actually instantiation
2511 -- (which is generated too late for us to process
2512 -- it), so there is no need to update in particular
6d16658d 2513 -- Last_Top_Level_Ctrl_Construct here.
213c9dc7
AC
2514
2515 if Counter_Val > Old_Counter_Val then
2516 Counter_Val := Old_Counter_Val;
2517 Set_Has_Controlled_Component (Pack_Id);
2518 end if;
2519 end if;
2520 end;
2521
2522 elsif Has_Controlled_Component (Pack_Id) then
2523
2524 -- We import the xxx__finalize_body routine since the
2525 -- generic body will be instantiated later.
2526
2527 declare
2528 Id : constant Node_Id :=
2529 Make_Defining_Identifier (Loc,
2530 New_Finalizer_Name (Defining_Unit_Name (Spec),
2531 For_Spec => False));
2532
2533 begin
2534 Set_Has_Qualified_Name (Id);
2535 Set_Has_Fully_Qualified_Name (Id);
2536 Set_Is_Imported (Id);
2537 Set_Has_Completion (Id);
2538 Set_Interface_Name (Id,
2539 Make_String_Literal (Loc,
2540 Strval => Get_Name_String (Chars (Id))));
2541
2542 Append_New_To (Finalizer_Stmts,
2543 Make_Subprogram_Declaration (Loc,
2544 Make_Procedure_Specification (Loc,
2545 Defining_Unit_Name => Id)));
2546 Append_To (Finalizer_Stmts,
2547 Make_Procedure_Call_Statement (Loc,
2548 Name => New_Occurrence_Of (Id, Loc)));
2549 end;
2550 end if;
2551 end if;
2552
df3e68b1
HK
2553 -- Nested package bodies, avoid generics
2554
2555 elsif Nkind (Decl) = N_Package_Body then
df3e68b1 2556
8636f52f
HK
2557 -- Do not inspect an ignored Ghost package body because all
2558 -- code found within will not appear in the final tree.
2559
2560 if Is_Ignored_Ghost_Entity (Defining_Entity (Decl)) then
2561 null;
2562
213c9dc7 2563 elsif Ekind (Corresponding_Spec (Decl)) /= E_Generic_Package
8636f52f 2564 then
df3e68b1
HK
2565 Old_Counter_Val := Counter_Val;
2566 Process_Declarations (Declarations (Decl), Preprocess);
2567
2568 -- The nested package body is the last construct to contain
2569 -- a controlled object.
2570
2571 if Preprocess
2572 and then Top_Level
2573 and then No (Last_Top_Level_Ctrl_Construct)
2574 and then Counter_Val > Old_Counter_Val
2575 then
2576 Last_Top_Level_Ctrl_Construct := Decl;
2577 end if;
2578 end if;
2579
937e9676 2580 -- Handle a rare case caused by a controlled transient object
df3e68b1
HK
2581 -- created as part of a record init proc. The variable is wrapped
2582 -- in a block, but the block is not associated with a transient
2583 -- scope.
2584
2585 elsif Nkind (Decl) = N_Block_Statement
2586 and then Inside_Init_Proc
2587 then
2588 Old_Counter_Val := Counter_Val;
2589
2590 if Present (Handled_Statement_Sequence (Decl)) then
2591 Process_Declarations
2592 (Statements (Handled_Statement_Sequence (Decl)),
2593 Preprocess);
2594 end if;
2595
2596 Process_Declarations (Declarations (Decl), Preprocess);
2597
2598 -- Either the declaration or statement list of the block has a
2599 -- controlled object.
2600
2601 if Preprocess
2602 and then Top_Level
2603 and then No (Last_Top_Level_Ctrl_Construct)
2604 and then Counter_Val > Old_Counter_Val
2605 then
2606 Last_Top_Level_Ctrl_Construct := Decl;
2607 end if;
e98668b1
AC
2608
2609 -- Handle the case where the original context has been wrapped in
2610 -- a block to avoid interference between exception handlers and
2611 -- At_End handlers. Treat the block as transparent and process its
2612 -- contents.
2613
2614 elsif Nkind (Decl) = N_Block_Statement
2615 and then Is_Finalization_Wrapper (Decl)
2616 then
2617 if Present (Handled_Statement_Sequence (Decl)) then
2618 Process_Declarations
2619 (Statements (Handled_Statement_Sequence (Decl)),
2620 Preprocess);
2621 end if;
2622
2623 Process_Declarations (Declarations (Decl), Preprocess);
df3e68b1
HK
2624 end if;
2625
2626 Prev_Non_Pragma (Decl);
2627 end loop;
2628 end Process_Declarations;
2629
2630 --------------------------------
2631 -- Process_Object_Declaration --
2632 --------------------------------
2633
2634 procedure Process_Object_Declaration
2635 (Decl : Node_Id;
2636 Has_No_Init : Boolean := False;
2637 Is_Protected : Boolean := False)
2638 is
0382062b
AC
2639 Loc : constant Source_Ptr := Sloc (Decl);
2640 Obj_Id : constant Entity_Id := Defining_Identifier (Decl);
df3e68b1 2641
0382062b
AC
2642 Init_Typ : Entity_Id;
2643 -- The initialization type of the related object declaration. Note
2cc2e964 2644 -- that this is not necessarily the same type as Obj_Typ because of
0382062b
AC
2645 -- possible type derivations.
2646
2647 Obj_Typ : Entity_Id;
2648 -- The type of the related object declaration
2649
2650 function Build_BIP_Cleanup_Stmts (Func_Id : Entity_Id) return Node_Id;
2651 -- Func_Id denotes a build-in-place function. Generate the following
2652 -- cleanup code:
df3e68b1
HK
2653 --
2654 -- if BIPallocfrom > Secondary_Stack'Pos
d3f70b35 2655 -- and then BIPfinalizationmaster /= null
df3e68b1
HK
2656 -- then
2657 -- declare
2658 -- type Ptr_Typ is access Obj_Typ;
d3f70b35
AC
2659 -- for Ptr_Typ'Storage_Pool
2660 -- use Base_Pool (BIPfinalizationmaster);
df3e68b1
HK
2661 -- begin
2662 -- Free (Ptr_Typ (Temp));
2663 -- end;
2664 -- end if;
2665 --
2666 -- Obj_Typ is the type of the current object, Temp is the original
2667 -- allocation which Obj_Id renames.
2668
2669 procedure Find_Last_Init
0382062b 2670 (Last_Init : out Node_Id;
df3e68b1 2671 Body_Insert : out Node_Id);
4ac2bbbd
AC
2672 -- Find the last initialization call related to object declaration
2673 -- Decl. Last_Init denotes the last initialization call which follows
0382062b
AC
2674 -- Decl. Body_Insert denotes a node where the finalizer body could be
2675 -- potentially inserted after (if blocks are involved).
df3e68b1
HK
2676
2677 -----------------------------
2678 -- Build_BIP_Cleanup_Stmts --
2679 -----------------------------
2680
2681 function Build_BIP_Cleanup_Stmts
0382062b 2682 (Func_Id : Entity_Id) return Node_Id
df3e68b1 2683 is
d3f70b35
AC
2684 Decls : constant List_Id := New_List;
2685 Fin_Mas_Id : constant Entity_Id :=
2686 Build_In_Place_Formal
2687 (Func_Id, BIP_Finalization_Master);
0382062b 2688 Func_Typ : constant Entity_Id := Etype (Func_Id);
d3f70b35
AC
2689 Temp_Id : constant Entity_Id :=
2690 Entity (Prefix (Name (Parent (Obj_Id))));
df3e68b1
HK
2691
2692 Cond : Node_Id;
2693 Free_Blk : Node_Id;
2694 Free_Stmt : Node_Id;
2695 Pool_Id : Entity_Id;
2696 Ptr_Typ : Entity_Id;
2697
2698 begin
2699 -- Generate:
d3f70b35 2700 -- Pool_Id renames Base_Pool (BIPfinalizationmaster.all).all;
df3e68b1
HK
2701
2702 Pool_Id := Make_Temporary (Loc, 'P');
2703
2704 Append_To (Decls,
2705 Make_Object_Renaming_Declaration (Loc,
2706 Defining_Identifier => Pool_Id,
cfae2bed 2707 Subtype_Mark =>
e4494292 2708 New_Occurrence_Of (RTE (RE_Root_Storage_Pool), Loc),
cfae2bed 2709 Name =>
df3e68b1
HK
2710 Make_Explicit_Dereference (Loc,
2711 Prefix =>
2712 Make_Function_Call (Loc,
cfae2bed 2713 Name =>
e4494292 2714 New_Occurrence_Of (RTE (RE_Base_Pool), Loc),
df3e68b1
HK
2715 Parameter_Associations => New_List (
2716 Make_Explicit_Dereference (Loc,
e4494292
RD
2717 Prefix =>
2718 New_Occurrence_Of (Fin_Mas_Id, Loc)))))));
df3e68b1
HK
2719
2720 -- Create an access type which uses the storage pool of the
d3f70b35 2721 -- caller's finalization master.
df3e68b1
HK
2722
2723 -- Generate:
0382062b 2724 -- type Ptr_Typ is access Func_Typ;
df3e68b1
HK
2725
2726 Ptr_Typ := Make_Temporary (Loc, 'P');
2727
2728 Append_To (Decls,
2729 Make_Full_Type_Declaration (Loc,
2730 Defining_Identifier => Ptr_Typ,
cfae2bed 2731 Type_Definition =>
df3e68b1 2732 Make_Access_To_Object_Definition (Loc,
0382062b 2733 Subtype_Indication => New_Occurrence_Of (Func_Typ, Loc))));
df3e68b1 2734
d3f70b35 2735 -- Perform minor decoration in order to set the master and the
df3e68b1
HK
2736 -- storage pool attributes.
2737
2e02ab86 2738 Mutate_Ekind (Ptr_Typ, E_Access_Type);
d3f70b35 2739 Set_Finalization_Master (Ptr_Typ, Fin_Mas_Id);
df3e68b1
HK
2740 Set_Associated_Storage_Pool (Ptr_Typ, Pool_Id);
2741
bbf14e13
AC
2742 if Debug_Generated_Code then
2743 Set_Debug_Info_Needed (Pool_Id);
2744 end if;
2745
df3e68b1
HK
2746 -- Create an explicit free statement. Note that the free uses the
2747 -- caller's pool expressed as a renaming.
2748
2749 Free_Stmt :=
2750 Make_Free_Statement (Loc,
2751 Expression =>
2752 Unchecked_Convert_To (Ptr_Typ,
e4494292 2753 New_Occurrence_Of (Temp_Id, Loc)));
df3e68b1
HK
2754
2755 Set_Storage_Pool (Free_Stmt, Pool_Id);
2756
2757 -- Create a block to house the dummy type and the instantiation as
2758 -- well as to perform the cleanup the temporary.
2759
2760 -- Generate:
2761 -- declare
2762 -- <Decls>
2763 -- begin
2764 -- Free (Ptr_Typ (Temp_Id));
2765 -- end;
2766
2767 Free_Blk :=
2768 Make_Block_Statement (Loc,
cfae2bed 2769 Declarations => Decls,
df3e68b1
HK
2770 Handled_Statement_Sequence =>
2771 Make_Handled_Sequence_Of_Statements (Loc,
2772 Statements => New_List (Free_Stmt)));
2773
2774 -- Generate:
d3f70b35 2775 -- if BIPfinalizationmaster /= null then
df3e68b1
HK
2776
2777 Cond :=
2778 Make_Op_Ne (Loc,
e4494292 2779 Left_Opnd => New_Occurrence_Of (Fin_Mas_Id, Loc),
cfae2bed 2780 Right_Opnd => Make_Null (Loc));
df3e68b1 2781
ef07419f 2782 -- For unconstrained or tagged results, escalate the condition to
df3e68b1 2783 -- include the allocation format. Generate:
41c79d60 2784
df3e68b1 2785 -- if BIPallocform > Secondary_Stack'Pos
d3f70b35 2786 -- and then BIPfinalizationmaster /= null
df3e68b1
HK
2787 -- then
2788
ef07419f 2789 if Needs_BIP_Alloc_Form (Func_Id) then
df3e68b1
HK
2790 declare
2791 Alloc : constant Entity_Id :=
2792 Build_In_Place_Formal (Func_Id, BIP_Alloc_Form);
2793 begin
2794 Cond :=
2795 Make_And_Then (Loc,
cfae2bed 2796 Left_Opnd =>
df3e68b1 2797 Make_Op_Gt (Loc,
e4494292 2798 Left_Opnd => New_Occurrence_Of (Alloc, Loc),
df3e68b1
HK
2799 Right_Opnd =>
2800 Make_Integer_Literal (Loc,
2801 UI_From_Int
2802 (BIP_Allocation_Form'Pos (Secondary_Stack)))),
2803
2804 Right_Opnd => Cond);
2805 end;
2806 end if;
2807
2808 -- Generate:
2809 -- if <Cond> then
2810 -- <Free_Blk>
2811 -- end if;
2812
2813 return
2814 Make_If_Statement (Loc,
cfae2bed 2815 Condition => Cond,
df3e68b1
HK
2816 Then_Statements => New_List (Free_Blk));
2817 end Build_BIP_Cleanup_Stmts;
2818
2819 --------------------
2820 -- Find_Last_Init --
2821 --------------------
2822
2823 procedure Find_Last_Init
0382062b 2824 (Last_Init : out Node_Id;
df3e68b1
HK
2825 Body_Insert : out Node_Id)
2826 is
0382062b 2827 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id;
4ac2bbbd 2828 -- Find the last initialization call within the statements of
0382062b 2829 -- block Blk.
4ac2bbbd 2830
0382062b 2831 function Is_Init_Call (N : Node_Id) return Boolean;
4ac2bbbd 2832 -- Determine whether node N denotes one of the initialization
0382062b 2833 -- procedures of types Init_Typ or Obj_Typ.
df3e68b1 2834
97ed5872 2835 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id;
90e491a7
PMR
2836 -- Obtain the next statement which follows list member Stmt while
2837 -- ignoring artifacts related to access-before-elaboration checks.
4ac2bbbd
AC
2838
2839 -----------------------------
2840 -- Find_Last_Init_In_Block --
2841 -----------------------------
2842
0382062b 2843 function Find_Last_Init_In_Block (Blk : Node_Id) return Node_Id is
4ac2bbbd
AC
2844 HSS : constant Node_Id := Handled_Statement_Sequence (Blk);
2845 Stmt : Node_Id;
2846
2847 begin
2848 -- Examine the individual statements of the block in reverse to
2849 -- locate the last initialization call.
2850
2851 if Present (HSS) and then Present (Statements (HSS)) then
2852 Stmt := Last (Statements (HSS));
2853 while Present (Stmt) loop
2854
2855 -- Peek inside nested blocks in case aborts are allowed
2856
2857 if Nkind (Stmt) = N_Block_Statement then
0382062b 2858 return Find_Last_Init_In_Block (Stmt);
4ac2bbbd 2859
0382062b 2860 elsif Is_Init_Call (Stmt) then
4ac2bbbd
AC
2861 return Stmt;
2862 end if;
2863
2864 Prev (Stmt);
2865 end loop;
2866 end if;
2867
2868 return Empty;
2869 end Find_Last_Init_In_Block;
97ed5872 2870
df3e68b1
HK
2871 ------------------
2872 -- Is_Init_Call --
2873 ------------------
2874
0382062b
AC
2875 function Is_Init_Call (N : Node_Id) return Boolean is
2876 function Is_Init_Proc_Of
2877 (Subp_Id : Entity_Id;
2878 Typ : Entity_Id) return Boolean;
2879 -- Determine whether subprogram Subp_Id is a valid init proc of
2880 -- type Typ.
2881
2882 ---------------------
2883 -- Is_Init_Proc_Of --
2884 ---------------------
2885
2886 function Is_Init_Proc_Of
2887 (Subp_Id : Entity_Id;
2888 Typ : Entity_Id) return Boolean
2889 is
2890 Deep_Init : Entity_Id := Empty;
2891 Prim_Init : Entity_Id := Empty;
2892 Type_Init : Entity_Id := Empty;
df3e68b1 2893
0382062b
AC
2894 begin
2895 -- Obtain all possible initialization routines of the
2896 -- related type and try to match the subprogram entity
2897 -- against one of them.
4ac2bbbd
AC
2898
2899 -- Deep_Initialize
2900
0382062b 2901 Deep_Init := TSS (Typ, TSS_Deep_Initialize);
4ac2bbbd
AC
2902
2903 -- Primitive Initialize
df3e68b1 2904
0382062b 2905 if Is_Controlled (Typ) then
ca811241 2906 Prim_Init := Find_Optional_Prim_Op (Typ, Name_Initialize);
ca5af305 2907
4ac2bbbd
AC
2908 if Present (Prim_Init) then
2909 Prim_Init := Ultimate_Alias (Prim_Init);
df3e68b1 2910 end if;
4ac2bbbd 2911 end if;
df3e68b1 2912
4ac2bbbd
AC
2913 -- Type initialization routine
2914
0382062b
AC
2915 if Has_Non_Null_Base_Init_Proc (Typ) then
2916 Type_Init := Base_Init_Proc (Typ);
4ac2bbbd
AC
2917 end if;
2918
2919 return
0382062b 2920 (Present (Deep_Init) and then Subp_Id = Deep_Init)
4ac2bbbd 2921 or else
0382062b
AC
2922 (Present (Prim_Init) and then Subp_Id = Prim_Init)
2923 or else
2924 (Present (Type_Init) and then Subp_Id = Type_Init);
2925 end Is_Init_Proc_Of;
2926
2927 -- Local variables
2928
2929 Call_Id : Entity_Id;
2930
2931 -- Start of processing for Is_Init_Call
2932
2933 begin
2934 if Nkind (N) = N_Procedure_Call_Statement
2935 and then Nkind (Name (N)) = N_Identifier
2936 then
2937 Call_Id := Entity (Name (N));
2938
2939 -- Consider both the type of the object declaration and its
2940 -- related initialization type.
2941
2942 return
2943 Is_Init_Proc_Of (Call_Id, Init_Typ)
4ac2bbbd 2944 or else
0382062b 2945 Is_Init_Proc_Of (Call_Id, Obj_Typ);
df3e68b1
HK
2946 end if;
2947
2948 return False;
2949 end Is_Init_Call;
2950
97ed5872
AC
2951 -----------------------------
2952 -- Next_Suitable_Statement --
2953 -----------------------------
2954
2955 function Next_Suitable_Statement (Stmt : Node_Id) return Node_Id is
90e491a7 2956 Result : Node_Id;
97ed5872
AC
2957
2958 begin
90e491a7
PMR
2959 -- Skip call markers and Program_Error raises installed by the
2960 -- ABE mechanism.
2961
2962 Result := Next (Stmt);
2963 while Present (Result) loop
4a08c95c
AC
2964 exit when Nkind (Result) not in
2965 N_Call_Marker | N_Raise_Program_Error;
97ed5872 2966
cbbe41d1 2967 Next (Result);
90e491a7 2968 end loop;
97ed5872
AC
2969
2970 return Result;
2971 end Next_Suitable_Statement;
2972
7b966a95
AC
2973 -- Local variables
2974
0382062b
AC
2975 Call : Node_Id;
2976 Stmt : Node_Id;
2977 Stmt_2 : Node_Id;
7b966a95 2978
b8b2d982
AC
2979 Deep_Init_Found : Boolean := False;
2980 -- A flag set when a call to [Deep_]Initialize has been found
2981
df3e68b1
HK
2982 -- Start of processing for Find_Last_Init
2983
2984 begin
2985 Last_Init := Decl;
2986 Body_Insert := Empty;
2987
2988 -- Object renamings and objects associated with controlled
4ac2bbbd 2989 -- function results do not require initialization.
df3e68b1
HK
2990
2991 if Has_No_Init then
2992 return;
2993 end if;
2994
4ac2bbbd
AC
2995 Stmt := Next_Suitable_Statement (Decl);
2996
0691ed6b
AC
2997 -- For an object with suppressed initialization, we check whether
2998 -- there is in fact no initialization expression. If there is not,
2999 -- then this is an object declaration that has been turned into a
3000 -- different object declaration that calls the build-in-place
3001 -- function in a 'Reference attribute, as in "F(...)'Reference".
3002 -- We search for that later object declaration, so that the
3003 -- Inc_Decl will be inserted after the call. Otherwise, if the
3004 -- call raises an exception, we will finalize the (uninitialized)
3005 -- object, which is wrong.
7b966a95 3006
3386e3ae 3007 if No_Initialization (Decl) then
0691ed6b
AC
3008 if No (Expression (Last_Init)) then
3009 loop
cbbe41d1 3010 Next (Last_Init);
0691ed6b
AC
3011 exit when No (Last_Init);
3012 exit when Nkind (Last_Init) = N_Object_Declaration
3013 and then Nkind (Expression (Last_Init)) = N_Reference
3014 and then Nkind (Prefix (Expression (Last_Init))) =
3015 N_Function_Call
3016 and then Is_Expanded_Build_In_Place_Call
3017 (Prefix (Expression (Last_Init)));
3018 end loop;
3019 end if;
3020
24de083f
AC
3021 return;
3022
c901877f
EB
3023 -- If the initialization is in the declaration, we're done, so
3024 -- early return if we have no more statements or they have been
3025 -- rewritten, which means that they were in the source code.
3026
3027 elsif No (Stmt) or else Original_Node (Stmt) /= Stmt then
3028 return;
3029
4ac2bbbd
AC
3030 -- In all other cases the initialization calls follow the related
3031 -- object. The general structure of object initialization built by
3032 -- routine Default_Initialize_Object is as follows:
3033
3034 -- [begin -- aborts allowed
3035 -- Abort_Defer;]
3036 -- Type_Init_Proc (Obj);
3037 -- [begin] -- exceptions allowed
3038 -- Deep_Initialize (Obj);
3039 -- [exception -- exceptions allowed
3040 -- when others =>
3041 -- Deep_Finalize (Obj, Self => False);
3042 -- raise;
3043 -- end;]
3044 -- [at end -- aborts allowed
3045 -- Abort_Undefer;
3046 -- end;]
3047
3048 -- When aborts are allowed, the initialization calls are housed
3049 -- within a block.
3050
3051 elsif Nkind (Stmt) = N_Block_Statement then
0382062b 3052 Last_Init := Find_Last_Init_In_Block (Stmt);
4ac2bbbd
AC
3053 Body_Insert := Stmt;
3054
3055 -- Otherwise the initialization calls follow the related object
df3e68b1 3056
7b966a95 3057 else
4ac2bbbd 3058 Stmt_2 := Next_Suitable_Statement (Stmt);
df3e68b1 3059
4ac2bbbd
AC
3060 -- Check for an optional call to Deep_Initialize which may
3061 -- appear within a block depending on whether the object has
3062 -- controlled components.
df3e68b1 3063
4ac2bbbd
AC
3064 if Present (Stmt_2) then
3065 if Nkind (Stmt_2) = N_Block_Statement then
0382062b 3066 Call := Find_Last_Init_In_Block (Stmt_2);
df3e68b1 3067
4ac2bbbd 3068 if Present (Call) then
b8b2d982
AC
3069 Deep_Init_Found := True;
3070 Last_Init := Call;
3071 Body_Insert := Stmt_2;
4ac2bbbd 3072 end if;
df3e68b1 3073
0382062b 3074 elsif Is_Init_Call (Stmt_2) then
b8b2d982
AC
3075 Deep_Init_Found := True;
3076 Last_Init := Stmt_2;
3077 Body_Insert := Last_Init;
4ac2bbbd 3078 end if;
b8b2d982 3079 end if;
df3e68b1 3080
4ac2bbbd
AC
3081 -- If the object lacks a call to Deep_Initialize, then it must
3082 -- have a call to its related type init proc.
df3e68b1 3083
b8b2d982 3084 if not Deep_Init_Found and then Is_Init_Call (Stmt) then
4ac2bbbd
AC
3085 Last_Init := Stmt;
3086 Body_Insert := Last_Init;
df3e68b1
HK
3087 end if;
3088 end if;
3089 end Find_Last_Init;
3090
4ac2bbbd
AC
3091 -- Local variables
3092
4ac2bbbd
AC
3093 Body_Ins : Node_Id;
3094 Count_Ins : Node_Id;
3095 Fin_Call : Node_Id;
321c24f7 3096 Fin_Stmts : List_Id := No_List;
4ac2bbbd
AC
3097 Inc_Decl : Node_Id;
3098 Label : Node_Id;
3099 Label_Id : Entity_Id;
3100 Obj_Ref : Node_Id;
4ac2bbbd 3101
df3e68b1
HK
3102 -- Start of processing for Process_Object_Declaration
3103
3104 begin
0382062b
AC
3105 -- Handle the object type and the reference to the object
3106
e4494292 3107 Obj_Ref := New_Occurrence_Of (Obj_Id, Loc);
df3e68b1
HK
3108 Obj_Typ := Base_Type (Etype (Obj_Id));
3109
0382062b
AC
3110 loop
3111 if Is_Access_Type (Obj_Typ) then
3112 Obj_Typ := Directly_Designated_Type (Obj_Typ);
3113 Obj_Ref := Make_Explicit_Dereference (Loc, Obj_Ref);
df3e68b1 3114
0382062b
AC
3115 elsif Is_Concurrent_Type (Obj_Typ)
3116 and then Present (Corresponding_Record_Type (Obj_Typ))
3117 then
3118 Obj_Typ := Corresponding_Record_Type (Obj_Typ);
3119 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
3120
3121 elsif Is_Private_Type (Obj_Typ)
3122 and then Present (Full_View (Obj_Typ))
3123 then
3124 Obj_Typ := Full_View (Obj_Typ);
3125 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
3126
3127 elsif Obj_Typ /= Base_Type (Obj_Typ) then
3128 Obj_Typ := Base_Type (Obj_Typ);
3129 Obj_Ref := Unchecked_Convert_To (Obj_Typ, Obj_Ref);
3130
3131 else
3132 exit;
3133 end if;
3134 end loop;
df3e68b1
HK
3135
3136 Set_Etype (Obj_Ref, Obj_Typ);
3137
0382062b
AC
3138 -- Handle the initialization type of the object declaration
3139
3140 Init_Typ := Obj_Typ;
3141 loop
3142 if Is_Private_Type (Init_Typ)
3143 and then Present (Full_View (Init_Typ))
3144 then
3145 Init_Typ := Full_View (Init_Typ);
3146
3147 elsif Is_Untagged_Derivation (Init_Typ) then
3148 Init_Typ := Root_Type (Init_Typ);
3149
3150 else
3151 exit;
3152 end if;
3153 end loop;
3154
df3e68b1
HK
3155 -- Set a new value for the state counter and insert the statement
3156 -- after the object declaration. Generate:
7b966a95 3157
df3e68b1
HK
3158 -- Counter := <value>;
3159
3160 Inc_Decl :=
3161 Make_Assignment_Statement (Loc,
e4494292 3162 Name => New_Occurrence_Of (Counter_Id, Loc),
cfae2bed 3163 Expression => Make_Integer_Literal (Loc, Counter_Val));
df3e68b1
HK
3164
3165 -- Insert the counter after all initialization has been done. The
3386e3ae 3166 -- place of insertion depends on the context.
df3e68b1 3167
4a08c95c 3168 if Ekind (Obj_Id) in E_Constant | E_Variable then
3386e3ae
AC
3169
3170 -- The object is initialized by a build-in-place function call.
3171 -- The counter insertion point is after the function call.
3172
3173 if Present (BIP_Initialization_Call (Obj_Id)) then
3174 Count_Ins := BIP_Initialization_Call (Obj_Id);
3175 Body_Ins := Empty;
3176
3177 -- The object is initialized by an aggregate. Insert the counter
3178 -- after the last aggregate assignment.
3179
3180 elsif Present (Last_Aggregate_Assignment (Obj_Id)) then
3181 Count_Ins := Last_Aggregate_Assignment (Obj_Id);
3182 Body_Ins := Empty;
3183
3184 -- In all other cases the counter is inserted after the last call
3185 -- to either [Deep_]Initialize or the type-specific init proc.
3186
3187 else
3188 Find_Last_Init (Count_Ins, Body_Ins);
3189 end if;
97779c34
AC
3190
3191 -- In all other cases the counter is inserted after the last call to
3386e3ae 3192 -- either [Deep_]Initialize or the type-specific init proc.
97779c34
AC
3193
3194 else
0382062b 3195 Find_Last_Init (Count_Ins, Body_Ins);
97779c34 3196 end if;
df3e68b1 3197
1804faa4
AC
3198 -- If the Initialize function is null or trivial, the call will have
3199 -- been replaced with a null statement, in which case place counter
3200 -- declaration after object declaration itself.
3201
3202 if No (Count_Ins) then
3203 Count_Ins := Decl;
3204 end if;
3205
df3e68b1
HK
3206 Insert_After (Count_Ins, Inc_Decl);
3207 Analyze (Inc_Decl);
3208
3209 -- If the current declaration is the last in the list, the finalizer
3210 -- body needs to be inserted after the set counter statement for the
3211 -- current object declaration. This is complicated by the fact that
3212 -- the set counter statement may appear in abort deferred block. In
3213 -- that case, the proper insertion place is after the block.
3214
3215 if No (Finalizer_Insert_Nod) then
3216
0691ed6b 3217 -- Insertion after an abort deferred block
df3e68b1
HK
3218
3219 if Present (Body_Ins) then
3220 Finalizer_Insert_Nod := Body_Ins;
3221 else
3222 Finalizer_Insert_Nod := Inc_Decl;
3223 end if;
3224 end if;
3225
3226 -- Create the associated label with this object, generate:
4ac2bbbd 3227
df3e68b1
HK
3228 -- L<counter> : label;
3229
3230 Label_Id :=
cfae2bed 3231 Make_Identifier (Loc, New_External_Name ('L', Counter_Val));
886b5a18
AC
3232 Set_Entity
3233 (Label_Id, Make_Defining_Identifier (Loc, Chars (Label_Id)));
df3e68b1
HK
3234 Label := Make_Label (Loc, Label_Id);
3235
3236 Prepend_To (Finalizer_Decls,
3237 Make_Implicit_Label_Declaration (Loc,
3238 Defining_Identifier => Entity (Label_Id),
cfae2bed 3239 Label_Construct => Label));
df3e68b1
HK
3240
3241 -- Create the associated jump with this object, generate:
4b03d946 3242
df3e68b1
HK
3243 -- when <counter> =>
3244 -- goto L<counter>;
3245
3246 Prepend_To (Jump_Alts,
3247 Make_Case_Statement_Alternative (Loc,
3248 Discrete_Choices => New_List (
3249 Make_Integer_Literal (Loc, Counter_Val)),
cfae2bed 3250 Statements => New_List (
df3e68b1 3251 Make_Goto_Statement (Loc,
e4494292 3252 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
df3e68b1
HK
3253
3254 -- Insert the jump destination, generate:
4b03d946 3255
df3e68b1
HK
3256 -- <<L<counter>>>
3257
3258 Append_To (Finalizer_Stmts, Label);
3259
54c49fcd
GL
3260 -- Disable warnings on Obj_Id. This works around an issue where GCC
3261 -- is not able to detect that Obj_Id is protected by a counter and
3262 -- emits spurious warnings.
3263
3264 if not Comes_From_Source (Obj_Id) then
3265 Set_Warnings_Off (Obj_Id);
3266 end if;
3267
df3e68b1
HK
3268 -- Processing for simple protected objects. Such objects require
3269 -- manual finalization of their lock managers.
3270
3271 if Is_Protected then
df3e68b1 3272 if Is_Simple_Protected_Type (Obj_Typ) then
88f47280 3273 Fin_Call := Cleanup_Protected_Object (Decl, Obj_Ref);
886b5a18 3274
88f47280
AC
3275 if Present (Fin_Call) then
3276 Fin_Stmts := New_List (Fin_Call);
3277 end if;
df3e68b1
HK
3278
3279 elsif Has_Simple_Protected_Object (Obj_Typ) then
3280 if Is_Record_Type (Obj_Typ) then
3281 Fin_Stmts := Cleanup_Record (Decl, Obj_Ref, Obj_Typ);
df3e68b1
HK
3282 elsif Is_Array_Type (Obj_Typ) then
3283 Fin_Stmts := Cleanup_Array (Decl, Obj_Ref, Obj_Typ);
3284 end if;
3285 end if;
3286
3287 -- Generate:
3288 -- begin
3289 -- System.Tasking.Protected_Objects.Finalize_Protection
3290 -- (Obj._object);
886b5a18 3291
df3e68b1
HK
3292 -- exception
3293 -- when others =>
3294 -- null;
3295 -- end;
3296
321c24f7
AC
3297 if Present (Fin_Stmts) and then Exceptions_OK then
3298 Fin_Stmts := New_List (
df3e68b1
HK
3299 Make_Block_Statement (Loc,
3300 Handled_Statement_Sequence =>
3301 Make_Handled_Sequence_Of_Statements (Loc,
cfae2bed 3302 Statements => Fin_Stmts,
df3e68b1
HK
3303
3304 Exception_Handlers => New_List (
3305 Make_Exception_Handler (Loc,
3306 Exception_Choices => New_List (
3307 Make_Others_Choice (Loc)),
3308
cfae2bed 3309 Statements => New_List (
df3e68b1
HK
3310 Make_Null_Statement (Loc)))))));
3311 end if;
3312
3313 -- Processing for regular controlled objects
3314
3315 else
3316 -- Generate:
7bf911b5 3317 -- begin
df3e68b1 3318 -- [Deep_]Finalize (Obj);
886b5a18 3319
df3e68b1
HK
3320 -- exception
3321 -- when Id : others =>
3322 -- if not Raised then
3323 -- Raised := True;
3324 -- Save_Occurrence (E, Id);
3325 -- end if;
3326 -- end;
3327
3328 Fin_Call :=
3329 Make_Final_Call (
3330 Obj_Ref => Obj_Ref,
3331 Typ => Obj_Typ);
3332
2168d7cc
AC
3333 -- Guard against a missing [Deep_]Finalize when the object type
3334 -- was not properly frozen.
3335
3336 if No (Fin_Call) then
3337 Fin_Call := Make_Null_Statement (Loc);
3338 end if;
3339
e6807723
AC
3340 -- For CodePeer, the exception handlers normally generated here
3341 -- generate complex flowgraphs which result in capacity problems.
3342 -- Omitting these handlers for CodePeer is justified as follows:
3343
3344 -- If a handler is dead, then omitting it is surely ok
3345
3346 -- If a handler is live, then CodePeer should flag the
3347 -- potentially-exception-raising construct that causes it
3348 -- to be live. That is what we are interested in, not what
3349 -- happens after the exception is raised.
3350
3351 if Exceptions_OK and not CodePeer_Mode then
df3e68b1
HK
3352 Fin_Stmts := New_List (
3353 Make_Block_Statement (Loc,
3354 Handled_Statement_Sequence =>
3355 Make_Handled_Sequence_Of_Statements (Loc,
3356 Statements => New_List (Fin_Call),
3357
3358 Exception_Handlers => New_List (
3359 Build_Exception_Handler
36b8f95f 3360 (Finalizer_Data, For_Package)))));
df3e68b1
HK
3361
3362 -- When exception handlers are prohibited, the finalization call
3363 -- appears unprotected. Any exception raised during finalization
3364 -- will bypass the circuitry which ensures the cleanup of all
3365 -- remaining objects.
3366
3367 else
3368 Fin_Stmts := New_List (Fin_Call);
3369 end if;
3370
3371 -- If we are dealing with a return object of a build-in-place
3372 -- function, generate the following cleanup statements:
886b5a18 3373
d3f70b35
AC
3374 -- if BIPallocfrom > Secondary_Stack'Pos
3375 -- and then BIPfinalizationmaster /= null
3376 -- then
df3e68b1
HK
3377 -- declare
3378 -- type Ptr_Typ is access Obj_Typ;
3379 -- for Ptr_Typ'Storage_Pool use
d3f70b35 3380 -- Base_Pool (BIPfinalizationmaster.all).all;
df3e68b1
HK
3381 -- begin
3382 -- Free (Ptr_Typ (Temp));
3383 -- end;
3384 -- end if;
4b03d946 3385
df3e68b1 3386 -- The generated code effectively detaches the temporary from the
535a8637 3387 -- caller finalization master and deallocates the object.
df3e68b1 3388
535a8637 3389 if Is_Return_Object (Obj_Id) then
df3e68b1 3390 declare
4844a259
EB
3391 Func_Id : constant Entity_Id :=
3392 Return_Applies_To (Scope (Obj_Id));
3393
df3e68b1
HK
3394 begin
3395 if Is_Build_In_Place_Function (Func_Id)
d3f70b35 3396 and then Needs_BIP_Finalization_Master (Func_Id)
df3e68b1 3397 then
0382062b 3398 Append_To (Fin_Stmts, Build_BIP_Cleanup_Stmts (Func_Id));
df3e68b1
HK
3399 end if;
3400 end;
3401 end if;
3402
4a08c95c 3403 if Ekind (Obj_Id) in E_Constant | E_Variable
3cebd1c0 3404 and then Present (Status_Flag_Or_Transient_Decl (Obj_Id))
df3e68b1 3405 then
35a1c212 3406 -- Temporaries created for the purpose of "exporting" a
937e9676 3407 -- transient object out of an Expression_With_Actions (EWA)
35a1c212
AC
3408 -- need guards. The following illustrates the usage of such
3409 -- temporaries.
3410
3411 -- Access_Typ : access [all] Obj_Typ;
3412 -- Temp : Access_Typ := null;
3413 -- <Counter> := ...;
3414
3415 -- do
3416 -- Ctrl_Trans : [access [all]] Obj_Typ := ...;
3417 -- Temp := Access_Typ (Ctrl_Trans); -- when a pointer
3418 -- <or>
3419 -- Temp := Ctrl_Trans'Unchecked_Access;
3420 -- in ... end;
3421
3422 -- The finalization machinery does not process EWA nodes as
3423 -- this may lead to premature finalization of expressions. Note
3424 -- that Temp is marked as being properly initialized regardless
3425 -- of whether the initialization of Ctrl_Trans succeeded. Since
3426 -- a failed initialization may leave Temp with a value of null,
3427 -- add a guard to handle this case:
3428
3429 -- if Obj /= null then
3430 -- <object finalization statements>
3431 -- end if;
df3e68b1 3432
3cebd1c0 3433 if Nkind (Status_Flag_Or_Transient_Decl (Obj_Id)) =
2a290fec 3434 N_Object_Declaration
3cebd1c0 3435 then
35a1c212
AC
3436 Fin_Stmts := New_List (
3437 Make_If_Statement (Loc,
3438 Condition =>
3439 Make_Op_Ne (Loc,
e4494292 3440 Left_Opnd => New_Occurrence_Of (Obj_Id, Loc),
35a1c212 3441 Right_Opnd => Make_Null (Loc)),
35a1c212 3442 Then_Statements => Fin_Stmts));
3cebd1c0 3443
2a290fec
AC
3444 -- Return objects use a flag to aid in processing their
3445 -- potential finalization when the enclosing function fails
3446 -- to return properly. Generate:
3cebd1c0
AC
3447
3448 -- if not Flag then
3449 -- <object finalization statements>
3450 -- end if;
3451
3452 else
3453 Fin_Stmts := New_List (
3454 Make_If_Statement (Loc,
3455 Condition =>
3456 Make_Op_Not (Loc,
3457 Right_Opnd =>
e4494292 3458 New_Occurrence_Of
3cebd1c0
AC
3459 (Status_Flag_Or_Transient_Decl (Obj_Id), Loc)),
3460
3461 Then_Statements => Fin_Stmts));
35a1c212 3462 end if;
df3e68b1
HK
3463 end if;
3464 end if;
3465
3466 Append_List_To (Finalizer_Stmts, Fin_Stmts);
3467
3468 -- Since the declarations are examined in reverse, the state counter
cfae2bed 3469 -- must be decremented in order to keep with the true position of
df3e68b1
HK
3470 -- objects.
3471
3472 Counter_Val := Counter_Val - 1;
3473 end Process_Object_Declaration;
3474
26e7e1a0
AC
3475 -------------------------------------
3476 -- Process_Tagged_Type_Declaration --
3477 -------------------------------------
3478
3479 procedure Process_Tagged_Type_Declaration (Decl : Node_Id) is
3480 Typ : constant Entity_Id := Defining_Identifier (Decl);
3481 DT_Ptr : constant Entity_Id :=
3482 Node (First_Elmt (Access_Disp_Table (Typ)));
3483 begin
3484 -- Generate:
3485 -- Ada.Tags.Unregister_Tag (<Typ>P);
3486
3487 Append_To (Tagged_Type_Stmts,
3488 Make_Procedure_Call_Statement (Loc,
886b5a18 3489 Name =>
e4494292 3490 New_Occurrence_Of (RTE (RE_Unregister_Tag), Loc),
26e7e1a0 3491 Parameter_Associations => New_List (
e4494292 3492 New_Occurrence_Of (DT_Ptr, Loc))));
26e7e1a0
AC
3493 end Process_Tagged_Type_Declaration;
3494
a968d80d 3495 -- Start of processing for Build_Finalizer
df3e68b1
HK
3496
3497 begin
3498 Fin_Id := Empty;
3499
06b599fd 3500 -- Do not perform this expansion in SPARK mode because it is not
2bfa5484
HK
3501 -- necessary.
3502
f5da7a97 3503 if GNATprove_Mode then
2bfa5484
HK
3504 return;
3505 end if;
3506
26e7e1a0
AC
3507 -- Step 1: Extract all lists which may contain controlled objects or
3508 -- library-level tagged types.
df3e68b1
HK
3509
3510 if For_Package_Spec then
3511 Decls := Visible_Declarations (Specification (N));
3512 Priv_Decls := Private_Declarations (Specification (N));
3513
3514 -- Retrieve the package spec id
3515
3516 Spec_Id := Defining_Unit_Name (Specification (N));
3517
3518 if Nkind (Spec_Id) = N_Defining_Program_Unit_Name then
3519 Spec_Id := Defining_Identifier (Spec_Id);
3520 end if;
3521
3522 -- Accept statement, block, entry body, package body, protected body,
3523 -- subprogram body or task body.
3524
3525 else
3526 Decls := Declarations (N);
3527 HSS := Handled_Statement_Sequence (N);
3528
3529 if Present (HSS) then
3530 if Present (Statements (HSS)) then
3531 Stmts := Statements (HSS);
3532 end if;
3533
3534 if Present (At_End_Proc (HSS)) then
3535 Prev_At_End := At_End_Proc (HSS);
3536 end if;
3537 end if;
3538
3539 -- Retrieve the package spec id for package bodies
3540
3541 if For_Package_Body then
3542 Spec_Id := Corresponding_Spec (N);
3543 end if;
3544 end if;
3545
3546 -- Do not process nested packages since those are handled by the
3547 -- enclosing scope's finalizer. Do not process non-expanded package
3548 -- instantiations since those will be re-analyzed and re-expanded.
3549
3550 if For_Package
3551 and then
3552 (not Is_Library_Level_Entity (Spec_Id)
3553
36e38022
BD
3554 -- Nested packages are library level entities, but do not need to
3555 -- be processed separately.
df3e68b1 3556
36e38022 3557 or else Scope_Depth (Spec_Id) /= Uint_1
41c79d60
AC
3558 or else (Is_Generic_Instance (Spec_Id)
3559 and then Package_Instantiation (Spec_Id) /= N))
213c9dc7
AC
3560
3561 -- Still need to process package body instantiations which may
3562 -- contain objects requiring finalization.
3563
3564 and then not
3565 (For_Package_Body
3566 and then Is_Library_Level_Entity (Spec_Id)
3567 and then Is_Generic_Instance (Spec_Id))
df3e68b1
HK
3568 then
3569 return;
3570 end if;
3571
3572 -- Step 2: Object [pre]processing
3573
3574 if For_Package then
3575
3576 -- Preprocess the visible declarations now in order to obtain the
3577 -- correct number of controlled object by the time the private
3578 -- declarations are processed.
3579
3580 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3581
3582 -- From all the possible contexts, only package specifications may
3583 -- have private declarations.
3584
3585 if For_Package_Spec then
3586 Process_Declarations
3587 (Priv_Decls, Preprocess => True, Top_Level => True);
87729e5a 3588 end if;
df3e68b1 3589
87729e5a
AC
3590 -- The current context may lack controlled objects, but require some
3591 -- other form of completion (task termination for instance). In such
3592 -- cases, the finalizer must be created and carry the additional
3593 -- statements.
df3e68b1 3594
0319cacc 3595 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
87729e5a 3596 Build_Components;
df3e68b1
HK
3597 end if;
3598
26e7e1a0
AC
3599 -- The preprocessing has determined that the context has controlled
3600 -- objects or library-level tagged types.
87729e5a 3601
0319cacc
AC
3602 if Has_Ctrl_Objs or Has_Tagged_Types then
3603
87729e5a
AC
3604 -- Private declarations are processed first in order to preserve
3605 -- possible dependencies between public and private objects.
3606
3607 if For_Package_Spec then
3608 Process_Declarations (Priv_Decls);
3609 end if;
3610
df3e68b1
HK
3611 Process_Declarations (Decls);
3612 end if;
3613
3614 -- Non-package case
3615
3616 else
3617 -- Preprocess both declarations and statements
3618
3619 Process_Declarations (Decls, Preprocess => True, Top_Level => True);
3620 Process_Declarations (Stmts, Preprocess => True, Top_Level => True);
3621
3622 -- At this point it is known that N has controlled objects. Ensure
3623 -- that N has a declarative list since the finalizer spec will be
3624 -- attached to it.
3625
cfae2bed 3626 if Has_Ctrl_Objs and then No (Decls) then
df3e68b1
HK
3627 Set_Declarations (N, New_List);
3628 Decls := Declarations (N);
3629 Spec_Decls := Decls;
3630 end if;
3631
3632 -- The current context may lack controlled objects, but require some
3633 -- other form of completion (task termination for instance). In such
3634 -- cases, the finalizer must be created and carry the additional
3635 -- statements.
3636
0319cacc 3637 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
df3e68b1
HK
3638 Build_Components;
3639 end if;
3640
0319cacc 3641 if Has_Ctrl_Objs or Has_Tagged_Types then
df3e68b1
HK
3642 Process_Declarations (Stmts);
3643 Process_Declarations (Decls);
3644 end if;
3645 end if;
3646
3647 -- Step 3: Finalizer creation
3648
213c9dc7 3649 if Acts_As_Clean or Has_Ctrl_Objs or Has_Tagged_Types then
df3e68b1
HK
3650 Create_Finalizer;
3651 end if;
a968d80d 3652 end Build_Finalizer;
df3e68b1
HK
3653
3654 --------------------------
3655 -- Build_Finalizer_Call --
3656 --------------------------
3657
3658 procedure Build_Finalizer_Call (N : Node_Id; Fin_Id : Entity_Id) is
df3e68b1 3659 begin
06b599fd 3660 -- Do not perform this expansion in SPARK mode because we do not create
2bfa5484
HK
3661 -- finalizers in the first place.
3662
f5da7a97 3663 if GNATprove_Mode then
2bfa5484
HK
3664 return;
3665 end if;
3666
df3e68b1 3667 -- If the construct to be cleaned up is a protected subprogram body, the
6a91be29 3668 -- finalizer call needs to be associated with the block that wraps the
df3e68b1
HK
3669 -- unprotected version of the subprogram. The following illustrates this
3670 -- scenario:
886b5a18 3671
df3e68b1
HK
3672 -- procedure Prot_SubpP is
3673 -- procedure finalizer is
3674 -- begin
3675 -- Service_Entries (Prot_Obj);
3676 -- Abort_Undefer;
3677 -- end finalizer;
886b5a18 3678
df3e68b1
HK
3679 -- begin
3680 -- . . .
3681 -- begin
3682 -- Prot_SubpN (Prot_Obj);
3683 -- at end
3684 -- finalizer;
3685 -- end;
3686 -- end Prot_SubpP;
3687
6d16658d
BD
3688 declare
3689 Loc : constant Source_Ptr := Sloc (N);
795d0063 3690
6d16658d
BD
3691 Is_Protected_Subp_Body : constant Boolean :=
3692 Nkind (N) = N_Subprogram_Body
3693 and then Is_Protected_Subprogram_Body (N);
3694 -- True if N is the protected version of a subprogram that belongs to
3695 -- a protected type.
3696
3697 HSS : constant Node_Id :=
3698 (if Is_Protected_Subp_Body
3699 then Handled_Statement_Sequence
3700 (Last (Statements (Handled_Statement_Sequence (N))))
3701 else Handled_Statement_Sequence (N));
3702
3703 -- We attach the At_End_Proc to the HSS if this is an accept
3704 -- statement or extended return statement. Also in the case of
3705 -- a protected subprogram, because if Service_Entries raises an
3706 -- exception, we do not lock the PO, so we also do not want to
3707 -- unlock it.
3708
3709 Use_HSS : constant Boolean :=
3710 Nkind (N) in N_Accept_Statement | N_Extended_Return_Statement
3711 or else Is_Protected_Subp_Body;
3712
3713 At_End_Proc_Bearer : constant Node_Id := (if Use_HSS then HSS else N);
3714 begin
3715 pragma Assert (No (At_End_Proc (At_End_Proc_Bearer)));
3716 Set_At_End_Proc (At_End_Proc_Bearer, New_Occurrence_Of (Fin_Id, Loc));
3717 -- Attach reference to finalizer to tree, for LLVM use
3718 Set_Parent (At_End_Proc (At_End_Proc_Bearer), At_End_Proc_Bearer);
3719 Analyze (At_End_Proc (At_End_Proc_Bearer));
3720 Expand_At_End_Handler (At_End_Proc_Bearer, Empty);
3721 end;
df3e68b1
HK
3722 end Build_Finalizer_Call;
3723
3724 ---------------------
3725 -- Build_Late_Proc --
3726 ---------------------
3727
3728 procedure Build_Late_Proc (Typ : Entity_Id; Nam : Name_Id) is
3729 begin
3730 for Final_Prim in Name_Of'Range loop
3731 if Name_Of (Final_Prim) = Nam then
3732 Set_TSS (Typ,
cfae2bed
AC
3733 Make_Deep_Proc
3734 (Prim => Final_Prim,
3735 Typ => Typ,
3736 Stmts => Make_Deep_Record_Body (Final_Prim, Typ)));
df3e68b1
HK
3737 end if;
3738 end loop;
3739 end Build_Late_Proc;
3740
3741 -------------------------------
3742 -- Build_Object_Declarations --
3743 -------------------------------
3744
36b8f95f
AC
3745 procedure Build_Object_Declarations
3746 (Data : out Finalization_Exception_Data;
3747 Decls : List_Id;
3748 Loc : Source_Ptr;
3749 For_Package : Boolean := False)
df3e68b1 3750 is
e2bc5465
AC
3751 Decl : Node_Id;
3752
3753 Dummy : Entity_Id;
e2bc5465
AC
3754 -- This variable captures an unused dummy internal entity, see the
3755 -- comment associated with its use.
df3e68b1
HK
3756
3757 begin
36b8f95f
AC
3758 pragma Assert (Decls /= No_List);
3759
2d1debf8
AC
3760 -- Always set the proper location as it may be needed even when
3761 -- exception propagation is forbidden.
3762
3763 Data.Loc := Loc;
3764
df3e68b1 3765 if Restriction_Active (No_Exception_Propagation) then
2d1debf8
AC
3766 Data.Abort_Id := Empty;
3767 Data.E_Id := Empty;
36b8f95f
AC
3768 Data.Raised_Id := Empty;
3769 return;
df3e68b1
HK
3770 end if;
3771
36b8f95f 3772 Data.Raised_Id := Make_Temporary (Loc, 'R');
824e9320
AC
3773
3774 -- In certain scenarios, finalization can be triggered by an abort. If
3775 -- the finalization itself fails and raises an exception, the resulting
3776 -- Program_Error must be supressed and replaced by an abort signal. In
3777 -- order to detect this scenario, save the state of entry into the
3778 -- finalization code.
f9ad6b62 3779
e2bc5465
AC
3780 -- This is not needed for library-level finalizers as they are called by
3781 -- the environment task and cannot be aborted.
276e7ed0 3782
535a8637 3783 if not For_Package then
e2bc5465
AC
3784 if Abort_Allowed then
3785 Data.Abort_Id := Make_Temporary (Loc, 'A');
23adb371 3786
e2bc5465
AC
3787 -- Generate:
3788 -- Abort_Id : constant Boolean := <A_Expr>;
824e9320 3789
e2bc5465
AC
3790 Append_To (Decls,
3791 Make_Object_Declaration (Loc,
3792 Defining_Identifier => Data.Abort_Id,
3793 Constant_Present => True,
3794 Object_Definition =>
3795 New_Occurrence_Of (Standard_Boolean, Loc),
3796 Expression =>
3797 New_Occurrence_Of (RTE (RE_Triggered_By_Abort), Loc)));
799d0e05 3798
e2bc5465 3799 -- Abort is not required
23adb371 3800
e2bc5465
AC
3801 else
3802 -- Generate a dummy entity to ensure that the internal symbols are
3803 -- in sync when a unit is compiled with and without aborts.
f9ad6b62 3804
e2bc5465
AC
3805 Dummy := Make_Temporary (Loc, 'A');
3806 Data.Abort_Id := Empty;
3807 end if;
23adb371 3808
535a8637 3809 -- Library-level finalizers
e2bc5465
AC
3810
3811 else
3812 Data.Abort_Id := Empty;
f9ad6b62
AC
3813 end if;
3814
23adb371 3815 if Exception_Extra_Info then
e2bc5465 3816 Data.E_Id := Make_Temporary (Loc, 'E');
824e9320 3817
23adb371
AC
3818 -- Generate:
3819 -- E_Id : Exception_Occurrence;
824e9320 3820
e2bc5465 3821 Decl :=
23adb371
AC
3822 Make_Object_Declaration (Loc,
3823 Defining_Identifier => Data.E_Id,
3824 Object_Definition =>
e4494292 3825 New_Occurrence_Of (RTE (RE_Exception_Occurrence), Loc));
e2bc5465 3826 Set_No_Initialization (Decl);
f9ad6b62 3827
e2bc5465 3828 Append_To (Decls, Decl);
df3e68b1 3829
23adb371 3830 else
e2bc5465 3831 Data.E_Id := Empty;
23adb371 3832 end if;
f9ad6b62 3833
824e9320
AC
3834 -- Generate:
3835 -- Raised_Id : Boolean := False;
f9ad6b62 3836
36b8f95f 3837 Append_To (Decls,
824e9320 3838 Make_Object_Declaration (Loc,
36b8f95f 3839 Defining_Identifier => Data.Raised_Id,
e4494292
RD
3840 Object_Definition => New_Occurrence_Of (Standard_Boolean, Loc),
3841 Expression => New_Occurrence_Of (Standard_False, Loc)));
bbf14e13
AC
3842
3843 if Debug_Generated_Code then
3844 Set_Debug_Info_Needed (Data.Raised_Id);
3845 end if;
df3e68b1
HK
3846 end Build_Object_Declarations;
3847
3848 ---------------------------
3849 -- Build_Raise_Statement --
3850 ---------------------------
3851
3852 function Build_Raise_Statement
36b8f95f 3853 (Data : Finalization_Exception_Data) return Node_Id
df3e68b1 3854 is
ddf67a1d 3855 Stmt : Node_Id;
23adb371 3856 Expr : Node_Id;
df3e68b1
HK
3857
3858 begin
57d3adcd 3859 -- Standard run-time use the specialized routine
14848f57 3860 -- Raise_From_Controlled_Operation.
f9ad6b62 3861
23adb371
AC
3862 if Exception_Extra_Info
3863 and then RTE_Available (RE_Raise_From_Controlled_Operation)
3864 then
ddf67a1d 3865 Stmt :=
36b8f95f 3866 Make_Procedure_Call_Statement (Data.Loc,
833eaa8a 3867 Name =>
e4494292 3868 New_Occurrence_Of
36b8f95f 3869 (RTE (RE_Raise_From_Controlled_Operation), Data.Loc),
ddf67a1d 3870 Parameter_Associations =>
e4494292 3871 New_List (New_Occurrence_Of (Data.E_Id, Data.Loc)));
e4982b64 3872
d72e7628 3873 -- Restricted run-time: exception messages are not supported and hence
14848f57
AC
3874 -- Raise_From_Controlled_Operation is not supported. Raise Program_Error
3875 -- instead.
f553e7bc 3876
df3e68b1 3877 else
ddf67a1d 3878 Stmt :=
36b8f95f 3879 Make_Raise_Program_Error (Data.Loc,
ddf67a1d 3880 Reason => PE_Finalize_Raised_Exception);
df3e68b1
HK
3881 end if;
3882
23adb371 3883 -- Generate:
799d0e05 3884
23adb371
AC
3885 -- Raised_Id and then not Abort_Id
3886 -- <or>
3887 -- Raised_Id
3888
e4494292 3889 Expr := New_Occurrence_Of (Data.Raised_Id, Data.Loc);
23adb371
AC
3890
3891 if Present (Data.Abort_Id) then
3892 Expr := Make_And_Then (Data.Loc,
3893 Left_Opnd => Expr,
3894 Right_Opnd =>
3895 Make_Op_Not (Data.Loc,
e4494292 3896 Right_Opnd => New_Occurrence_Of (Data.Abort_Id, Data.Loc)));
23adb371
AC
3897 end if;
3898
df3e68b1 3899 -- Generate:
799d0e05 3900
ca5af305 3901 -- if Raised_Id and then not Abort_Id then
ddf67a1d 3902 -- Raise_From_Controlled_Operation (E_Id);
14848f57
AC
3903 -- <or>
3904 -- raise Program_Error; -- restricted runtime
df3e68b1
HK
3905 -- end if;
3906
3907 return
36b8f95f 3908 Make_If_Statement (Data.Loc,
23adb371 3909 Condition => Expr,
ddf67a1d 3910 Then_Statements => New_List (Stmt));
df3e68b1
HK
3911 end Build_Raise_Statement;
3912
3913 -----------------------------
3914 -- Build_Record_Deep_Procs --
3915 -----------------------------
3916
3917 procedure Build_Record_Deep_Procs (Typ : Entity_Id) is
3918 begin
3919 Set_TSS (Typ,
cfae2bed
AC
3920 Make_Deep_Proc
3921 (Prim => Initialize_Case,
3922 Typ => Typ,
3923 Stmts => Make_Deep_Record_Body (Initialize_Case, Typ)));
df3e68b1 3924
51245e2d 3925 if not Is_Limited_View (Typ) then
df3e68b1 3926 Set_TSS (Typ,
cfae2bed
AC
3927 Make_Deep_Proc
3928 (Prim => Adjust_Case,
3929 Typ => Typ,
3930 Stmts => Make_Deep_Record_Body (Adjust_Case, Typ)));
df3e68b1
HK
3931 end if;
3932
d2b4b3da
AC
3933 -- Do not generate Deep_Finalize and Finalize_Address if finalization is
3934 -- suppressed since these routine will not be used.
df3e68b1 3935
d2b4b3da 3936 if not Restriction_Active (No_Finalization) then
df3e68b1 3937 Set_TSS (Typ,
cfae2bed 3938 Make_Deep_Proc
d2b4b3da 3939 (Prim => Finalize_Case,
cfae2bed 3940 Typ => Typ,
d2b4b3da
AC
3941 Stmts => Make_Deep_Record_Body (Finalize_Case, Typ)));
3942
94295b25 3943 -- Create TSS primitive Finalize_Address (unless CodePeer_Mode)
d2b4b3da 3944
89b6c83e
AC
3945 if not CodePeer_Mode then
3946 Set_TSS (Typ,
3947 Make_Deep_Proc
3948 (Prim => Address_Case,
3949 Typ => Typ,
3950 Stmts => Make_Deep_Record_Body (Address_Case, Typ)));
3951 end if;
df3e68b1
HK
3952 end if;
3953 end Build_Record_Deep_Procs;
3954
3955 -------------------
3956 -- Cleanup_Array --
3957 -------------------
3958
3959 function Cleanup_Array
3960 (N : Node_Id;
3961 Obj : Node_Id;
3962 Typ : Entity_Id) return List_Id
3963 is
3964 Loc : constant Source_Ptr := Sloc (N);
3965 Index_List : constant List_Id := New_List;
3966
3967 function Free_Component return List_Id;
3968 -- Generate the code to finalize the task or protected subcomponents
3969 -- of a single component of the array.
3970
3971 function Free_One_Dimension (Dim : Int) return List_Id;
3972 -- Generate a loop over one dimension of the array
3973
3974 --------------------
3975 -- Free_Component --
3976 --------------------
3977
3978 function Free_Component return List_Id is
3979 Stmts : List_Id := New_List;
3980 Tsk : Node_Id;
3981 C_Typ : constant Entity_Id := Component_Type (Typ);
3982
3983 begin
3984 -- Component type is known to contain tasks or protected objects
3985
3986 Tsk :=
3987 Make_Indexed_Component (Loc,
3988 Prefix => Duplicate_Subexpr_No_Checks (Obj),
3989 Expressions => Index_List);
3990
3991 Set_Etype (Tsk, C_Typ);
3992
3993 if Is_Task_Type (C_Typ) then
3994 Append_To (Stmts, Cleanup_Task (N, Tsk));
3995
3996 elsif Is_Simple_Protected_Type (C_Typ) then
3997 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
3998
3999 elsif Is_Record_Type (C_Typ) then
4000 Stmts := Cleanup_Record (N, Tsk, C_Typ);
4001
4002 elsif Is_Array_Type (C_Typ) then
4003 Stmts := Cleanup_Array (N, Tsk, C_Typ);
4004 end if;
4005
4006 return Stmts;
4007 end Free_Component;
4008
4009 ------------------------
4010 -- Free_One_Dimension --
4011 ------------------------
4012
4013 function Free_One_Dimension (Dim : Int) return List_Id is
4014 Index : Entity_Id;
4015
4016 begin
4017 if Dim > Number_Dimensions (Typ) then
4018 return Free_Component;
4019
4020 -- Here we generate the required loop
4021
4022 else
4023 Index := Make_Temporary (Loc, 'J');
e4494292 4024 Append (New_Occurrence_Of (Index, Loc), Index_List);
df3e68b1
HK
4025
4026 return New_List (
4027 Make_Implicit_Loop_Statement (N,
cfae2bed 4028 Identifier => Empty,
df3e68b1
HK
4029 Iteration_Scheme =>
4030 Make_Iteration_Scheme (Loc,
4031 Loop_Parameter_Specification =>
4032 Make_Loop_Parameter_Specification (Loc,
cfae2bed 4033 Defining_Identifier => Index,
df3e68b1
HK
4034 Discrete_Subtype_Definition =>
4035 Make_Attribute_Reference (Loc,
cfae2bed 4036 Prefix => Duplicate_Subexpr (Obj),
df3e68b1 4037 Attribute_Name => Name_Range,
cfae2bed 4038 Expressions => New_List (
df3e68b1 4039 Make_Integer_Literal (Loc, Dim))))),
eedc5882 4040 Statements => Free_One_Dimension (Dim + 1)));
df3e68b1
HK
4041 end if;
4042 end Free_One_Dimension;
4043
4044 -- Start of processing for Cleanup_Array
4045
4046 begin
4047 return Free_One_Dimension (1);
4048 end Cleanup_Array;
4049
4050 --------------------
4051 -- Cleanup_Record --
4052 --------------------
4053
4054 function Cleanup_Record
4055 (N : Node_Id;
4056 Obj : Node_Id;
4057 Typ : Entity_Id) return List_Id
4058 is
4059 Loc : constant Source_Ptr := Sloc (N);
df3e68b1
HK
4060 Stmts : constant List_Id := New_List;
4061 U_Typ : constant Entity_Id := Underlying_Type (Typ);
4062
9880061b
HK
4063 Comp : Entity_Id;
4064 Tsk : Node_Id;
4065
df3e68b1
HK
4066 begin
4067 if Has_Discriminants (U_Typ)
4068 and then Nkind (Parent (U_Typ)) = N_Full_Type_Declaration
41c79d60 4069 and then Nkind (Type_Definition (Parent (U_Typ))) = N_Record_Definition
df3e68b1
HK
4070 and then
4071 Present
cfae2bed 4072 (Variant_Part (Component_List (Type_Definition (Parent (U_Typ)))))
df3e68b1 4073 then
cfae2bed
AC
4074 -- For now, do not attempt to free a component that may appear in a
4075 -- variant, and instead issue a warning. Doing this "properly" would
4076 -- require building a case statement and would be quite a mess. Note
4077 -- that the RM only requires that free "work" for the case of a task
4078 -- access value, so already we go way beyond this in that we deal
4079 -- with the array case and non-discriminated record cases.
df3e68b1
HK
4080
4081 Error_Msg_N
685bc70f 4082 ("task/protected object in variant record will not be freed??", N);
df3e68b1
HK
4083 return New_List (Make_Null_Statement (Loc));
4084 end if;
4085
9880061b 4086 Comp := First_Component (U_Typ);
df3e68b1 4087 while Present (Comp) loop
e3102ec0
GL
4088 if Chars (Comp) /= Name_uParent
4089 and then (Has_Task (Etype (Comp))
4090 or else Has_Simple_Protected_Object (Etype (Comp)))
df3e68b1
HK
4091 then
4092 Tsk :=
4093 Make_Selected_Component (Loc,
4094 Prefix => Duplicate_Subexpr_No_Checks (Obj),
4095 Selector_Name => New_Occurrence_Of (Comp, Loc));
4096 Set_Etype (Tsk, Etype (Comp));
4097
4098 if Is_Task_Type (Etype (Comp)) then
4099 Append_To (Stmts, Cleanup_Task (N, Tsk));
4100
4101 elsif Is_Simple_Protected_Type (Etype (Comp)) then
4102 Append_To (Stmts, Cleanup_Protected_Object (N, Tsk));
4103
4104 elsif Is_Record_Type (Etype (Comp)) then
4105
9880061b
HK
4106 -- Recurse, by generating the prefix of the argument to the
4107 -- eventual cleanup call.
df3e68b1 4108
cfae2bed 4109 Append_List_To (Stmts, Cleanup_Record (N, Tsk, Etype (Comp)));
df3e68b1
HK
4110
4111 elsif Is_Array_Type (Etype (Comp)) then
cfae2bed 4112 Append_List_To (Stmts, Cleanup_Array (N, Tsk, Etype (Comp)));
df3e68b1
HK
4113 end if;
4114 end if;
4115
4116 Next_Component (Comp);
4117 end loop;
4118
4119 return Stmts;
4120 end Cleanup_Record;
4121
4122 ------------------------------
4123 -- Cleanup_Protected_Object --
4124 ------------------------------
4125
4126 function Cleanup_Protected_Object
4127 (N : Node_Id;
4128 Ref : Node_Id) return Node_Id
4129 is
4130 Loc : constant Source_Ptr := Sloc (N);
4131
4132 begin
e4982b64
AC
4133 -- For restricted run-time libraries (Ravenscar), tasks are
4134 -- non-terminating, and protected objects can only appear at library
4135 -- level, so we do not want finalization of protected objects.
4136
4137 if Restricted_Profile then
4138 return Empty;
4139
4140 else
4141 return
4142 Make_Procedure_Call_Statement (Loc,
2c1b72d7 4143 Name =>
e4494292 4144 New_Occurrence_Of (RTE (RE_Finalize_Protection), Loc),
2c1b72d7 4145 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
e4982b64 4146 end if;
df3e68b1
HK
4147 end Cleanup_Protected_Object;
4148
4149 ------------------
4150 -- Cleanup_Task --
4151 ------------------
4152
4153 function Cleanup_Task
4154 (N : Node_Id;
4155 Ref : Node_Id) return Node_Id
4156 is
fb8e3581 4157 Loc : constant Source_Ptr := Sloc (N);
2c1b72d7 4158
df3e68b1 4159 begin
e4982b64 4160 -- For restricted run-time libraries (Ravenscar), tasks are
0c506265
HK
4161 -- non-terminating and they can only appear at library level,
4162 -- so we do not want finalization of task objects.
e4982b64
AC
4163
4164 if Restricted_Profile then
4165 return Empty;
4166
4167 else
4168 return
4169 Make_Procedure_Call_Statement (Loc,
2c1b72d7 4170 Name =>
e4494292 4171 New_Occurrence_Of (RTE (RE_Free_Task), Loc),
2c1b72d7 4172 Parameter_Associations => New_List (Concurrent_Ref (Ref)));
e4982b64 4173 end if;
df3e68b1
HK
4174 end Cleanup_Task;
4175
400ad4e9 4176 --------------------------------------
86f32857 4177 -- Check_Unnesting_Elaboration_Code --
400ad4e9 4178 --------------------------------------
86f32857
ES
4179
4180 procedure Check_Unnesting_Elaboration_Code (N : Node_Id) is
f68289d8
GD
4181 Loc : constant Source_Ptr := Sloc (N);
4182 Block_Elab_Proc : Entity_Id := Empty;
4183
4184 procedure Set_Block_Elab_Proc;
4185 -- Create a defining identifier for a procedure that will replace
4186 -- a block with nested subprograms (unless it has already been created,
4187 -- in which case this is a no-op).
4188
4189 procedure Set_Block_Elab_Proc is
4190 begin
4191 if No (Block_Elab_Proc) then
a8d89c45 4192 Block_Elab_Proc := Make_Temporary (Loc, 'I');
f68289d8
GD
4193 end if;
4194 end Set_Block_Elab_Proc;
4195
4196 procedure Reset_Scopes_To_Block_Elab_Proc (L : List_Id);
4197 -- Find entities in the elaboration code of a library package body that
4198 -- contain or represent a subprogram body. A body can appear within a
4199 -- block or a loop or can appear by itself if generated for an object
4200 -- declaration that involves controlled actions. The first such entity
4201 -- forces creation of a new procedure entity (via Set_Block_Elab_Proc)
4202 -- that will be used to reset the scopes of all entities that become
4203 -- local to the new elaboration procedure. This is needed for subsequent
4204 -- unnesting actions, which depend on proper setting of the Scope links
4205 -- to determine the nesting level of each subprogram.
51f2fc7d 4206
51f2fc7d
ES
4207 -----------------------
4208 -- Find_Local_Scope --
4209 -----------------------
4210
f68289d8 4211 procedure Reset_Scopes_To_Block_Elab_Proc (L : List_Id) is
66f84da8 4212 Id : Entity_Id;
92a68a04 4213 Stat : Node_Id;
2e188579 4214 Node : Node_Id;
51f2fc7d
ES
4215
4216 begin
4217 Stat := First (L);
4218 while Present (Stat) loop
4219 case Nkind (Stat) is
4220 when N_Block_Statement =>
2e188579
AC
4221 if Present (Identifier (Stat)) then
4222 Id := Entity (Identifier (Stat));
2401c98f 4223
2e188579
AC
4224 -- The Scope of this block needs to be reset to the new
4225 -- procedure if the block contains nested subprograms.
66f84da8 4226
2e188579
AC
4227 if Present (Id) and then Contains_Subprogram (Id) then
4228 Set_Block_Elab_Proc;
4229 Set_Scope (Id, Block_Elab_Proc);
4230 end if;
51f2fc7d
ES
4231 end if;
4232
4233 when N_Loop_Statement =>
66f84da8 4234 Id := Entity (Identifier (Stat));
2401c98f 4235
f68289d8 4236 if Present (Id) and then Contains_Subprogram (Id) then
66f84da8 4237 if Scope (Id) = Current_Scope then
f68289d8
GD
4238 Set_Block_Elab_Proc;
4239 Set_Scope (Id, Block_Elab_Proc);
66f84da8 4240 end if;
51f2fc7d
ES
4241 end if;
4242
f68289d8
GD
4243 -- We traverse the loop's statements as well, which may
4244 -- include other block (etc.) statements that need to have
4245 -- their Scope set to Block_Elab_Proc. (Is this really the
4246 -- case, or do such nested blocks refer to the loop scope
4247 -- rather than the loop's enclosing scope???.)
51f2fc7d 4248
f68289d8 4249 Reset_Scopes_To_Block_Elab_Proc (Statements (Stat));
51f2fc7d 4250
f68289d8
GD
4251 when N_If_Statement =>
4252 Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Stat));
f68289d8 4253 Reset_Scopes_To_Block_Elab_Proc (Else_Statements (Stat));
51f2fc7d 4254
2e188579
AC
4255 Node := First (Elsif_Parts (Stat));
4256 while Present (Node) loop
4257 Reset_Scopes_To_Block_Elab_Proc (Then_Statements (Node));
4258 Next (Node);
4259 end loop;
51f2fc7d
ES
4260
4261 when N_Case_Statement =>
2e188579
AC
4262 Node := First (Alternatives (Stat));
4263 while Present (Node) loop
4264 Reset_Scopes_To_Block_Elab_Proc (Statements (Node));
4265 Next (Node);
4266 end loop;
51f2fc7d 4267
f68289d8
GD
4268 -- Reset the Scope of a subprogram occurring at the top level
4269
51f2fc7d 4270 when N_Subprogram_Body =>
66f84da8 4271 Id := Defining_Entity (Stat);
2401c98f 4272
f68289d8
GD
4273 Set_Block_Elab_Proc;
4274 Set_Scope (Id, Block_Elab_Proc);
51f2fc7d
ES
4275
4276 when others =>
4277 null;
4278 end case;
92a68a04 4279
51f2fc7d
ES
4280 Next (Stat);
4281 end loop;
f68289d8 4282 end Reset_Scopes_To_Block_Elab_Proc;
51f2fc7d 4283
f2c2cdfb
HK
4284 -- Local variables
4285
66f84da8 4286 H_Seq : constant Node_Id := Handled_Statement_Sequence (N);
f2c2cdfb
HK
4287 Elab_Body : Node_Id;
4288 Elab_Call : Node_Id;
f2c2cdfb
HK
4289
4290 -- Start of processing for Check_Unnesting_Elaboration_Code
4291
86f32857 4292 begin
f68289d8
GD
4293 if Present (H_Seq) then
4294 Reset_Scopes_To_Block_Elab_Proc (Statements (H_Seq));
66f84da8 4295
f68289d8 4296 -- There may be subprograms declared in the exception handlers
66f84da8
ES
4297 -- of the current body.
4298
f68289d8 4299 if Present (Exception_Handlers (H_Seq)) then
66f84da8
ES
4300 declare
4301 Handler : Node_Id := First (Exception_Handlers (H_Seq));
4302 begin
4303 while Present (Handler) loop
f68289d8 4304 Reset_Scopes_To_Block_Elab_Proc (Statements (Handler));
66f84da8
ES
4305
4306 Next (Handler);
4307 end loop;
4308 end;
4309 end if;
86f32857 4310
f68289d8 4311 if Present (Block_Elab_Proc) then
0c506265
HK
4312 Elab_Body :=
4313 Make_Subprogram_Body (Loc,
4314 Specification =>
4315 Make_Procedure_Specification (Loc,
f68289d8 4316 Defining_Unit_Name => Block_Elab_Proc),
0c506265
HK
4317 Declarations => New_List,
4318 Handled_Statement_Sequence =>
4319 Relocate_Node (Handled_Statement_Sequence (N)));
4320
4321 Elab_Call :=
4322 Make_Procedure_Call_Statement (Loc,
f68289d8 4323 Name => New_Occurrence_Of (Block_Elab_Proc, Loc));
86f32857 4324
86f32857
ES
4325 Append_To (Declarations (N), Elab_Body);
4326 Analyze (Elab_Body);
f68289d8 4327 Set_Has_Nested_Subprogram (Block_Elab_Proc);
86f32857
ES
4328
4329 Set_Handled_Statement_Sequence (N,
0c506265
HK
4330 Make_Handled_Sequence_Of_Statements (Loc,
4331 Statements => New_List (Elab_Call)));
4332
86f32857
ES
4333 Analyze (Elab_Call);
4334
f68289d8
GD
4335 -- Could we reset the scopes of entities associated with the new
4336 -- procedure here via a loop over entities rather than doing it in
4337 -- the recursive Reset_Scopes_To_Elab_Proc procedure???
86f32857
ES
4338 end if;
4339 end if;
4340 end Check_Unnesting_Elaboration_Code;
4341
f68289d8
GD
4342 ---------------------------------------
4343 -- Check_Unnesting_In_Decls_Or_Stmts --
4344 ---------------------------------------
302319e0 4345
f68289d8
GD
4346 procedure Check_Unnesting_In_Decls_Or_Stmts (Decls_Or_Stmts : List_Id) is
4347 Decl_Or_Stmt : Node_Id;
302319e0
ES
4348
4349 begin
302319e0 4350 if Unnest_Subprogram_Mode
f68289d8 4351 and then Present (Decls_Or_Stmts)
302319e0 4352 then
f68289d8
GD
4353 Decl_Or_Stmt := First (Decls_Or_Stmts);
4354 while Present (Decl_Or_Stmt) loop
4355 if Nkind (Decl_Or_Stmt) = N_Block_Statement
4356 and then Contains_Subprogram (Entity (Identifier (Decl_Or_Stmt)))
e60c10b3 4357 then
f68289d8 4358 Unnest_Block (Decl_Or_Stmt);
e60c10b3 4359
05746958
GD
4360 -- If-statements may contain subprogram bodies at the outer level
4361 -- of their statement lists, and the subprograms may make up-level
4362 -- references (such as to objects declared in the same statement
4363 -- list). Unlike block and loop cases, however, we don't have an
4364 -- entity on which to test the Contains_Subprogram flag, so
4365 -- Unnest_If_Statement must traverse the statement lists to
4366 -- determine whether there are nested subprograms present.
4367
4368 elsif Nkind (Decl_Or_Stmt) = N_If_Statement then
4369 Unnest_If_Statement (Decl_Or_Stmt);
4370
7e536bfd
GD
4371 elsif Nkind (Decl_Or_Stmt) = N_Loop_Statement then
4372 declare
4373 Id : constant Entity_Id :=
4374 Entity (Identifier (Decl_Or_Stmt));
4375
4376 begin
4377 -- When a top-level loop within declarations of a library
4378 -- package spec or body contains nested subprograms, we wrap
4379 -- it in a procedure to handle possible up-level references
4380 -- to entities associated with the loop (such as loop
4381 -- parameters).
4382
4383 if Present (Id) and then Contains_Subprogram (Id) then
4384 Unnest_Loop (Decl_Or_Stmt);
4385 end if;
4386 end;
4387
f68289d8
GD
4388 elsif Nkind (Decl_Or_Stmt) = N_Package_Declaration
4389 and then not Modify_Tree_For_C
4390 then
4391 Check_Unnesting_In_Decls_Or_Stmts
4392 (Visible_Declarations (Specification (Decl_Or_Stmt)));
4393 Check_Unnesting_In_Decls_Or_Stmts
4394 (Private_Declarations (Specification (Decl_Or_Stmt)));
302319e0 4395
f68289d8
GD
4396 elsif Nkind (Decl_Or_Stmt) = N_Package_Body
4397 and then not Modify_Tree_For_C
4398 then
4399 Check_Unnesting_In_Decls_Or_Stmts (Declarations (Decl_Or_Stmt));
4400 if Present (Statements
4401 (Handled_Statement_Sequence (Decl_Or_Stmt)))
4402 then
4403 Check_Unnesting_In_Decls_Or_Stmts (Statements
4404 (Handled_Statement_Sequence (Decl_Or_Stmt)));
4405 Check_Unnesting_In_Handlers (Decl_Or_Stmt);
4406 end if;
302319e0
ES
4407 end if;
4408
f68289d8 4409 Next (Decl_Or_Stmt);
302319e0
ES
4410 end loop;
4411 end if;
f68289d8
GD
4412 end Check_Unnesting_In_Decls_Or_Stmts;
4413
4414 ---------------------------------
4415 -- Check_Unnesting_In_Handlers --
4416 ---------------------------------
4417
4418 procedure Check_Unnesting_In_Handlers (N : Node_Id) is
4419 Stmt_Seq : constant Node_Id := Handled_Statement_Sequence (N);
4420
4421 begin
4422 if Present (Stmt_Seq)
4423 and then Present (Exception_Handlers (Stmt_Seq))
4424 then
4425 declare
4426 Handler : Node_Id := First (Exception_Handlers (Stmt_Seq));
4427 begin
4428 while Present (Handler) loop
4429 if Present (Statements (Handler)) then
4430 Check_Unnesting_In_Decls_Or_Stmts (Statements (Handler));
4431 end if;
4432
4433 Next (Handler);
4434 end loop;
4435 end;
4436 end if;
4437 end Check_Unnesting_In_Handlers;
302319e0 4438
df3e68b1
HK
4439 ------------------------------
4440 -- Check_Visibly_Controlled --
4441 ------------------------------
4442
4443 procedure Check_Visibly_Controlled
4444 (Prim : Final_Primitives;
4445 Typ : Entity_Id;
4446 E : in out Entity_Id;
4447 Cref : in out Node_Id)
4448 is
4449 Parent_Type : Entity_Id;
4450 Op : Entity_Id;
4451
4452 begin
4453 if Is_Derived_Type (Typ)
4454 and then Comes_From_Source (E)
7d0d27d9 4455 and then No (Overridden_Operation (E))
df3e68b1
HK
4456 then
4457 -- We know that the explicit operation on the type does not override
4458 -- the inherited operation of the parent, and that the derivation
4459 -- is from a private type that is not visibly controlled.
4460
4461 Parent_Type := Etype (Typ);
ca811241 4462 Op := Find_Optional_Prim_Op (Parent_Type, Name_Of (Prim));
df3e68b1
HK
4463
4464 if Present (Op) then
4465 E := Op;
4466
4467 -- Wrap the object to be initialized into the proper
4468 -- unchecked conversion, to be compatible with the operation
4469 -- to be called.
4470
4471 if Nkind (Cref) = N_Unchecked_Type_Conversion then
4472 Cref := Unchecked_Convert_To (Parent_Type, Expression (Cref));
4473 else
4474 Cref := Unchecked_Convert_To (Parent_Type, Cref);
4475 end if;
4476 end if;
4477 end if;
4478 end Check_Visibly_Controlled;
4479
e60c10b3
ES
4480 --------------------------
4481 -- Contains_Subprogram --
4482 --------------------------
4483
4484 function Contains_Subprogram (Blk : Entity_Id) return Boolean is
4485 E : Entity_Id;
4486
4487 begin
4488 E := First_Entity (Blk);
4489
4490 while Present (E) loop
4491 if Is_Subprogram (E) then
4492 return True;
4493
4a08c95c 4494 elsif Ekind (E) in E_Block | E_Loop
e60c10b3
ES
4495 and then Contains_Subprogram (E)
4496 then
4497 return True;
4498 end if;
4499
4500 Next_Entity (E);
4501 end loop;
4502
4503 return False;
4504 end Contains_Subprogram;
4505
df3e68b1
HK
4506 ------------------
4507 -- Convert_View --
4508 ------------------
4509
4510 function Convert_View
4511 (Proc : Entity_Id;
4512 Arg : Node_Id;
4513 Ind : Pos := 1) return Node_Id
4514 is
4515 Fent : Entity_Id := First_Entity (Proc);
4516 Ftyp : Entity_Id;
4517 Atyp : Entity_Id;
4518
4519 begin
4520 for J in 2 .. Ind loop
4521 Next_Entity (Fent);
4522 end loop;
4523
4524 Ftyp := Etype (Fent);
4525
4a08c95c 4526 if Nkind (Arg) in N_Type_Conversion | N_Unchecked_Type_Conversion then
df3e68b1
HK
4527 Atyp := Entity (Subtype_Mark (Arg));
4528 else
4529 Atyp := Etype (Arg);
4530 end if;
4531
4532 if Is_Abstract_Subprogram (Proc) and then Is_Tagged_Type (Ftyp) then
4533 return Unchecked_Convert_To (Class_Wide_Type (Ftyp), Arg);
4534
4535 elsif Ftyp /= Atyp
4536 and then Present (Atyp)
cfae2bed
AC
4537 and then (Is_Private_Type (Ftyp) or else Is_Private_Type (Atyp))
4538 and then Base_Type (Underlying_Type (Atyp)) =
4539 Base_Type (Underlying_Type (Ftyp))
df3e68b1
HK
4540 then
4541 return Unchecked_Convert_To (Ftyp, Arg);
4542
4543 -- If the argument is already a conversion, as generated by
4544 -- Make_Init_Call, set the target type to the type of the formal
4545 -- directly, to avoid spurious typing problems.
4546
4a08c95c 4547 elsif Nkind (Arg) in N_Unchecked_Type_Conversion | N_Type_Conversion
df3e68b1
HK
4548 and then not Is_Class_Wide_Type (Atyp)
4549 then
4550 Set_Subtype_Mark (Arg, New_Occurrence_Of (Ftyp, Sloc (Arg)));
4551 Set_Etype (Arg, Ftyp);
4552 return Arg;
4553
3c756b76
AC
4554 -- Otherwise, introduce a conversion when the designated object
4555 -- has a type derived from the formal of the controlled routine.
4556
4557 elsif Is_Private_Type (Ftyp)
4558 and then Present (Atyp)
4559 and then Is_Derived_Type (Underlying_Type (Base_Type (Atyp)))
4560 then
4561 return Unchecked_Convert_To (Ftyp, Arg);
4562
df3e68b1
HK
4563 else
4564 return Arg;
4565 end if;
4566 end Convert_View;
4567
df3e68b1
HK
4568 -------------------------------
4569 -- Establish_Transient_Scope --
4570 -------------------------------
4571
4572 -- This procedure is called each time a transient block has to be inserted
4573 -- that is to say for each call to a function with unconstrained or tagged
d4dfb005 4574 -- result. It creates a new scope on the scope stack in order to enclose
8fdafe44 4575 -- all transient variables generated.
df3e68b1 4576
6560f851
HK
4577 procedure Establish_Transient_Scope
4578 (N : Node_Id;
4579 Manage_Sec_Stack : Boolean)
4580 is
f037632e
BD
4581 function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean;
4582 -- Determine whether arbitrary Id denotes a package or subprogram [body]
4583
4584 function Find_Enclosing_Transient_Scope return Entity_Id;
4585 -- Examine the scope stack looking for the nearest enclosing transient
4586 -- scope within the innermost enclosing package or subprogram. Return
4587 -- Empty if no such scope exists.
4588
4589 function Find_Transient_Context (N : Node_Id) return Node_Id;
4590 -- Locate a suitable context for arbitrary node N which may need to be
4591 -- serviced by a transient scope. Return Empty if no suitable context
4592 -- is available.
df3e68b1 4593
6560f851
HK
4594 procedure Delegate_Sec_Stack_Management;
4595 -- Move the management of the secondary stack to the nearest enclosing
4596 -- suitable scope.
df3e68b1 4597
f037632e
BD
4598 procedure Create_Transient_Scope (Context : Node_Id);
4599 -- Place a new scope on the scope stack in order to service construct
4600 -- Context. Context is the node found by Find_Transient_Context. The
4601 -- new scope may also manage the secondary stack.
df3e68b1 4602
6560f851
HK
4603 ----------------------------
4604 -- Create_Transient_Scope --
4605 ----------------------------
df3e68b1 4606
f037632e 4607 procedure Create_Transient_Scope (Context : Node_Id) is
6560f851 4608 Loc : constant Source_Ptr := Sloc (N);
df3e68b1 4609
6560f851 4610 Iter_Loop : Entity_Id;
f037632e
BD
4611 Trans_Scop : constant Entity_Id :=
4612 New_Internal_Entity (E_Block, Current_Scope, Loc, 'B');
406935b6 4613
6560f851 4614 begin
6560f851 4615 Set_Etype (Trans_Scop, Standard_Void_Type);
7edfb4c6 4616
f037632e
BD
4617 -- Push a new scope, and set its Node_To_Be_Wrapped and Is_Transient
4618 -- fields.
4619
6560f851 4620 Push_Scope (Trans_Scop);
f037632e 4621 Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped := Context;
df3e68b1
HK
4622 Set_Scope_Is_Transient;
4623
6560f851 4624 -- The transient scope must also manage the secondary stack
7edfb4c6 4625
6560f851
HK
4626 if Manage_Sec_Stack then
4627 Set_Uses_Sec_Stack (Trans_Scop);
df3e68b1 4628 Check_Restriction (No_Secondary_Stack, N);
7edfb4c6
HK
4629
4630 -- The expansion of iterator loops generates references to objects
4631 -- in order to extract elements from a container:
4632
4633 -- Ref : Reference_Type_Ptr := Reference (Container, Cursor);
4634 -- Obj : <object type> renames Ref.all.Element.all;
4635
4636 -- These references are controlled and returned on the secondary
4637 -- stack. A new reference is created at each iteration of the loop
4638 -- and as a result it must be finalized and the space occupied by
4639 -- it on the secondary stack reclaimed at the end of the current
4640 -- iteration.
4641
4642 -- When the context that requires a transient scope is a call to
4643 -- routine Reference, the node to be wrapped is the source object:
4644
4645 -- for Obj of Container loop
4646
2a5ec8e6
BD
4647 -- Routine Wrap_Transient_Declaration however does not generate
4648 -- a physical block as wrapping a declaration will kill it too
4649 -- early. To handle this peculiar case, mark the related iterator
4650 -- loop as requiring the secondary stack. This signals the
4651 -- finalization machinery to manage the secondary stack (see
4652 -- routine Process_Statements_For_Controlled_Objects).
7edfb4c6 4653
6560f851 4654 Iter_Loop := Find_Enclosing_Iterator_Loop (Trans_Scop);
7edfb4c6
HK
4655
4656 if Present (Iter_Loop) then
4657 Set_Uses_Sec_Stack (Iter_Loop);
4658 end if;
df3e68b1
HK
4659 end if;
4660
df3e68b1
HK
4661 if Debug_Flag_W then
4662 Write_Str (" <Transient>");
4663 Write_Eol;
4664 end if;
6560f851
HK
4665 end Create_Transient_Scope;
4666
4667 -----------------------------------
4668 -- Delegate_Sec_Stack_Management --
4669 -----------------------------------
4670
4671 procedure Delegate_Sec_Stack_Management is
6560f851
HK
4672 begin
4673 for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop
f037632e
BD
4674 declare
4675 Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index);
4676 begin
4677 -- Prevent the search from going too far or within the scope
4678 -- space of another unit.
6560f851 4679
f037632e
BD
4680 if Scope.Entity = Standard_Standard then
4681 return;
6560f851 4682
f037632e
BD
4683 -- No transient scope should be encountered during the
4684 -- traversal because Establish_Transient_Scope should have
4685 -- already handled this case.
6560f851 4686
f037632e
BD
4687 elsif Scope.Is_Transient then
4688 raise Program_Error;
6560f851 4689
f037632e
BD
4690 -- The construct that requires secondary stack management is
4691 -- always enclosed by a package or subprogram scope.
6560f851 4692
f037632e
BD
4693 elsif Is_Package_Or_Subprogram (Scope.Entity) then
4694 Set_Uses_Sec_Stack (Scope.Entity);
4695 Check_Restriction (No_Secondary_Stack, N);
6560f851 4696
f037632e
BD
4697 return;
4698 end if;
4699 end;
6560f851
HK
4700 end loop;
4701
4702 -- At this point no suitable scope was found. This should never occur
4703 -- because a construct is always enclosed by a compilation unit which
4704 -- has a scope.
4705
4706 pragma Assert (False);
4707 end Delegate_Sec_Stack_Management;
4708
4709 ------------------------------------
4710 -- Find_Enclosing_Transient_Scope --
4711 ------------------------------------
4712
4713 function Find_Enclosing_Transient_Scope return Entity_Id is
6560f851
HK
4714 begin
4715 for Index in reverse Scope_Stack.First .. Scope_Stack.Last loop
f037632e
BD
4716 declare
4717 Scope : Scope_Stack_Entry renames Scope_Stack.Table (Index);
4718 begin
4719 -- Prevent the search from going too far or within the scope
4720 -- space of another unit.
6560f851 4721
f037632e
BD
4722 if Scope.Entity = Standard_Standard
4723 or else Is_Package_Or_Subprogram (Scope.Entity)
4724 then
4725 exit;
6560f851 4726
f037632e
BD
4727 elsif Scope.Is_Transient then
4728 return Scope.Entity;
4729 end if;
4730 end;
6560f851
HK
4731 end loop;
4732
4733 return Empty;
4734 end Find_Enclosing_Transient_Scope;
4735
f037632e
BD
4736 ----------------------------
4737 -- Find_Transient_Context --
4738 ----------------------------
4739
4740 function Find_Transient_Context (N : Node_Id) return Node_Id is
4741 Curr : Node_Id := N;
4742 Prev : Node_Id := Empty;
4743
4744 begin
4745 while Present (Curr) loop
4746 case Nkind (Curr) is
4747
4748 -- Declarations
4749
4750 -- Declarations act as a boundary for a transient scope even if
4751 -- they are not wrapped, see Wrap_Transient_Declaration.
4752
4753 when N_Object_Declaration
4754 | N_Object_Renaming_Declaration
4755 | N_Subtype_Declaration
4756 =>
4757 return Curr;
4758
4759 -- Statements
4760
4761 -- Statements and statement-like constructs act as a boundary
4762 -- for a transient scope.
4763
4764 when N_Accept_Alternative
4765 | N_Attribute_Definition_Clause
4766 | N_Case_Statement
4767 | N_Case_Statement_Alternative
4768 | N_Code_Statement
4769 | N_Delay_Alternative
4770 | N_Delay_Until_Statement
4771 | N_Delay_Relative_Statement
4772 | N_Discriminant_Association
4773 | N_Elsif_Part
4774 | N_Entry_Body_Formal_Part
4775 | N_Exit_Statement
4776 | N_If_Statement
4777 | N_Iteration_Scheme
4778 | N_Terminate_Alternative
4779 =>
4780 pragma Assert (Present (Prev));
4781 return Prev;
4782
4783 when N_Assignment_Statement =>
4784 return Curr;
4785
4786 when N_Entry_Call_Statement
4787 | N_Procedure_Call_Statement
4788 =>
4789 -- When an entry or procedure call acts as the alternative
4790 -- of a conditional or timed entry call, the proper context
4791 -- is that of the alternative.
4792
4793 if Nkind (Parent (Curr)) = N_Entry_Call_Alternative
4794 and then Nkind (Parent (Parent (Curr))) in
4795 N_Conditional_Entry_Call | N_Timed_Entry_Call
4796 then
4797 return Parent (Parent (Curr));
4798
4799 -- General case for entry or procedure calls
4800
4801 else
4802 return Curr;
4803 end if;
4804
4805 when N_Pragma =>
4806
4807 -- Pragma Check is not a valid transient context in
4808 -- GNATprove mode because the pragma must remain unchanged.
4809
4810 if GNATprove_Mode
4811 and then Get_Pragma_Id (Curr) = Pragma_Check
4812 then
4813 return Empty;
4814
4815 -- General case for pragmas
4816
4817 else
4818 return Curr;
4819 end if;
4820
4821 when N_Raise_Statement =>
4822 return Curr;
4823
4824 when N_Simple_Return_Statement =>
4825
4826 -- A return statement is not a valid transient context when
4827 -- the function itself requires transient scope management
4828 -- because the result will be reclaimed too early.
4829
4830 if Requires_Transient_Scope (Etype
4831 (Return_Applies_To (Return_Statement_Entity (Curr))))
4832 then
4833 return Empty;
4834
4835 -- General case for return statements
4836
4837 else
4838 return Curr;
4839 end if;
4840
4841 -- Special
4842
4843 when N_Attribute_Reference =>
4844 if Is_Procedure_Attribute_Name (Attribute_Name (Curr)) then
4845 return Curr;
4846 end if;
4847
4848 -- An Ada 2012 iterator specification is not a valid context
4849 -- because Analyze_Iterator_Specification already employs
4850 -- special processing for it.
4851
4852 when N_Iterator_Specification =>
4853 return Empty;
4854
4855 when N_Loop_Parameter_Specification =>
4856
4857 -- An iteration scheme is not a valid context because
4858 -- routine Analyze_Iteration_Scheme already employs
4859 -- special processing.
4860
4861 if Nkind (Parent (Curr)) = N_Iteration_Scheme then
4862 return Empty;
4863 else
4864 return Parent (Curr);
4865 end if;
4866
4867 -- Termination
4868
4869 -- The following nodes represent "dummy contexts" which do not
4870 -- need to be wrapped.
4871
4872 when N_Component_Declaration
4873 | N_Discriminant_Specification
4874 | N_Parameter_Specification
4875 =>
4876 return Empty;
4877
4878 -- If the traversal leaves a scope without having been able to
4879 -- find a construct to wrap, something is going wrong, but this
4880 -- can happen in error situations that are not detected yet
4881 -- (such as a dynamic string in a pragma Export).
4882
4883 when N_Block_Statement
4884 | N_Entry_Body
4885 | N_Package_Body
4886 | N_Package_Declaration
4887 | N_Protected_Body
4888 | N_Subprogram_Body
4889 | N_Task_Body
4890 =>
4891 return Empty;
4892
4893 -- Default
4894
4895 when others =>
4896 null;
4897 end case;
4898
4899 Prev := Curr;
4900 Curr := Parent (Curr);
4901 end loop;
4902
4903 return Empty;
4904 end Find_Transient_Context;
4905
6560f851
HK
4906 ------------------------------
4907 -- Is_Package_Or_Subprogram --
4908 ------------------------------
4909
4910 function Is_Package_Or_Subprogram (Id : Entity_Id) return Boolean is
4911 begin
4a08c95c
AC
4912 return Ekind (Id) in E_Entry
4913 | E_Entry_Family
4914 | E_Function
4915 | E_Package
4916 | E_Procedure
4917 | E_Subprogram_Body;
6560f851
HK
4918 end Is_Package_Or_Subprogram;
4919
4920 -- Local variables
4921
66c0fa2c
HK
4922 Trans_Id : constant Entity_Id := Find_Enclosing_Transient_Scope;
4923 Context : Node_Id;
6560f851
HK
4924
4925 -- Start of processing for Establish_Transient_Scope
4926
4927 begin
f037632e
BD
4928 -- Do not create a new transient scope if there is already an enclosing
4929 -- transient scope within the innermost enclosing package or subprogram.
6560f851 4930
66c0fa2c 4931 if Present (Trans_Id) then
6560f851
HK
4932
4933 -- If the transient scope was requested for purposes of managing the
4934 -- secondary stack, then the existing scope must perform this task.
4935
4936 if Manage_Sec_Stack then
66c0fa2c 4937 Set_Uses_Sec_Stack (Trans_Id);
6560f851
HK
4938 end if;
4939
4940 return;
4941 end if;
4942
f037632e
BD
4943 -- Find the construct that must be serviced by a new transient scope, if
4944 -- it exists.
6560f851 4945
66c0fa2c
HK
4946 Context := Find_Transient_Context (N);
4947
4948 if Present (Context) then
4949 if Nkind (Context) = N_Assignment_Statement then
6560f851 4950
66c0fa2c
HK
4951 -- An assignment statement with suppressed controlled semantics
4952 -- does not need a transient scope because finalization is not
4953 -- desirable at this point. Note that No_Ctrl_Actions is also
4954 -- set for non-controlled assignments to suppress dispatching
4955 -- _assign.
6560f851 4956
66c0fa2c
HK
4957 if No_Ctrl_Actions (Context)
4958 and then Needs_Finalization (Etype (Name (Context)))
4959 then
4960 -- When a controlled component is initialized by a function
4961 -- call, the result on the secondary stack is always assigned
4962 -- to the component. Signal the nearest suitable scope that it
4963 -- is safe to manage the secondary stack.
6560f851 4964
66c0fa2c
HK
4965 if Manage_Sec_Stack and then Within_Init_Proc then
4966 Delegate_Sec_Stack_Management;
4967 end if;
4968
4969 -- Otherwise the assignment is a normal transient context and thus
4970 -- requires a transient scope.
4971
4972 else
4973 Create_Transient_Scope (Context);
4974 end if;
4975
4976 -- General case
4977
4978 else
4979 Create_Transient_Scope (Context);
4980 end if;
df3e68b1
HK
4981 end if;
4982 end Establish_Transient_Scope;
4983
4984 ----------------------------
4985 -- Expand_Cleanup_Actions --
4986 ----------------------------
4987
4988 procedure Expand_Cleanup_Actions (N : Node_Id) is
4a08c95c
AC
4989 pragma Assert
4990 (Nkind (N) in N_Block_Statement
4a08c95c 4991 | N_Subprogram_Body
6a91be29
BD
4992 | N_Task_Body
4993 | N_Entry_Body
4994 | N_Extended_Return_Statement);
40c21e91 4995
df3e68b1
HK
4996 Scop : constant Entity_Id := Current_Scope;
4997
85be939e
AC
4998 Is_Asynchronous_Call : constant Boolean :=
4999 Nkind (N) = N_Block_Statement
5000 and then Is_Asynchronous_Call_Block (N);
5001 Is_Master : constant Boolean :=
40c21e91
PMR
5002 Nkind (N) /= N_Extended_Return_Statement
5003 and then Nkind (N) /= N_Entry_Body
85be939e
AC
5004 and then Is_Task_Master (N);
5005 Is_Protected_Subp_Body : constant Boolean :=
5006 Nkind (N) = N_Subprogram_Body
5007 and then Is_Protected_Subprogram_Body (N);
5008 Is_Task_Allocation : constant Boolean :=
5009 Nkind (N) = N_Block_Statement
5010 and then Is_Task_Allocation_Block (N);
5011 Is_Task_Body : constant Boolean :=
5012 Nkind (Original_Node (N)) = N_Task_Body;
9a975bfc
BD
5013
5014 -- We mark the secondary stack if it is used in this construct, and
5015 -- we're not returning a function result on the secondary stack, except
5016 -- that a build-in-place function that might or might not return on the
5017 -- secondary stack always needs a mark. A run-time test is required in
5018 -- the case where the build-in-place function has a BIP_Alloc extra
5019 -- parameter (see Create_Finalizer).
5020
85be939e 5021 Needs_Sec_Stack_Mark : constant Boolean :=
9a975bfc
BD
5022 (Uses_Sec_Stack (Scop)
5023 and then
5024 not Sec_Stack_Needed_For_Return (Scop))
5025 or else
5026 (Is_Build_In_Place_Function (Scop)
5027 and then Needs_BIP_Alloc_Form (Scop));
5028
85be939e
AC
5029 Needs_Custom_Cleanup : constant Boolean :=
5030 Nkind (N) = N_Block_Statement
5031 and then Present (Cleanup_Actions (N));
5032
5033 Actions_Required : constant Boolean :=
5034 Requires_Cleanup_Actions (N, True)
5035 or else Is_Asynchronous_Call
5036 or else Is_Master
5037 or else Is_Protected_Subp_Body
5038 or else Is_Task_Allocation
5039 or else Is_Task_Body
5040 or else Needs_Sec_Stack_Mark
5041 or else Needs_Custom_Cleanup;
df3e68b1 5042
df3e68b1 5043 Loc : Source_Ptr;
36295779 5044 Cln : List_Id;
df3e68b1 5045
df3e68b1
HK
5046 -- Start of processing for Expand_Cleanup_Actions
5047
5048 begin
5049 -- The current construct does not need any form of servicing
5050
5051 if not Actions_Required then
5052 return;
5053
5054 -- If the current node is a rewritten task body and the descriptors have
5055 -- not been delayed (due to some nested instantiations), do not generate
5056 -- redundant cleanup actions.
5057
5058 elsif Is_Task_Body
5059 and then Nkind (N) = N_Subprogram_Body
5060 and then not Delay_Subprogram_Descriptors (Corresponding_Spec (N))
5061 then
5062 return;
5063 end if;
5064
40c21e91 5065 -- If an extended return statement contains something like
c581c520 5066 --
40c21e91 5067 -- X := F (...);
c581c520 5068 --
40c21e91 5069 -- where F is a build-in-place function call returning a controlled
c581c520
PMR
5070 -- type, then a temporary object will be implicitly declared as part
5071 -- of the statement list, and this will need cleanup. In such cases,
5072 -- we transform:
40c21e91
PMR
5073 --
5074 -- return Result : T := ... do
5075 -- <statements> -- possibly with handlers
5076 -- end return;
5077 --
5078 -- into:
5079 --
5080 -- return Result : T := ... do
5081 -- declare -- no declarations
5082 -- begin
5083 -- <statements> -- possibly with handlers
5084 -- end; -- no handlers
5085 -- end return;
5086 --
5087 -- So Expand_Cleanup_Actions will end up being called recursively on the
5088 -- block statement.
5089
5090 if Nkind (N) = N_Extended_Return_Statement then
5091 declare
5092 Block : constant Node_Id :=
c581c520
PMR
5093 Make_Block_Statement (Sloc (N),
5094 Declarations => Empty_List,
5095 Handled_Statement_Sequence =>
5096 Handled_Statement_Sequence (N));
40c21e91 5097 begin
c581c520
PMR
5098 Set_Handled_Statement_Sequence (N,
5099 Make_Handled_Sequence_Of_Statements (Sloc (N),
5100 Statements => New_List (Block)));
5101
40c21e91
PMR
5102 Analyze (Block);
5103 end;
5104
5105 -- Analysis of the block did all the work
5106
5107 return;
5108 end if;
5109
36295779
AC
5110 if Needs_Custom_Cleanup then
5111 Cln := Cleanup_Actions (N);
5112 else
5113 Cln := No_List;
5114 end if;
5115
6d16658d
BD
5116 if No (Declarations (N)) then
5117 Set_Declarations (N, New_List);
5118 end if;
df3e68b1 5119
6d16658d
BD
5120 declare
5121 Decls : constant List_Id := Declarations (N);
5122 Fin_Id : Entity_Id;
5123 Mark : Entity_Id := Empty;
df3e68b1 5124 begin
56af8688
PMR
5125 -- If we are generating expanded code for debugging purposes, use the
5126 -- Sloc of the point of insertion for the cleanup code. The Sloc will
5127 -- be updated subsequently to reference the proper line in .dg files.
5128 -- If we are not debugging generated code, use No_Location instead,
5129 -- so that no debug information is generated for the cleanup code.
5130 -- This makes the behavior of the NEXT command in GDB monotonic, and
5131 -- makes the placement of breakpoints more accurate.
5132
5133 if Debug_Generated_Code then
5134 Loc := Sloc (Scop);
5135 else
5136 Loc := No_Location;
5137 end if;
5138
df3e68b1
HK
5139 -- A task activation call has already been built for a task
5140 -- allocation block.
5141
5142 if not Is_Task_Allocation then
5143 Build_Task_Activation_Call (N);
5144 end if;
5145
5146 if Is_Master then
5147 Establish_Task_Master (N);
5148 end if;
5149
df3e68b1
HK
5150 -- If secondary stack is in use, generate:
5151 --
5152 -- Mnn : constant Mark_Id := SS_Mark;
5153
df3e68b1 5154 if Needs_Sec_Stack_Mark then
6d16658d 5155 Set_Uses_Sec_Stack (Scop, False); -- avoid duplicate SS marks
df3e68b1
HK
5156 Mark := Make_Temporary (Loc, 'M');
5157
df3e68b1 5158 declare
6d16658d 5159 Mark_Call : constant Node_Id := Build_SS_Mark_Call (Loc, Mark);
df3e68b1 5160 begin
6d16658d
BD
5161 Prepend_To (Decls, Mark_Call);
5162 Analyze (Mark_Call);
df3e68b1
HK
5163 end;
5164 end if;
5165
df3e68b1
HK
5166 -- Generate finalization calls for all controlled objects appearing
5167 -- in the statements of N. Add context specific cleanup for various
5168 -- constructs.
5169
5170 Build_Finalizer
5171 (N => N,
36295779 5172 Clean_Stmts => Build_Cleanup_Statements (N, Cln),
df3e68b1 5173 Mark_Id => Mark,
6d16658d 5174 Top_Decls => Decls,
df3e68b1
HK
5175 Defer_Abort => Nkind (Original_Node (N)) = N_Task_Body
5176 or else Is_Master,
5177 Fin_Id => Fin_Id);
5178
5179 if Present (Fin_Id) then
5180 Build_Finalizer_Call (N, Fin_Id);
5181 end if;
df3e68b1
HK
5182 end;
5183 end Expand_Cleanup_Actions;
5184
5185 ---------------------------
5186 -- Expand_N_Package_Body --
5187 ---------------------------
5188
5189 -- Add call to Activate_Tasks if body is an activator (actual processing
5190 -- is in chapter 9).
5191
5192 -- Generate subprogram descriptor for elaboration routine
5193
5194 -- Encode entity names in package body
5195
5196 procedure Expand_N_Package_Body (N : Node_Id) is
1af4455a
HK
5197 Spec_Id : constant Entity_Id := Corresponding_Spec (N);
5198 Fin_Id : Entity_Id;
5199
df3e68b1
HK
5200 begin
5201 -- This is done only for non-generic packages
5202
1af4455a 5203 if Ekind (Spec_Id) = E_Package then
bbb9c475
EB
5204 -- Build dispatch tables of library-level tagged types for bodies
5205 -- that are not compilation units (see Analyze_Compilation_Unit),
5206 -- except for instances because they have no N_Compilation_Unit.
df3e68b1 5207
f46faa08 5208 if Tagged_Type_Expansion
1af4455a 5209 and then Is_Library_Level_Entity (Spec_Id)
bbb9c475
EB
5210 and then (not Is_Compilation_Unit (Spec_Id)
5211 or else Is_Generic_Instance (Spec_Id))
f46faa08
AC
5212 then
5213 Build_Static_Dispatch_Tables (N);
df3e68b1
HK
5214 end if;
5215
bbb9c475
EB
5216 Push_Scope (Spec_Id);
5217
2c5ed0df 5218 Expand_CUDA_Package (N);
8b7b6263 5219
df3e68b1 5220 Build_Task_Activation_Call (N);
9b2451e5 5221
90e491a7
PMR
5222 -- Verify the run-time semantics of pragma Initial_Condition at the
5223 -- end of the body statements.
9b2451e5 5224
90e491a7 5225 Expand_Pragma_Initial_Condition (Spec_Id, N);
f68289d8
GD
5226
5227 -- If this is a library-level package and unnesting is enabled,
5228 -- check for the presence of blocks with nested subprograms occurring
5229 -- in elaboration code, and generate procedures to encapsulate the
5230 -- blocks in case the nested subprograms make up-level references.
5231
5232 if Unnest_Subprogram_Mode
5233 and then
5234 Is_Library_Level_Entity (Current_Scope)
5235 then
5236 Check_Unnesting_Elaboration_Code (N);
5237 Check_Unnesting_In_Decls_Or_Stmts (Declarations (N));
5238 Check_Unnesting_In_Handlers (N);
5239 end if;
9b2451e5 5240
df3e68b1
HK
5241 Pop_Scope;
5242 end if;
5243
90e491a7 5244 Set_Elaboration_Flag (N, Spec_Id);
1af4455a 5245 Set_In_Package_Body (Spec_Id, False);
df3e68b1
HK
5246
5247 -- Set to encode entity names in package body before gigi is called
5248
5249 Qualify_Entity_Names (N);
5250
1af4455a 5251 if Ekind (Spec_Id) /= E_Generic_Package then
df3e68b1
HK
5252 Build_Finalizer
5253 (N => N,
26e7e1a0 5254 Clean_Stmts => No_List,
df3e68b1
HK
5255 Mark_Id => Empty,
5256 Top_Decls => No_List,
5257 Defer_Abort => False,
5258 Fin_Id => Fin_Id);
5259
5260 if Present (Fin_Id) then
5261 declare
5262 Body_Ent : Node_Id := Defining_Unit_Name (N);
5263
5264 begin
5265 if Nkind (Body_Ent) = N_Defining_Program_Unit_Name then
5266 Body_Ent := Defining_Identifier (Body_Ent);
5267 end if;
5268
5269 Set_Finalizer (Body_Ent, Fin_Id);
5270 end;
5271 end if;
5272 end if;
5273 end Expand_N_Package_Body;
5274
5275 ----------------------------------
5276 -- Expand_N_Package_Declaration --
5277 ----------------------------------
5278
5279 -- Add call to Activate_Tasks if there are tasks declared and the package
885c4871 5280 -- has no body. Note that in Ada 83 this may result in premature activation
df3e68b1
HK
5281 -- of some tasks, given that we cannot tell whether a body will eventually
5282 -- appear.
5283
5284 procedure Expand_N_Package_Declaration (N : Node_Id) is
2c1b72d7
AC
5285 Id : constant Entity_Id := Defining_Entity (N);
5286 Spec : constant Node_Id := Specification (N);
5287 Decls : List_Id;
5288 Fin_Id : Entity_Id;
5289
df3e68b1 5290 No_Body : Boolean := False;
2c1b72d7
AC
5291 -- True in the case of a package declaration that is a compilation
5292 -- unit and for which no associated body will be compiled in this
5293 -- compilation.
df3e68b1
HK
5294
5295 begin
5296 -- Case of a package declaration other than a compilation unit
5297
5298 if Nkind (Parent (N)) /= N_Compilation_Unit then
5299 null;
5300
5301 -- Case of a compilation unit that does not require a body
5302
5303 elsif not Body_Required (Parent (N))
5304 and then not Unit_Requires_Body (Id)
5305 then
5306 No_Body := True;
5307
5308 -- Special case of generating calling stubs for a remote call interface
2c1b72d7
AC
5309 -- package: even though the package declaration requires one, the body
5310 -- won't be processed in this compilation (so any stubs for RACWs
5311 -- declared in the package must be generated here, along with the spec).
df3e68b1
HK
5312
5313 elsif Parent (N) = Cunit (Main_Unit)
5314 and then Is_Remote_Call_Interface (Id)
5315 and then Distribution_Stub_Mode = Generate_Caller_Stub_Body
5316 then
5317 No_Body := True;
5318 end if;
5319
d72e7628 5320 -- For a nested instance, delay processing until freeze point
0d566e01
ES
5321
5322 if Has_Delayed_Freeze (Id)
d72e7628 5323 and then Nkind (Parent (N)) /= N_Compilation_Unit
0d566e01
ES
5324 then
5325 return;
5326 end if;
5327
df3e68b1
HK
5328 -- For a package declaration that implies no associated body, generate
5329 -- task activation call and RACW supporting bodies now (since we won't
5330 -- have a specific separate compilation unit for that).
5331
5332 if No_Body then
5333 Push_Scope (Id);
5334
9b2451e5 5335 -- Generate RACW subprogram bodies
df3e68b1 5336
9b2451e5 5337 if Has_RACW (Id) then
df3e68b1
HK
5338 Decls := Private_Declarations (Spec);
5339
5340 if No (Decls) then
5341 Decls := Visible_Declarations (Spec);
5342 end if;
5343
5344 if No (Decls) then
5345 Decls := New_List;
5346 Set_Visible_Declarations (Spec, Decls);
5347 end if;
5348
5349 Append_RACW_Bodies (Decls, Id);
5350 Analyze_List (Decls);
5351 end if;
5352
9b2451e5
AC
5353 -- Generate task activation call as last step of elaboration
5354
df3e68b1 5355 if Present (Activation_Chain_Entity (N)) then
9b2451e5
AC
5356 Build_Task_Activation_Call (N);
5357 end if;
df3e68b1 5358
90e491a7
PMR
5359 -- Verify the run-time semantics of pragma Initial_Condition at the
5360 -- end of the private declarations when the package lacks a body.
df3e68b1 5361
90e491a7 5362 Expand_Pragma_Initial_Condition (Id, N);
df3e68b1
HK
5363
5364 Pop_Scope;
5365 end if;
5366
bbb9c475
EB
5367 -- Build dispatch tables of library-level tagged types for instances
5368 -- that are not compilation units (see Analyze_Compilation_Unit).
df3e68b1 5369
f46faa08 5370 if Tagged_Type_Expansion
bbb9c475
EB
5371 and then Is_Library_Level_Entity (Id)
5372 and then Is_Generic_Instance (Id)
5373 and then not Is_Compilation_Unit (Id)
df3e68b1 5374 then
f46faa08 5375 Build_Static_Dispatch_Tables (N);
df3e68b1
HK
5376 end if;
5377
5378 -- Note: it is not necessary to worry about generating a subprogram
5379 -- descriptor, since the only way to get exception handlers into a
5380 -- package spec is to include instantiations, and that would cause
5381 -- generation of subprogram descriptors to be delayed in any case.
5382
5383 -- Set to encode entity names in package spec before gigi is called
5384
5385 Qualify_Entity_Names (N);
5386
5387 if Ekind (Id) /= E_Generic_Package then
5388 Build_Finalizer
5389 (N => N,
26e7e1a0 5390 Clean_Stmts => No_List,
df3e68b1
HK
5391 Mark_Id => Empty,
5392 Top_Decls => No_List,
5393 Defer_Abort => False,
5394 Fin_Id => Fin_Id);
5395
5396 Set_Finalizer (Id, Fin_Id);
5397 end if;
68f27c97 5398
f68289d8
GD
5399 -- If this is a library-level package and unnesting is enabled,
5400 -- check for the presence of blocks with nested subprograms occurring
5401 -- in elaboration code, and generate procedures to encapsulate the
5402 -- blocks in case the nested subprograms make up-level references.
5403
5404 if Unnest_Subprogram_Mode
5405 and then Is_Library_Level_Entity (Current_Scope)
5406 then
5407 Check_Unnesting_In_Decls_Or_Stmts (Visible_Declarations (Spec));
5408 Check_Unnesting_In_Decls_Or_Stmts (Private_Declarations (Spec));
5409 end if;
df3e68b1
HK
5410 end Expand_N_Package_Declaration;
5411
df3e68b1
HK
5412 ---------------------------------
5413 -- Has_Simple_Protected_Object --
5414 ---------------------------------
70482933 5415
df3e68b1
HK
5416 function Has_Simple_Protected_Object (T : Entity_Id) return Boolean is
5417 begin
5418 if Has_Task (T) then
5419 return False;
dcfa065d 5420
df3e68b1
HK
5421 elsif Is_Simple_Protected_Type (T) then
5422 return True;
dcfa065d 5423
df3e68b1
HK
5424 elsif Is_Array_Type (T) then
5425 return Has_Simple_Protected_Object (Component_Type (T));
70482933 5426
df3e68b1
HK
5427 elsif Is_Record_Type (T) then
5428 declare
5429 Comp : Entity_Id;
70482933 5430
df3e68b1
HK
5431 begin
5432 Comp := First_Component (T);
df3e68b1
HK
5433 while Present (Comp) loop
5434 if Has_Simple_Protected_Object (Etype (Comp)) then
5435 return True;
5436 end if;
70482933 5437
df3e68b1
HK
5438 Next_Component (Comp);
5439 end loop;
70482933 5440
df3e68b1
HK
5441 return False;
5442 end;
70482933 5443
df3e68b1
HK
5444 else
5445 return False;
5446 end if;
5447 end Has_Simple_Protected_Object;
70482933 5448
df3e68b1
HK
5449 ------------------------------------
5450 -- Insert_Actions_In_Scope_Around --
5451 ------------------------------------
fbf5a39b 5452
8e888920
AC
5453 procedure Insert_Actions_In_Scope_Around
5454 (N : Node_Id;
5455 Clean : Boolean;
5456 Manage_SS : Boolean)
5457 is
36295779
AC
5458 Act_Before : constant List_Id :=
5459 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Before);
8071b771
AC
5460 Act_After : constant List_Id :=
5461 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (After);
5462 Act_Cleanup : constant List_Id :=
5463 Scope_Stack.Table (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup);
d7f41b2d 5464 -- Note: We used to use renamings of Scope_Stack.Table (Scope_Stack.
937e9676 5465 -- Last), but this was incorrect as Process_Transients_In_Scope may
d7f41b2d 5466 -- introduce new scopes and cause a reallocation of Scope_Stack.Table.
df3e68b1 5467
937e9676 5468 procedure Process_Transients_In_Scope
2c1b72d7
AC
5469 (First_Object : Node_Id;
5470 Last_Object : Node_Id;
5471 Related_Node : Node_Id);
937e9676
AC
5472 -- Find all transient objects in the list First_Object .. Last_Object
5473 -- and generate finalization actions for them. Related_Node denotes the
5474 -- node which created all transient objects.
df3e68b1 5475
937e9676
AC
5476 ---------------------------------
5477 -- Process_Transients_In_Scope --
5478 ---------------------------------
df3e68b1 5479
937e9676 5480 procedure Process_Transients_In_Scope
2c1b72d7
AC
5481 (First_Object : Node_Id;
5482 Last_Object : Node_Id;
5483 Related_Node : Node_Id)
70482933 5484 is
c31cbf91 5485 Must_Hook : Boolean;
937e9676 5486 -- Flag denoting whether the context requires transient object
36eef04a 5487 -- export to the outer finalizer.
8c5b03a0 5488
36eef04a 5489 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result;
c31cbf91 5490 -- Return Abandon if arbitrary node denotes a subprogram call
9b168a8b 5491
c31cbf91
PT
5492 function Has_Subprogram_Call is
5493 new Traverse_Func (Is_Subprogram_Call);
97779c34 5494
937e9676
AC
5495 procedure Process_Transient_In_Scope
5496 (Obj_Decl : Node_Id;
5497 Blk_Data : Finalization_Exception_Data;
5498 Blk_Stmts : List_Id);
5499 -- Generate finalization actions for a single transient object
5500 -- denoted by object declaration Obj_Decl. Blk_Data is the
5501 -- exception data of the enclosing block. Blk_Stmts denotes the
5502 -- statements of the enclosing block.
5503
36eef04a
AC
5504 ------------------------
5505 -- Is_Subprogram_Call --
5506 ------------------------
5507
5508 function Is_Subprogram_Call (N : Node_Id) return Traverse_Result is
9b168a8b 5509 begin
18431dc5
AC
5510 -- A regular procedure or function call
5511
5512 if Nkind (N) in N_Subprogram_Call then
18431dc5
AC
5513 return Abandon;
5514
5515 -- Special cases
36eef04a 5516
18431dc5
AC
5517 -- Heavy expansion may relocate function calls outside the related
5518 -- node. Inspect the original node to detect the initial placement
5519 -- of the call.
5520
dc67cfea 5521 elsif Is_Rewrite_Substitution (N) then
c31cbf91 5522 return Has_Subprogram_Call (Original_Node (N));
e2ef0ff6 5523
18431dc5 5524 -- Generalized indexing always involves a function call
36eef04a 5525
18431dc5
AC
5526 elsif Nkind (N) = N_Indexed_Component
5527 and then Present (Generalized_Indexing (N))
36eef04a 5528 then
36eef04a
AC
5529 return Abandon;
5530
5531 -- Keep searching
5532
5533 else
5534 return OK;
5535 end if;
5536 end Is_Subprogram_Call;
5537
937e9676
AC
5538 --------------------------------
5539 -- Process_Transient_In_Scope --
5540 --------------------------------
9b168a8b 5541
937e9676
AC
5542 procedure Process_Transient_In_Scope
5543 (Obj_Decl : Node_Id;
5544 Blk_Data : Finalization_Exception_Data;
5545 Blk_Stmts : List_Id)
5546 is
5547 Loc : constant Source_Ptr := Sloc (Obj_Decl);
5548 Obj_Id : constant Entity_Id := Defining_Entity (Obj_Decl);
5549 Fin_Call : Node_Id;
5550 Fin_Stmts : List_Id;
5551 Hook_Assign : Node_Id;
5552 Hook_Clear : Node_Id;
5553 Hook_Decl : Node_Id;
5554 Hook_Insert : Node_Id;
5555 Ptr_Decl : Node_Id;
5556
5557 begin
5558 -- Mark the transient object as successfully processed to avoid
5559 -- double finalization.
5560
5561 Set_Is_Finalized_Transient (Obj_Id);
5562
5563 -- Construct all the pieces necessary to hook and finalize the
5564 -- transient object.
5565
5566 Build_Transient_Object_Statements
5567 (Obj_Decl => Obj_Decl,
5568 Fin_Call => Fin_Call,
5569 Hook_Assign => Hook_Assign,
5570 Hook_Clear => Hook_Clear,
5571 Hook_Decl => Hook_Decl,
5572 Ptr_Decl => Ptr_Decl);
5573
5574 -- The context contains at least one subprogram call which may
5575 -- raise an exception. This scenario employs "hooking" to pass
5576 -- transient objects to the enclosing finalizer in case of an
5577 -- exception.
5578
5579 if Must_Hook then
5580
5581 -- Add the access type which provides a reference to the
5582 -- transient object. Generate:
5583
5584 -- type Ptr_Typ is access all Desig_Typ;
5585
5586 Insert_Action (Obj_Decl, Ptr_Decl);
5587
5588 -- Add the temporary which acts as a hook to the transient
5589 -- object. Generate:
5590
5591 -- Hook : Ptr_Typ := null;
5592
5593 Insert_Action (Obj_Decl, Hook_Decl);
5594
5595 -- When the transient object is initialized by an aggregate,
5596 -- the hook must capture the object after the last aggregate
5597 -- assignment takes place. Only then is the object considered
5598 -- fully initialized. Generate:
5599
5600 -- Hook := Ptr_Typ (Obj_Id);
5601 -- <or>
5602 -- Hook := Obj_Id'Unrestricted_Access;
5603
7e8e3cb4
AC
5604 -- Similarly if we have a build in place call: we must
5605 -- initialize Hook only after the call has happened, otherwise
5606 -- Obj_Id will not be initialized yet.
5607
5608 if Ekind (Obj_Id) in E_Constant | E_Variable then
5609 if Present (Last_Aggregate_Assignment (Obj_Id)) then
5610 Hook_Insert := Last_Aggregate_Assignment (Obj_Id);
5611 elsif Present (BIP_Initialization_Call (Obj_Id)) then
5612 Hook_Insert := BIP_Initialization_Call (Obj_Id);
5613 else
5614 Hook_Insert := Obj_Decl;
5615 end if;
937e9676
AC
5616
5617 -- Otherwise the hook seizes the related object immediately
5618
5619 else
5620 Hook_Insert := Obj_Decl;
5621 end if;
5622
5623 Insert_After_And_Analyze (Hook_Insert, Hook_Assign);
5624 end if;
5625
5626 -- When exception propagation is enabled wrap the hook clear
5627 -- statement and the finalization call into a block to catch
5628 -- potential exceptions raised during finalization. Generate:
5629
5630 -- begin
5631 -- [Hook := null;]
5632 -- [Deep_]Finalize (Obj_Ref);
5633
5634 -- exception
5635 -- when others =>
5636 -- if not Raised then
5637 -- Raised := True;
5638 -- Save_Occurrence
5639 -- (Enn, Get_Current_Excep.all.all);
5640 -- end if;
5641 -- end;
5642
5643 if Exceptions_OK then
5644 Fin_Stmts := New_List;
5645
5646 if Must_Hook then
5647 Append_To (Fin_Stmts, Hook_Clear);
5648 end if;
5649
5650 Append_To (Fin_Stmts, Fin_Call);
5651
5652 Prepend_To (Blk_Stmts,
5653 Make_Block_Statement (Loc,
5654 Handled_Statement_Sequence =>
5655 Make_Handled_Sequence_Of_Statements (Loc,
5656 Statements => Fin_Stmts,
5657 Exception_Handlers => New_List (
5658 Build_Exception_Handler (Blk_Data)))));
5659
5660 -- Otherwise generate:
5661
5662 -- [Hook := null;]
5663 -- [Deep_]Finalize (Obj_Ref);
5664
5665 -- Note that the statements are inserted in reverse order to
5666 -- achieve the desired final order outlined above.
5667
5668 else
5669 Prepend_To (Blk_Stmts, Fin_Call);
5670
5671 if Must_Hook then
5672 Prepend_To (Blk_Stmts, Hook_Clear);
5673 end if;
5674 end if;
5675 end Process_Transient_In_Scope;
5676
5677 -- Local variables
6e840989 5678
8c5b03a0 5679 Built : Boolean := False;
937e9676 5680 Blk_Data : Finalization_Exception_Data;
6e840989
HK
5681 Blk_Decl : Node_Id := Empty;
5682 Blk_Decls : List_Id := No_List;
5683 Blk_Ins : Node_Id;
a6b13d32
AC
5684 Blk_Stmts : List_Id := No_List;
5685 Loc : Source_Ptr := No_Location;
6e840989 5686 Obj_Decl : Node_Id;
8c5b03a0 5687
937e9676 5688 -- Start of processing for Process_Transients_In_Scope
3217f71e 5689
70482933 5690 begin
6e840989
HK
5691 -- The expansion performed by this routine is as follows:
5692
5693 -- type Ptr_Typ_1 is access all Ctrl_Trans_Obj_1_Typ;
5694 -- Hook_1 : Ptr_Typ_1 := null;
5695 -- Ctrl_Trans_Obj_1 : ...;
5696 -- Hook_1 := Ctrl_Trans_Obj_1'Unrestricted_Access;
5697 -- . . .
5698 -- type Ptr_Typ_N is access all Ctrl_Trans_Obj_N_Typ;
5699 -- Hook_N : Ptr_Typ_N := null;
5700 -- Ctrl_Trans_Obj_N : ...;
5701 -- Hook_N := Ctrl_Trans_Obj_N'Unrestricted_Access;
5702
5703 -- declare
5704 -- Abrt : constant Boolean := ...;
5705 -- Ex : Exception_Occurrence;
5706 -- Raised : Boolean := False;
5707
5708 -- begin
7bf911b5
HK
5709 -- Abort_Defer;
5710
6e840989
HK
5711 -- begin
5712 -- Hook_N := null;
5713 -- [Deep_]Finalize (Ctrl_Trans_Obj_N);
5714
5715 -- exception
5716 -- when others =>
5717 -- if not Raised then
5718 -- Raised := True;
5719 -- Save_Occurrence (Ex, Get_Current_Excep.all.all);
5720 -- end;
5721 -- . . .
5722 -- begin
5723 -- Hook_1 := null;
5724 -- [Deep_]Finalize (Ctrl_Trans_Obj_1);
5725
5726 -- exception
5727 -- when others =>
5728 -- if not Raised then
5729 -- Raised := True;
5730 -- Save_Occurrence (Ex, Get_Current_Excep.all.all);
5731 -- end;
5732
937e9676
AC
5733 -- Abort_Undefer;
5734
6e840989
HK
5735 -- if Raised and not Abrt then
5736 -- Raise_From_Controlled_Operation (Ex);
5737 -- end if;
6e840989
HK
5738 -- end;
5739
8c7ff9a0
AC
5740 -- Recognize a scenario where the transient context is an object
5741 -- declaration initialized by a build-in-place function call:
5742
5743 -- Obj : ... := BIP_Function_Call (Ctrl_Func_Call);
5744
5745 -- The rough expansion of the above is:
5746
5747 -- Temp : ... := Ctrl_Func_Call;
5748 -- Obj : ...;
5749 -- Res : ... := BIP_Func_Call (..., Obj, ...);
5750
937e9676
AC
5751 -- The finalization of any transient object must happen after the
5752 -- build-in-place function call is executed.
8c7ff9a0
AC
5753
5754 if Nkind (N) = N_Object_Declaration
5755 and then Present (BIP_Initialization_Call (Defining_Identifier (N)))
5756 then
5757 Must_Hook := True;
6e840989 5758 Blk_Ins := BIP_Initialization_Call (Defining_Identifier (N));
8c7ff9a0 5759
36eef04a
AC
5760 -- Search the context for at least one subprogram call. If found, the
5761 -- machinery exports all transient objects to the enclosing finalizer
5762 -- due to the possibility of abnormal call termination.
5763
8c7ff9a0 5764 else
c31cbf91
PT
5765 Must_Hook := Has_Subprogram_Call (N) = Abandon;
5766 Blk_Ins := Last_Object;
6e840989
HK
5767 end if;
5768
5769 if Clean then
5770 Insert_List_After_And_Analyze (Blk_Ins, Act_Cleanup);
8c7ff9a0 5771 end if;
36eef04a 5772
df3e68b1 5773 -- Examine all objects in the list First_Object .. Last_Object
70482933 5774
6e840989
HK
5775 Obj_Decl := First_Object;
5776 while Present (Obj_Decl) loop
5777 if Nkind (Obj_Decl) = N_Object_Declaration
5778 and then Analyzed (Obj_Decl)
5779 and then Is_Finalizable_Transient (Obj_Decl, N)
70482933 5780
2c1b72d7
AC
5781 -- Do not process the node to be wrapped since it will be
5782 -- handled by the enclosing finalizer.
70482933 5783
6e840989 5784 and then Obj_Decl /= Related_Node
df3e68b1 5785 then
937e9676 5786 Loc := Sloc (Obj_Decl);
8c5b03a0 5787
40c21e91 5788 -- Before generating the cleanup code for the first transient
6e840989
HK
5789 -- object, create a wrapper block which houses all hook clear
5790 -- statements and finalization calls. This wrapper is needed by
40c21e91 5791 -- the back end.
6e840989
HK
5792
5793 if not Built then
5794 Built := True;
5795 Blk_Stmts := New_List;
8c5b03a0 5796
937e9676
AC
5797 -- Generate:
5798 -- Abrt : constant Boolean := ...;
5799 -- Ex : Exception_Occurrence;
5800 -- Raised : Boolean := False;
8c5b03a0 5801
6e840989
HK
5802 if Exceptions_OK then
5803 Blk_Decls := New_List;
937e9676 5804 Build_Object_Declarations (Blk_Data, Blk_Decls, Loc);
6e840989
HK
5805 end if;
5806
5807 Blk_Decl :=
5808 Make_Block_Statement (Loc,
5809 Declarations => Blk_Decls,
5810 Handled_Statement_Sequence =>
5811 Make_Handled_Sequence_Of_Statements (Loc,
5812 Statements => Blk_Stmts));
8c5b03a0
AC
5813 end if;
5814
937e9676
AC
5815 -- Construct all necessary circuitry to hook and finalize a
5816 -- single transient object.
8c5b03a0 5817
a6b13d32 5818 pragma Assert (Present (Blk_Stmts));
937e9676
AC
5819 Process_Transient_In_Scope
5820 (Obj_Decl => Obj_Decl,
5821 Blk_Data => Blk_Data,
5822 Blk_Stmts => Blk_Stmts);
5eeeed5e 5823 end if;
79ee6ab3 5824
5eeeed5e
AC
5825 -- Terminate the scan after the last object has been processed to
5826 -- avoid touching unrelated code.
fbf5a39b 5827
6e840989 5828 if Obj_Decl = Last_Object then
df3e68b1
HK
5829 exit;
5830 end if;
70482933 5831
6e840989 5832 Next (Obj_Decl);
df3e68b1 5833 end loop;
70482933 5834
937e9676
AC
5835 -- Complete the decoration of the enclosing finalization block and
5836 -- insert it into the tree.
5837
6e840989 5838 if Present (Blk_Decl) then
7bf911b5 5839
a6b13d32
AC
5840 pragma Assert (Present (Blk_Stmts));
5841 pragma Assert (Loc /= No_Location);
5842
937e9676
AC
5843 -- Note that this Abort_Undefer does not require a extra block or
5844 -- an AT_END handler because each finalization exception is caught
5845 -- in its own corresponding finalization block. As a result, the
5846 -- call to Abort_Defer always takes place.
7bf911b5
HK
5847
5848 if Abort_Allowed then
5849 Prepend_To (Blk_Stmts,
5850 Build_Runtime_Call (Loc, RE_Abort_Defer));
5851
5852 Append_To (Blk_Stmts,
5853 Build_Runtime_Call (Loc, RE_Abort_Undefer));
5854 end if;
5855
937e9676
AC
5856 -- Generate:
5857 -- if Raised and then not Abrt then
5858 -- Raise_From_Controlled_Operation (Ex);
5859 -- end if;
5860
5861 if Exceptions_OK then
5862 Append_To (Blk_Stmts, Build_Raise_Statement (Blk_Data));
5863 end if;
5864
6e840989 5865 Insert_After_And_Analyze (Blk_Ins, Blk_Decl);
df3e68b1 5866 end if;
937e9676 5867 end Process_Transients_In_Scope;
70482933 5868
8e888920
AC
5869 -- Local variables
5870
5871 Loc : constant Source_Ptr := Sloc (N);
5872 Node_To_Wrap : constant Node_Id := Node_To_Be_Wrapped;
5873 First_Obj : Node_Id;
5874 Last_Obj : Node_Id;
5875 Mark_Id : Entity_Id;
5876 Target : Node_Id;
5877
df3e68b1 5878 -- Start of processing for Insert_Actions_In_Scope_Around
70482933 5879
df3e68b1 5880 begin
ed323421 5881 -- Nothing to do if the scope does not manage the secondary stack or
b7e68e7d 5882 -- does not contain meaningful actions for insertion.
ed323421
AC
5883
5884 if not Manage_SS
5885 and then No (Act_Before)
5886 and then No (Act_After)
5887 and then No (Act_Cleanup)
5888 then
df3e68b1 5889 return;
fbf5a39b 5890 end if;
70482933 5891
8e888920
AC
5892 -- If the node to be wrapped is the trigger of an asynchronous select,
5893 -- it is not part of a statement list. The actions must be inserted
5894 -- before the select itself, which is part of some list of statements.
5895 -- Note that the triggering alternative includes the triggering
41c79d60
AC
5896 -- statement and an optional statement list. If the node to be
5897 -- wrapped is part of that list, the normal insertion applies.
70482933 5898
8e888920
AC
5899 if Nkind (Parent (Node_To_Wrap)) = N_Triggering_Alternative
5900 and then not Is_List_Member (Node_To_Wrap)
5901 then
5902 Target := Parent (Parent (Node_To_Wrap));
5903 else
5904 Target := N;
5905 end if;
33c423c8 5906
8e888920
AC
5907 First_Obj := Target;
5908 Last_Obj := Target;
33c423c8 5909
8e888920
AC
5910 -- Add all actions associated with a transient scope into the main tree.
5911 -- There are several scenarios here:
2c1b72d7 5912
8e888920
AC
5913 -- +--- Before ----+ +----- After ---+
5914 -- 1) First_Obj ....... Target ........ Last_Obj
2c1b72d7 5915
8e888920 5916 -- 2) First_Obj ....... Target
2c1b72d7 5917
8e888920 5918 -- 3) Target ........ Last_Obj
9732e886 5919
8e888920 5920 -- Flag declarations are inserted before the first object
9732e886 5921
8e888920
AC
5922 if Present (Act_Before) then
5923 First_Obj := First (Act_Before);
5924 Insert_List_Before (Target, Act_Before);
5925 end if;
e8374e7a 5926
8e888920 5927 -- Finalization calls are inserted after the last object
e8374e7a 5928
8e888920
AC
5929 if Present (Act_After) then
5930 Last_Obj := Last (Act_After);
5931 Insert_List_After (Target, Act_After);
5932 end if;
33c423c8 5933
8e888920 5934 -- Mark and release the secondary stack when the context warrants it
70482933 5935
8e888920
AC
5936 if Manage_SS then
5937 Mark_Id := Make_Temporary (Loc, 'M');
70482933 5938
8e888920
AC
5939 -- Generate:
5940 -- Mnn : constant Mark_Id := SS_Mark;
afe4375b 5941
8e888920
AC
5942 Insert_Before_And_Analyze
5943 (First_Obj, Build_SS_Mark_Call (Loc, Mark_Id));
afe4375b 5944
8e888920
AC
5945 -- Generate:
5946 -- SS_Release (Mnn);
afe4375b 5947
8e888920
AC
5948 Insert_After_And_Analyze
5949 (Last_Obj, Build_SS_Release_Call (Loc, Mark_Id));
5950 end if;
afe4375b 5951
937e9676
AC
5952 -- Check for transient objects associated with Target and generate the
5953 -- appropriate finalization actions for them.
afe4375b 5954
937e9676 5955 Process_Transients_In_Scope
8e888920
AC
5956 (First_Object => First_Obj,
5957 Last_Object => Last_Obj,
5958 Related_Node => Target);
3aac5551 5959
8e888920
AC
5960 -- Reset the action lists
5961
5962 Scope_Stack.Table
5963 (Scope_Stack.Last).Actions_To_Be_Wrapped (Before) := No_List;
5964 Scope_Stack.Table
5965 (Scope_Stack.Last).Actions_To_Be_Wrapped (After) := No_List;
5966
5967 if Clean then
5968 Scope_Stack.Table
5969 (Scope_Stack.Last).Actions_To_Be_Wrapped (Cleanup) := No_List;
5970 end if;
df3e68b1 5971 end Insert_Actions_In_Scope_Around;
afe4375b 5972
df3e68b1
HK
5973 ------------------------------
5974 -- Is_Simple_Protected_Type --
5975 ------------------------------
afe4375b 5976
df3e68b1
HK
5977 function Is_Simple_Protected_Type (T : Entity_Id) return Boolean is
5978 begin
5979 return
5980 Is_Protected_Type (T)
88e7531b 5981 and then not Uses_Lock_Free (T)
df3e68b1
HK
5982 and then not Has_Entries (T)
5983 and then Is_RTE (Find_Protection_Type (T), RE_Protection);
5984 end Is_Simple_Protected_Type;
afe4375b 5985
df3e68b1
HK
5986 -----------------------
5987 -- Make_Adjust_Call --
5988 -----------------------
afe4375b 5989
df3e68b1 5990 function Make_Adjust_Call
4ac2bbbd
AC
5991 (Obj_Ref : Node_Id;
5992 Typ : Entity_Id;
5993 Skip_Self : Boolean := False) return Node_Id
df3e68b1
HK
5994 is
5995 Loc : constant Source_Ptr := Sloc (Obj_Ref);
5996 Adj_Id : Entity_Id := Empty;
2168d7cc 5997 Ref : Node_Id;
df3e68b1 5998 Utyp : Entity_Id;
afe4375b 5999
df3e68b1 6000 begin
2168d7cc
AC
6001 Ref := Obj_Ref;
6002
df3e68b1 6003 -- Recover the proper type which contains Deep_Adjust
afe4375b 6004
df3e68b1
HK
6005 if Is_Class_Wide_Type (Typ) then
6006 Utyp := Root_Type (Typ);
6007 else
6008 Utyp := Typ;
6009 end if;
afe4375b 6010
df3e68b1
HK
6011 Utyp := Underlying_Type (Base_Type (Utyp));
6012 Set_Assignment_OK (Ref);
afe4375b 6013
1fb63e89 6014 -- Deal with untagged derivation of private views
afe4375b 6015
2168d7cc 6016 if Present (Utyp) and then Is_Untagged_Derivation (Typ) then
df3e68b1
HK
6017 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
6018 Ref := Unchecked_Convert_To (Utyp, Ref);
6019 Set_Assignment_OK (Ref);
6020 end if;
afe4375b 6021
df3e68b1
HK
6022 -- When dealing with the completion of a private type, use the base
6023 -- type instead.
afe4375b 6024
2168d7cc 6025 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
df3e68b1 6026 pragma Assert (Is_Private_Type (Typ));
afe4375b 6027
df3e68b1
HK
6028 Utyp := Base_Type (Utyp);
6029 Ref := Unchecked_Convert_To (Utyp, Ref);
70482933
RK
6030 end if;
6031
2168d7cc
AC
6032 -- The underlying type may not be present due to a missing full view. In
6033 -- this case freezing did not take place and there is no [Deep_]Adjust
6034 -- primitive to call.
6035
6036 if No (Utyp) then
6037 return Empty;
6038
6039 elsif Skip_Self then
df3e68b1 6040 if Has_Controlled_Component (Utyp) then
4ac2bbbd 6041 if Is_Tagged_Type (Utyp) then
ca811241 6042 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
4ac2bbbd
AC
6043 else
6044 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
6045 end if;
df3e68b1 6046 end if;
9732e886 6047
d3cb4cc0 6048 -- Class-wide types, interfaces and types with controlled components
e8374e7a 6049
df3e68b1 6050 elsif Is_Class_Wide_Type (Typ)
d3cb4cc0 6051 or else Is_Interface (Typ)
df3e68b1
HK
6052 or else Has_Controlled_Component (Utyp)
6053 then
6054 if Is_Tagged_Type (Utyp) then
ca811241 6055 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
df3e68b1
HK
6056 else
6057 Adj_Id := TSS (Utyp, TSS_Deep_Adjust);
6058 end if;
9732e886 6059
d3cb4cc0
AC
6060 -- Derivations from [Limited_]Controlled
6061
6062 elsif Is_Controlled (Utyp) then
6063 if Has_Controlled_Component (Utyp) then
ca811241 6064 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
d3cb4cc0 6065 else
ca811241 6066 Adj_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Adjust_Case));
d3cb4cc0
AC
6067 end if;
6068
6069 -- Tagged types
6070
6071 elsif Is_Tagged_Type (Utyp) then
ca811241 6072 Adj_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Adjust);
9732e886 6073
df3e68b1 6074 else
d3cb4cc0 6075 raise Program_Error;
df3e68b1 6076 end if;
e8374e7a 6077
df3e68b1 6078 if Present (Adj_Id) then
e8374e7a 6079
df3e68b1
HK
6080 -- If the object is unanalyzed, set its expected type for use in
6081 -- Convert_View in case an additional conversion is needed.
9732e886 6082
df3e68b1
HK
6083 if No (Etype (Ref))
6084 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
6085 then
6086 Set_Etype (Ref, Typ);
9732e886 6087 end if;
33c423c8 6088
df3e68b1
HK
6089 -- The object reference may need another conversion depending on the
6090 -- type of the formal and that of the actual.
70482933 6091
df3e68b1
HK
6092 if not Is_Class_Wide_Type (Typ) then
6093 Ref := Convert_View (Adj_Id, Ref);
6094 end if;
70482933 6095
4ac2bbbd
AC
6096 return
6097 Make_Call (Loc,
6098 Proc_Id => Adj_Id,
2168d7cc 6099 Param => Ref,
4ac2bbbd 6100 Skip_Self => Skip_Self);
df3e68b1
HK
6101 else
6102 return Empty;
6103 end if;
6104 end Make_Adjust_Call;
70482933 6105
df3e68b1
HK
6106 ---------------
6107 -- Make_Call --
6108 ---------------
70482933 6109
df3e68b1 6110 function Make_Call
4ac2bbbd
AC
6111 (Loc : Source_Ptr;
6112 Proc_Id : Entity_Id;
6113 Param : Node_Id;
6114 Skip_Self : Boolean := False) return Node_Id
70482933 6115 is
df3e68b1 6116 Params : constant List_Id := New_List (Param);
70482933
RK
6117
6118 begin
4ac2bbbd
AC
6119 -- Do not apply the controlled action to the object itself by signaling
6120 -- the related routine to avoid self.
dcfa065d 6121
4ac2bbbd 6122 if Skip_Self then
e4494292 6123 Append_To (Params, New_Occurrence_Of (Standard_False, Loc));
df3e68b1 6124 end if;
dcfa065d 6125
df3e68b1
HK
6126 return
6127 Make_Procedure_Call_Statement (Loc,
e4494292 6128 Name => New_Occurrence_Of (Proc_Id, Loc),
df3e68b1
HK
6129 Parameter_Associations => Params);
6130 end Make_Call;
70482933 6131
df3e68b1
HK
6132 --------------------------
6133 -- Make_Deep_Array_Body --
6134 --------------------------
70482933 6135
df3e68b1
HK
6136 function Make_Deep_Array_Body
6137 (Prim : Final_Primitives;
6138 Typ : Entity_Id) return List_Id
6139 is
6140 function Build_Adjust_Or_Finalize_Statements
6141 (Typ : Entity_Id) return List_Id;
6142 -- Create the statements necessary to adjust or finalize an array of
6143 -- controlled elements. Generate:
cfae2bed 6144 --
df3e68b1 6145 -- declare
14848f57 6146 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
6147 -- <or>
6148 -- Abort : constant Boolean := False; -- no abort
cfae2bed 6149 --
df3e68b1
HK
6150 -- E : Exception_Occurrence;
6151 -- Raised : Boolean := False;
cfae2bed 6152 --
df3e68b1
HK
6153 -- begin
6154 -- for J1 in [reverse] Typ'First (1) .. Typ'Last (1) loop
6155 -- ^-- in the finalization case
6156 -- ...
6157 -- for Jn in [reverse] Typ'First (n) .. Typ'Last (n) loop
6158 -- begin
6159 -- [Deep_]Adjust / Finalize (V (J1, ..., Jn));
cfae2bed 6160 --
df3e68b1
HK
6161 -- exception
6162 -- when others =>
6163 -- if not Raised then
6164 -- Raised := True;
6165 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6166 -- end if;
6167 -- end;
6168 -- end loop;
6169 -- ...
6170 -- end loop;
cfae2bed 6171 --
ca5af305
AC
6172 -- if Raised and then not Abort then
6173 -- Raise_From_Controlled_Operation (E);
df3e68b1
HK
6174 -- end if;
6175 -- end;
6176
6177 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id;
6178 -- Create the statements necessary to initialize an array of controlled
6179 -- elements. Include a mechanism to carry out partial finalization if an
6180 -- exception occurs. Generate:
cfae2bed 6181 --
df3e68b1
HK
6182 -- declare
6183 -- Counter : Integer := 0;
cfae2bed 6184 --
df3e68b1
HK
6185 -- begin
6186 -- for J1 in V'Range (1) loop
6187 -- ...
6188 -- for JN in V'Range (N) loop
6189 -- begin
6190 -- [Deep_]Initialize (V (J1, ..., JN));
cfae2bed 6191 --
df3e68b1 6192 -- Counter := Counter + 1;
cfae2bed 6193 --
df3e68b1
HK
6194 -- exception
6195 -- when others =>
6196 -- declare
14848f57 6197 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
6198 -- <or>
6199 -- Abort : constant Boolean := False; -- no abort
7f37fff1 6200 -- E : Exception_Occurrence;
df3e68b1
HK
6201 -- Raised : Boolean := False;
6202
6203 -- begin
6204 -- Counter :=
6205 -- V'Length (1) *
6206 -- V'Length (2) *
6207 -- ...
6208 -- V'Length (N) - Counter;
6209
6210 -- for F1 in reverse V'Range (1) loop
6211 -- ...
6212 -- for FN in reverse V'Range (N) loop
6213 -- if Counter > 0 then
6214 -- Counter := Counter - 1;
6215 -- else
6216 -- begin
6217 -- [Deep_]Finalize (V (F1, ..., FN));
6218
6219 -- exception
6220 -- when others =>
6221 -- if not Raised then
6222 -- Raised := True;
6223 -- Save_Occurrence (E,
6224 -- Get_Current_Excep.all.all);
6225 -- end if;
6226 -- end;
6227 -- end if;
6228 -- end loop;
6229 -- ...
6230 -- end loop;
6231 -- end;
886b5a18 6232 --
ca5af305
AC
6233 -- if Raised and then not Abort then
6234 -- Raise_From_Controlled_Operation (E);
df3e68b1 6235 -- end if;
886b5a18 6236 --
df3e68b1
HK
6237 -- raise;
6238 -- end;
6239 -- end loop;
6240 -- end loop;
6241 -- end;
6242
6243 function New_References_To
6244 (L : List_Id;
6245 Loc : Source_Ptr) return List_Id;
6246 -- Given a list of defining identifiers, return a list of references to
6247 -- the original identifiers, in the same order as they appear.
6248
6249 -----------------------------------------
6250 -- Build_Adjust_Or_Finalize_Statements --
6251 -----------------------------------------
6252
6253 function Build_Adjust_Or_Finalize_Statements
6254 (Typ : Entity_Id) return List_Id
6255 is
321c24f7
AC
6256 Comp_Typ : constant Entity_Id := Component_Type (Typ);
6257 Index_List : constant List_Id := New_List;
6258 Loc : constant Source_Ptr := Sloc (Typ);
6259 Num_Dims : constant Int := Number_Dimensions (Typ);
df3e68b1 6260
d0ef7921
AC
6261 procedure Build_Indexes;
6262 -- Generate the indexes used in the dimension loops
df3e68b1
HK
6263
6264 -------------------
d0ef7921 6265 -- Build_Indexes --
df3e68b1
HK
6266 -------------------
6267
d0ef7921 6268 procedure Build_Indexes is
df3e68b1
HK
6269 begin
6270 -- Generate the following identifiers:
6271 -- Jnn - for initialization
70482933 6272
df3e68b1
HK
6273 for Dim in 1 .. Num_Dims loop
6274 Append_To (Index_List,
6275 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
6276 end loop;
d0ef7921 6277 end Build_Indexes;
70482933 6278
2168d7cc
AC
6279 -- Local variables
6280
6281 Final_Decls : List_Id := No_List;
6282 Final_Data : Finalization_Exception_Data;
6283 Block : Node_Id;
6284 Call : Node_Id;
6285 Comp_Ref : Node_Id;
6286 Core_Loop : Node_Id;
6287 Dim : Int;
6288 J : Entity_Id;
6289 Loop_Id : Entity_Id;
6290 Stmts : List_Id;
6291
df3e68b1 6292 -- Start of processing for Build_Adjust_Or_Finalize_Statements
70482933 6293
df3e68b1 6294 begin
2168d7cc 6295 Final_Decls := New_List;
70482933 6296
d0ef7921 6297 Build_Indexes;
2168d7cc 6298 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
dcfa065d 6299
df3e68b1
HK
6300 Comp_Ref :=
6301 Make_Indexed_Component (Loc,
2c1b72d7
AC
6302 Prefix => Make_Identifier (Loc, Name_V),
6303 Expressions => New_References_To (Index_List, Loc));
df3e68b1 6304 Set_Etype (Comp_Ref, Comp_Typ);
dcfa065d 6305
df3e68b1
HK
6306 -- Generate:
6307 -- [Deep_]Adjust (V (J1, ..., JN))
70482933 6308
df3e68b1 6309 if Prim = Adjust_Case then
2c1b72d7 6310 Call := Make_Adjust_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
70482933 6311
df3e68b1
HK
6312 -- Generate:
6313 -- [Deep_]Finalize (V (J1, ..., JN))
70482933 6314
df3e68b1 6315 else pragma Assert (Prim = Finalize_Case);
2c1b72d7 6316 Call := Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
df3e68b1 6317 end if;
70482933 6318
2168d7cc 6319 if Present (Call) then
c5288c90 6320
2168d7cc 6321 -- Generate the block which houses the adjust or finalize call:
c5288c90 6322
2168d7cc
AC
6323 -- begin
6324 -- <adjust or finalize call>
c5288c90 6325
2168d7cc
AC
6326 -- exception
6327 -- when others =>
6328 -- if not Raised then
6329 -- Raised := True;
6330 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6331 -- end if;
6332 -- end;
c5288c90 6333
2168d7cc
AC
6334 if Exceptions_OK then
6335 Core_Loop :=
6336 Make_Block_Statement (Loc,
6337 Handled_Statement_Sequence =>
6338 Make_Handled_Sequence_Of_Statements (Loc,
6339 Statements => New_List (Call),
6340 Exception_Handlers => New_List (
6341 Build_Exception_Handler (Final_Data))));
6342 else
6343 Core_Loop := Call;
6344 end if;
70482933 6345
2168d7cc
AC
6346 -- Generate the dimension loops starting from the innermost one
6347
6348 -- for Jnn in [reverse] V'Range (Dim) loop
6349 -- <core loop>
6350 -- end loop;
6351
6352 J := Last (Index_List);
6353 Dim := Num_Dims;
6354 while Present (J) and then Dim > 0 loop
6355 Loop_Id := J;
6356 Prev (J);
6357 Remove (Loop_Id);
6358
6359 Core_Loop :=
6360 Make_Loop_Statement (Loc,
6361 Iteration_Scheme =>
6362 Make_Iteration_Scheme (Loc,
6363 Loop_Parameter_Specification =>
6364 Make_Loop_Parameter_Specification (Loc,
6365 Defining_Identifier => Loop_Id,
6366 Discrete_Subtype_Definition =>
6367 Make_Attribute_Reference (Loc,
6368 Prefix => Make_Identifier (Loc, Name_V),
6369 Attribute_Name => Name_Range,
6370 Expressions => New_List (
6371 Make_Integer_Literal (Loc, Dim))),
6372
6373 Reverse_Present =>
6374 Prim = Finalize_Case)),
6375
6376 Statements => New_List (Core_Loop),
6377 End_Label => Empty);
6378
6379 Dim := Dim - 1;
6380 end loop;
70482933 6381
2168d7cc
AC
6382 -- Generate the block which contains the core loop, declarations
6383 -- of the abort flag, the exception occurrence, the raised flag
6384 -- and the conditional raise:
70482933 6385
2168d7cc
AC
6386 -- declare
6387 -- Abort : constant Boolean := Triggered_By_Abort;
6388 -- <or>
6389 -- Abort : constant Boolean := False; -- no abort
70482933 6390
2168d7cc
AC
6391 -- E : Exception_Occurrence;
6392 -- Raised : Boolean := False;
70482933 6393
2168d7cc
AC
6394 -- begin
6395 -- <core loop>
70482933 6396
2168d7cc
AC
6397 -- if Raised and then not Abort then
6398 -- Raise_From_Controlled_Operation (E);
6399 -- end if;
6400 -- end;
f9ad6b62 6401
2168d7cc 6402 Stmts := New_List (Core_Loop);
70482933 6403
2168d7cc
AC
6404 if Exceptions_OK then
6405 Append_To (Stmts, Build_Raise_Statement (Final_Data));
6406 end if;
70482933 6407
2168d7cc
AC
6408 Block :=
6409 Make_Block_Statement (Loc,
6410 Declarations => Final_Decls,
6411 Handled_Statement_Sequence =>
6412 Make_Handled_Sequence_Of_Statements (Loc,
6413 Statements => Stmts));
70482933 6414
2168d7cc
AC
6415 -- Otherwise previous errors or a missing full view may prevent the
6416 -- proper freezing of the component type. If this is the case, there
6417 -- is no [Deep_]Adjust or [Deep_]Finalize primitive to call.
70482933 6418
2168d7cc
AC
6419 else
6420 Block := Make_Null_Statement (Loc);
df3e68b1 6421 end if;
70482933 6422
2168d7cc 6423 return New_List (Block);
df3e68b1
HK
6424 end Build_Adjust_Or_Finalize_Statements;
6425
6426 ---------------------------------
6427 -- Build_Initialize_Statements --
6428 ---------------------------------
6429
6430 function Build_Initialize_Statements (Typ : Entity_Id) return List_Id is
321c24f7
AC
6431 Comp_Typ : constant Entity_Id := Component_Type (Typ);
6432 Final_List : constant List_Id := New_List;
6433 Index_List : constant List_Id := New_List;
6434 Loc : constant Source_Ptr := Sloc (Typ);
6435 Num_Dims : constant Int := Number_Dimensions (Typ);
df3e68b1 6436
2168d7cc 6437 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id;
df3e68b1
HK
6438 -- Generate the following assignment:
6439 -- Counter := V'Length (1) *
6440 -- ...
6441 -- V'Length (N) - Counter;
2168d7cc
AC
6442 --
6443 -- Counter_Id denotes the entity of the counter.
df3e68b1
HK
6444
6445 function Build_Finalization_Call return Node_Id;
6446 -- Generate a deep finalization call for an array element
6447
d0ef7921
AC
6448 procedure Build_Indexes;
6449 -- Generate the initialization and finalization indexes used in the
df3e68b1
HK
6450 -- dimension loops.
6451
6452 function Build_Initialization_Call return Node_Id;
6453 -- Generate a deep initialization call for an array element
6454
2168d7cc
AC
6455 ----------------------
6456 -- Build_Assignment --
6457 ----------------------
df3e68b1 6458
2168d7cc 6459 function Build_Assignment (Counter_Id : Entity_Id) return Node_Id is
df3e68b1
HK
6460 Dim : Int;
6461 Expr : Node_Id;
70482933 6462
df3e68b1
HK
6463 begin
6464 -- Start from the first dimension and generate:
6465 -- V'Length (1)
70482933 6466
df3e68b1
HK
6467 Dim := 1;
6468 Expr :=
6469 Make_Attribute_Reference (Loc,
cfae2bed
AC
6470 Prefix => Make_Identifier (Loc, Name_V),
6471 Attribute_Name => Name_Length,
6472 Expressions => New_List (Make_Integer_Literal (Loc, Dim)));
df3e68b1
HK
6473
6474 -- Process the rest of the dimensions, generate:
6475 -- Expr * V'Length (N)
6476
6477 Dim := Dim + 1;
6478 while Dim <= Num_Dims loop
6479 Expr :=
6480 Make_Op_Multiply (Loc,
2c1b72d7 6481 Left_Opnd => Expr,
df3e68b1
HK
6482 Right_Opnd =>
6483 Make_Attribute_Reference (Loc,
2c1b72d7
AC
6484 Prefix => Make_Identifier (Loc, Name_V),
6485 Attribute_Name => Name_Length,
6486 Expressions => New_List (
df3e68b1
HK
6487 Make_Integer_Literal (Loc, Dim))));
6488
6489 Dim := Dim + 1;
6490 end loop;
70482933 6491
df3e68b1
HK
6492 -- Generate:
6493 -- Counter := Expr - Counter;
70482933 6494
df3e68b1
HK
6495 return
6496 Make_Assignment_Statement (Loc,
e4494292 6497 Name => New_Occurrence_Of (Counter_Id, Loc),
df3e68b1
HK
6498 Expression =>
6499 Make_Op_Subtract (Loc,
2c1b72d7 6500 Left_Opnd => Expr,
e4494292 6501 Right_Opnd => New_Occurrence_Of (Counter_Id, Loc)));
2168d7cc 6502 end Build_Assignment;
df3e68b1
HK
6503
6504 -----------------------------
6505 -- Build_Finalization_Call --
6506 -----------------------------
6507
6508 function Build_Finalization_Call return Node_Id is
6509 Comp_Ref : constant Node_Id :=
6510 Make_Indexed_Component (Loc,
2c1b72d7
AC
6511 Prefix => Make_Identifier (Loc, Name_V),
6512 Expressions => New_References_To (Final_List, Loc));
70482933 6513
df3e68b1
HK
6514 begin
6515 Set_Etype (Comp_Ref, Comp_Typ);
70482933 6516
df3e68b1
HK
6517 -- Generate:
6518 -- [Deep_]Finalize (V);
70482933 6519
2c1b72d7 6520 return Make_Final_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
df3e68b1 6521 end Build_Finalization_Call;
70482933 6522
df3e68b1 6523 -------------------
d0ef7921 6524 -- Build_Indexes --
df3e68b1 6525 -------------------
70482933 6526
d0ef7921 6527 procedure Build_Indexes is
df3e68b1
HK
6528 begin
6529 -- Generate the following identifiers:
6530 -- Jnn - for initialization
6531 -- Fnn - for finalization
f4d379b8 6532
df3e68b1
HK
6533 for Dim in 1 .. Num_Dims loop
6534 Append_To (Index_List,
6535 Make_Defining_Identifier (Loc, New_External_Name ('J', Dim)));
f4d379b8 6536
df3e68b1
HK
6537 Append_To (Final_List,
6538 Make_Defining_Identifier (Loc, New_External_Name ('F', Dim)));
6539 end loop;
d0ef7921 6540 end Build_Indexes;
70482933 6541
df3e68b1
HK
6542 -------------------------------
6543 -- Build_Initialization_Call --
6544 -------------------------------
70482933 6545
df3e68b1
HK
6546 function Build_Initialization_Call return Node_Id is
6547 Comp_Ref : constant Node_Id :=
6548 Make_Indexed_Component (Loc,
cfae2bed
AC
6549 Prefix => Make_Identifier (Loc, Name_V),
6550 Expressions => New_References_To (Index_List, Loc));
70482933 6551
df3e68b1
HK
6552 begin
6553 Set_Etype (Comp_Ref, Comp_Typ);
6554
6555 -- Generate:
6556 -- [Deep_]Initialize (V (J1, ..., JN));
70482933 6557
2c1b72d7 6558 return Make_Init_Call (Obj_Ref => Comp_Ref, Typ => Comp_Typ);
df3e68b1 6559 end Build_Initialization_Call;
70482933 6560
2168d7cc
AC
6561 -- Local variables
6562
6563 Counter_Id : Entity_Id;
6564 Dim : Int;
6565 F : Node_Id;
6566 Fin_Stmt : Node_Id;
6567 Final_Block : Node_Id;
6568 Final_Data : Finalization_Exception_Data;
6569 Final_Decls : List_Id := No_List;
6570 Final_Loop : Node_Id;
6571 Init_Block : Node_Id;
6572 Init_Call : Node_Id;
6573 Init_Loop : Node_Id;
6574 J : Node_Id;
6575 Loop_Id : Node_Id;
6576 Stmts : List_Id;
6577
df3e68b1 6578 -- Start of processing for Build_Initialize_Statements
70482933 6579
df3e68b1 6580 begin
2168d7cc
AC
6581 Counter_Id := Make_Temporary (Loc, 'C');
6582 Final_Decls := New_List;
70482933 6583
d0ef7921 6584 Build_Indexes;
2168d7cc 6585 Build_Object_Declarations (Final_Data, Final_Decls, Loc);
70482933 6586
df3e68b1
HK
6587 -- Generate the block which houses the finalization call, the index
6588 -- guard and the handler which triggers Program_Error later on.
6589
6590 -- if Counter > 0 then
6591 -- Counter := Counter - 1;
6592 -- else
7bf911b5 6593 -- begin
df3e68b1
HK
6594 -- [Deep_]Finalize (V (F1, ..., FN));
6595 -- exception
6596 -- when others =>
6597 -- if not Raised then
6598 -- Raised := True;
6599 -- Save_Occurrence (E, Get_Current_Excep.all.all);
6600 -- end if;
6601 -- end;
6602 -- end if;
6603
2168d7cc 6604 Fin_Stmt := Build_Finalization_Call;
df3e68b1 6605
2168d7cc
AC
6606 if Present (Fin_Stmt) then
6607 if Exceptions_OK then
6608 Fin_Stmt :=
6609 Make_Block_Statement (Loc,
6610 Handled_Statement_Sequence =>
6611 Make_Handled_Sequence_Of_Statements (Loc,
6612 Statements => New_List (Fin_Stmt),
6613 Exception_Handlers => New_List (
6614 Build_Exception_Handler (Final_Data))));
6615 end if;
df3e68b1 6616
2168d7cc
AC
6617 -- This is the core of the loop, the dimension iterators are added
6618 -- one by one in reverse.
70482933 6619
df3e68b1 6620 Final_Loop :=
2168d7cc
AC
6621 Make_If_Statement (Loc,
6622 Condition =>
6623 Make_Op_Gt (Loc,
6624 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
6625 Right_Opnd => Make_Integer_Literal (Loc, 0)),
6626
6627 Then_Statements => New_List (
6628 Make_Assignment_Statement (Loc,
6629 Name => New_Occurrence_Of (Counter_Id, Loc),
6630 Expression =>
6631 Make_Op_Subtract (Loc,
6632 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
6633 Right_Opnd => Make_Integer_Literal (Loc, 1)))),
6634
6635 Else_Statements => New_List (Fin_Stmt));
6636
6637 -- Generate all finalization loops starting from the innermost
6638 -- dimension.
6639
6640 -- for Fnn in reverse V'Range (Dim) loop
6641 -- <final loop>
6642 -- end loop;
6643
6644 F := Last (Final_List);
6645 Dim := Num_Dims;
6646 while Present (F) and then Dim > 0 loop
6647 Loop_Id := F;
6648 Prev (F);
6649 Remove (Loop_Id);
6650
6651 Final_Loop :=
6652 Make_Loop_Statement (Loc,
6653 Iteration_Scheme =>
6654 Make_Iteration_Scheme (Loc,
6655 Loop_Parameter_Specification =>
6656 Make_Loop_Parameter_Specification (Loc,
6657 Defining_Identifier => Loop_Id,
6658 Discrete_Subtype_Definition =>
6659 Make_Attribute_Reference (Loc,
6660 Prefix => Make_Identifier (Loc, Name_V),
6661 Attribute_Name => Name_Range,
6662 Expressions => New_List (
6663 Make_Integer_Literal (Loc, Dim))),
6664
6665 Reverse_Present => True)),
6666
6667 Statements => New_List (Final_Loop),
6668 End_Label => Empty);
6669
6670 Dim := Dim - 1;
6671 end loop;
70482933 6672
2168d7cc
AC
6673 -- Generate the block which contains the finalization loops, the
6674 -- declarations of the abort flag, the exception occurrence, the
6675 -- raised flag and the conditional raise.
70482933 6676
2168d7cc
AC
6677 -- declare
6678 -- Abort : constant Boolean := Triggered_By_Abort;
6679 -- <or>
6680 -- Abort : constant Boolean := False; -- no abort
70482933 6681
2168d7cc
AC
6682 -- E : Exception_Occurrence;
6683 -- Raised : Boolean := False;
70482933 6684
2168d7cc
AC
6685 -- begin
6686 -- Counter :=
6687 -- V'Length (1) *
6688 -- ...
6689 -- V'Length (N) - Counter;
70482933 6690
2168d7cc 6691 -- <final loop>
f9ad6b62 6692
2168d7cc
AC
6693 -- if Raised and then not Abort then
6694 -- Raise_From_Controlled_Operation (E);
6695 -- end if;
70482933 6696
2168d7cc
AC
6697 -- raise;
6698 -- end;
70482933 6699
2168d7cc 6700 Stmts := New_List (Build_Assignment (Counter_Id), Final_Loop);
70482933 6701
2168d7cc
AC
6702 if Exceptions_OK then
6703 Append_To (Stmts, Build_Raise_Statement (Final_Data));
6704 Append_To (Stmts, Make_Raise_Statement (Loc));
6705 end if;
70482933 6706
2168d7cc
AC
6707 Final_Block :=
6708 Make_Block_Statement (Loc,
6709 Declarations => Final_Decls,
6710 Handled_Statement_Sequence =>
6711 Make_Handled_Sequence_Of_Statements (Loc,
6712 Statements => Stmts));
70482933 6713
2168d7cc
AC
6714 -- Otherwise previous errors or a missing full view may prevent the
6715 -- proper freezing of the component type. If this is the case, there
6716 -- is no [Deep_]Finalize primitive to call.
df3e68b1 6717
2168d7cc
AC
6718 else
6719 Final_Block := Make_Null_Statement (Loc);
70482933
RK
6720 end if;
6721
df3e68b1
HK
6722 -- Generate the block which contains the initialization call and
6723 -- the partial finalization code.
70482933 6724
df3e68b1
HK
6725 -- begin
6726 -- [Deep_]Initialize (V (J1, ..., JN));
70482933 6727
df3e68b1 6728 -- Counter := Counter + 1;
70482933 6729
df3e68b1
HK
6730 -- exception
6731 -- when others =>
6732 -- <finalization code>
6733 -- end;
70482933 6734
2168d7cc 6735 Init_Call := Build_Initialization_Call;
70482933 6736
097826df
GD
6737 -- Only create finalization block if there is a nontrivial call
6738 -- to initialization or a Default_Initial_Condition check to be
6739 -- performed.
6740
6741 if (Present (Init_Call)
6742 and then Nkind (Init_Call) /= N_Null_Statement)
6743 or else
6744 (Has_DIC (Comp_Typ)
6745 and then not GNATprove_Mode
6746 and then Present (DIC_Procedure (Comp_Typ))
6747 and then not Has_Null_Body (DIC_Procedure (Comp_Typ)))
1804faa4 6748 then
097826df
GD
6749 declare
6750 Init_Stmts : constant List_Id := New_List;
6751
6752 begin
6753 if Present (Init_Call) then
6754 Append_To (Init_Stmts, Init_Call);
6755 end if;
6756
6757 if Has_DIC (Comp_Typ)
6758 and then Present (DIC_Procedure (Comp_Typ))
6759 then
6760 Append_To
6761 (Init_Stmts,
6762 Build_DIC_Call (Loc,
6763 Make_Indexed_Component (Loc,
6764 Prefix => Make_Identifier (Loc, Name_V),
6765 Expressions => New_References_To (Index_List, Loc)),
6766 Comp_Typ));
6767 end if;
6768
6769 Init_Loop :=
6770 Make_Block_Statement (Loc,
6771 Handled_Statement_Sequence =>
6772 Make_Handled_Sequence_Of_Statements (Loc,
6773 Statements => Init_Stmts,
6774 Exception_Handlers => New_List (
6775 Make_Exception_Handler (Loc,
6776 Exception_Choices => New_List (
6777 Make_Others_Choice (Loc)),
6778 Statements => New_List (Final_Block)))));
6779 end;
5d09245e 6780
2168d7cc
AC
6781 Append_To (Statements (Handled_Statement_Sequence (Init_Loop)),
6782 Make_Assignment_Statement (Loc,
6783 Name => New_Occurrence_Of (Counter_Id, Loc),
6784 Expression =>
6785 Make_Op_Add (Loc,
6786 Left_Opnd => New_Occurrence_Of (Counter_Id, Loc),
6787 Right_Opnd => Make_Integer_Literal (Loc, 1))));
6788
6789 -- Generate all initialization loops starting from the innermost
6790 -- dimension.
6791
6792 -- for Jnn in V'Range (Dim) loop
6793 -- <init loop>
6794 -- end loop;
6795
6796 J := Last (Index_List);
6797 Dim := Num_Dims;
6798 while Present (J) and then Dim > 0 loop
6799 Loop_Id := J;
6800 Prev (J);
6801 Remove (Loop_Id);
6802
6803 Init_Loop :=
6804 Make_Loop_Statement (Loc,
6805 Iteration_Scheme =>
6806 Make_Iteration_Scheme (Loc,
6807 Loop_Parameter_Specification =>
6808 Make_Loop_Parameter_Specification (Loc,
6809 Defining_Identifier => Loop_Id,
6810 Discrete_Subtype_Definition =>
6811 Make_Attribute_Reference (Loc,
6812 Prefix => Make_Identifier (Loc, Name_V),
6813 Attribute_Name => Name_Range,
6814 Expressions => New_List (
6815 Make_Integer_Literal (Loc, Dim))))),
6816
6817 Statements => New_List (Init_Loop),
6818 End_Label => Empty);
6819
6820 Dim := Dim - 1;
6821 end loop;
70482933 6822
2168d7cc
AC
6823 -- Generate the block which contains the counter variable and the
6824 -- initialization loops.
70482933 6825
2168d7cc
AC
6826 -- declare
6827 -- Counter : Integer := 0;
6828 -- begin
6829 -- <init loop>
6830 -- end;
70482933 6831
2168d7cc
AC
6832 Init_Block :=
6833 Make_Block_Statement (Loc,
cfae2bed 6834 Declarations => New_List (
df3e68b1
HK
6835 Make_Object_Declaration (Loc,
6836 Defining_Identifier => Counter_Id,
2c1b72d7 6837 Object_Definition =>
e4494292 6838 New_Occurrence_Of (Standard_Integer, Loc),
2c1b72d7 6839 Expression => Make_Integer_Literal (Loc, 0))),
df3e68b1
HK
6840
6841 Handled_Statement_Sequence =>
6842 Make_Handled_Sequence_Of_Statements (Loc,
2168d7cc
AC
6843 Statements => New_List (Init_Loop)));
6844
bbf14e13
AC
6845 if Debug_Generated_Code then
6846 Set_Debug_Info_Needed (Counter_Id);
6847 end if;
6848
2168d7cc
AC
6849 -- Otherwise previous errors or a missing full view may prevent the
6850 -- proper freezing of the component type. If this is the case, there
6851 -- is no [Deep_]Initialize primitive to call.
6852
6853 else
6854 Init_Block := Make_Null_Statement (Loc);
6855 end if;
6856
6857 return New_List (Init_Block);
df3e68b1
HK
6858 end Build_Initialize_Statements;
6859
6860 -----------------------
6861 -- New_References_To --
6862 -----------------------
6863
6864 function New_References_To
6865 (L : List_Id;
6866 Loc : Source_Ptr) return List_Id
6867 is
6868 Refs : constant List_Id := New_List;
6869 Id : Node_Id;
70482933 6870
df3e68b1
HK
6871 begin
6872 Id := First (L);
6873 while Present (Id) loop
e4494292 6874 Append_To (Refs, New_Occurrence_Of (Id, Loc));
df3e68b1
HK
6875 Next (Id);
6876 end loop;
70482933 6877
df3e68b1
HK
6878 return Refs;
6879 end New_References_To;
70482933 6880
df3e68b1 6881 -- Start of processing for Make_Deep_Array_Body
70482933 6882
df3e68b1
HK
6883 begin
6884 case Prim is
6885 when Address_Case =>
6886 return Make_Finalize_Address_Stmts (Typ);
70482933 6887
d8f43ee6
HK
6888 when Adjust_Case
6889 | Finalize_Case
6890 =>
df3e68b1 6891 return Build_Adjust_Or_Finalize_Statements (Typ);
70482933 6892
df3e68b1
HK
6893 when Initialize_Case =>
6894 return Build_Initialize_Statements (Typ);
6895 end case;
6896 end Make_Deep_Array_Body;
70482933 6897
df3e68b1
HK
6898 --------------------
6899 -- Make_Deep_Proc --
6900 --------------------
fbf5a39b 6901
df3e68b1
HK
6902 function Make_Deep_Proc
6903 (Prim : Final_Primitives;
6904 Typ : Entity_Id;
6905 Stmts : List_Id) return Entity_Id
6906 is
6907 Loc : constant Source_Ptr := Sloc (Typ);
6908 Formals : List_Id;
6909 Proc_Id : Entity_Id;
fbf5a39b 6910
df3e68b1
HK
6911 begin
6912 -- Create the object formal, generate:
6913 -- V : System.Address
70482933 6914
df3e68b1
HK
6915 if Prim = Address_Case then
6916 Formals := New_List (
6917 Make_Parameter_Specification (Loc,
2c1b72d7 6918 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
e4494292
RD
6919 Parameter_Type =>
6920 New_Occurrence_Of (RTE (RE_Address), Loc)));
70482933 6921
df3e68b1 6922 -- Default case
dfd99a80 6923
df3e68b1
HK
6924 else
6925 -- V : in out Typ
6926
6927 Formals := New_List (
6928 Make_Parameter_Specification (Loc,
2c1b72d7
AC
6929 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
6930 In_Present => True,
6931 Out_Present => True,
e4494292 6932 Parameter_Type => New_Occurrence_Of (Typ, Loc)));
dfd99a80 6933
df3e68b1
HK
6934 -- F : Boolean := True
6935
6936 if Prim = Adjust_Case
6937 or else Prim = Finalize_Case
6938 then
6939 Append_To (Formals,
6940 Make_Parameter_Specification (Loc,
2c1b72d7
AC
6941 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
6942 Parameter_Type =>
e4494292 6943 New_Occurrence_Of (Standard_Boolean, Loc),
2c1b72d7 6944 Expression =>
e4494292 6945 New_Occurrence_Of (Standard_True, Loc)));
dfd99a80
TQ
6946 end if;
6947 end if;
6948
df3e68b1
HK
6949 Proc_Id :=
6950 Make_Defining_Identifier (Loc,
6951 Chars => Make_TSS_Name (Typ, Deep_Name_Of (Prim)));
70482933 6952
df3e68b1
HK
6953 -- Generate:
6954 -- procedure Deep_Initialize / Adjust / Finalize (V : in out <typ>) is
6955 -- begin
6956 -- <stmts>
6957 -- exception -- Finalize and Adjust cases only
6958 -- raise Program_Error;
6959 -- end Deep_Initialize / Adjust / Finalize;
70482933 6960
df3e68b1 6961 -- or
70482933 6962
df3e68b1
HK
6963 -- procedure Finalize_Address (V : System.Address) is
6964 -- begin
6965 -- <stmts>
6966 -- end Finalize_Address;
70482933 6967
df3e68b1
HK
6968 Discard_Node (
6969 Make_Subprogram_Body (Loc,
6970 Specification =>
6971 Make_Procedure_Specification (Loc,
6972 Defining_Unit_Name => Proc_Id,
6973 Parameter_Specifications => Formals),
70482933 6974
df3e68b1 6975 Declarations => Empty_List,
70482933 6976
df3e68b1 6977 Handled_Statement_Sequence =>
2c1b72d7 6978 Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts)));
70482933 6979
1804faa4
AC
6980 -- If there are no calls to component initialization, indicate that
6981 -- the procedure is trivial, so prevent calls to it.
6982
6983 if Is_Empty_List (Stmts)
6984 or else Nkind (First (Stmts)) = N_Null_Statement
6985 then
6986 Set_Is_Trivial_Subprogram (Proc_Id);
6987 end if;
6988
df3e68b1
HK
6989 return Proc_Id;
6990 end Make_Deep_Proc;
70482933 6991
df3e68b1
HK
6992 ---------------------------
6993 -- Make_Deep_Record_Body --
6994 ---------------------------
70482933 6995
df3e68b1
HK
6996 function Make_Deep_Record_Body
6997 (Prim : Final_Primitives;
6998 Typ : Entity_Id;
6999 Is_Local : Boolean := False) return List_Id
7000 is
7001 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id;
7002 -- Build the statements necessary to adjust a record type. The type may
7003 -- have discriminants and contain variant parts. Generate:
cfae2bed 7004 --
df3e68b1 7005 -- begin
df3e68b1
HK
7006 -- begin
7007 -- [Deep_]Adjust (V.Comp_1);
7008 -- exception
7009 -- when Id : others =>
7010 -- if not Raised then
7011 -- Raised := True;
7012 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7013 -- end if;
7014 -- end;
7015 -- . . .
7016 -- begin
7017 -- [Deep_]Adjust (V.Comp_N);
7018 -- exception
7019 -- when Id : others =>
7020 -- if not Raised then
7021 -- Raised := True;
7022 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7023 -- end if;
7024 -- end;
cfae2bed 7025 --
df3e68b1
HK
7026 -- begin
7027 -- Deep_Adjust (V._parent, False); -- If applicable
7028 -- exception
7029 -- when Id : others =>
7030 -- if not Raised then
7031 -- Raised := True;
7032 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7033 -- end if;
7034 -- end;
cfae2bed 7035 --
df3e68b1
HK
7036 -- if F then
7037 -- begin
7038 -- Adjust (V); -- If applicable
7039 -- exception
7040 -- when others =>
7041 -- if not Raised then
7042 -- Raised := True;
7f37fff1 7043 -- Save_Occurrence (E, Get_Current_Excep.all.all);
df3e68b1
HK
7044 -- end if;
7045 -- end;
7046 -- end if;
cfae2bed 7047 --
ca5af305
AC
7048 -- if Raised and then not Abort then
7049 -- Raise_From_Controlled_Operation (E);
df3e68b1
HK
7050 -- end if;
7051 -- end;
7052
7053 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id;
7054 -- Build the statements necessary to finalize a record type. The type
7055 -- may have discriminants and contain variant parts. Generate:
cfae2bed 7056 --
df3e68b1 7057 -- declare
14848f57 7058 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
7059 -- <or>
7060 -- Abort : constant Boolean := False; -- no abort
7f37fff1 7061 -- E : Exception_Occurrence;
df3e68b1 7062 -- Raised : Boolean := False;
cfae2bed 7063 --
df3e68b1 7064 -- begin
df3e68b1
HK
7065 -- if F then
7066 -- begin
7067 -- Finalize (V); -- If applicable
7068 -- exception
7069 -- when others =>
7070 -- if not Raised then
7071 -- Raised := True;
7f37fff1 7072 -- Save_Occurrence (E, Get_Current_Excep.all.all);
df3e68b1
HK
7073 -- end if;
7074 -- end;
7075 -- end if;
cfae2bed 7076 --
df3e68b1
HK
7077 -- case Variant_1 is
7078 -- when Value_1 =>
7079 -- case State_Counter_N => -- If Is_Local is enabled
7080 -- when N => .
7081 -- goto LN; .
7082 -- ... .
7083 -- when 1 => .
7084 -- goto L1; .
7085 -- when others => .
7086 -- goto L0; .
7087 -- end case; .
cfae2bed 7088 --
df3e68b1
HK
7089 -- <<LN>> -- If Is_Local is enabled
7090 -- begin
7091 -- [Deep_]Finalize (V.Comp_N);
7092 -- exception
7093 -- when others =>
7094 -- if not Raised then
7095 -- Raised := True;
7f37fff1 7096 -- Save_Occurrence (E, Get_Current_Excep.all.all);
df3e68b1
HK
7097 -- end if;
7098 -- end;
7099 -- . . .
7100 -- <<L1>>
7101 -- begin
7102 -- [Deep_]Finalize (V.Comp_1);
7103 -- exception
7104 -- when others =>
7105 -- if not Raised then
7106 -- Raised := True;
7f37fff1 7107 -- Save_Occurrence (E, Get_Current_Excep.all.all);
df3e68b1
HK
7108 -- end if;
7109 -- end;
7110 -- <<L0>>
7111 -- end case;
cfae2bed 7112 --
df3e68b1
HK
7113 -- case State_Counter_1 => -- If Is_Local is enabled
7114 -- when M => .
7115 -- goto LM; .
7116 -- ...
cfae2bed 7117 --
df3e68b1
HK
7118 -- begin
7119 -- Deep_Finalize (V._parent, False); -- If applicable
7120 -- exception
7121 -- when Id : others =>
7122 -- if not Raised then
7123 -- Raised := True;
7124 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7125 -- end if;
7126 -- end;
cfae2bed 7127 --
ca5af305
AC
7128 -- if Raised and then not Abort then
7129 -- Raise_From_Controlled_Operation (E);
df3e68b1
HK
7130 -- end if;
7131 -- end;
7132
7133 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id;
7134 -- Given a derived tagged type Typ, traverse all components, find field
7135 -- _parent and return its type.
7136
7137 procedure Preprocess_Components
7138 (Comps : Node_Id;
b3143037 7139 Num_Comps : out Nat;
df3e68b1
HK
7140 Has_POC : out Boolean);
7141 -- Examine all components in component list Comps, count all controlled
7142 -- components and determine whether at least one of them is per-object
7143 -- constrained. Component _parent is always skipped.
7144
7145 -----------------------------
7146 -- Build_Adjust_Statements --
7147 -----------------------------
7148
7149 function Build_Adjust_Statements (Typ : Entity_Id) return List_Id is
321c24f7
AC
7150 Loc : constant Source_Ptr := Sloc (Typ);
7151 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
7bf911b5 7152
321c24f7 7153 Finalizer_Data : Finalization_Exception_Data;
df3e68b1 7154
df3e68b1
HK
7155 function Process_Component_List_For_Adjust
7156 (Comps : Node_Id) return List_Id;
7157 -- Build all necessary adjust statements for a single component list
7158
7159 ---------------------------------------
7160 -- Process_Component_List_For_Adjust --
7161 ---------------------------------------
7162
7163 function Process_Component_List_For_Adjust
7164 (Comps : Node_Id) return List_Id
7165 is
2168d7cc 7166 Stmts : constant List_Id := New_List;
df3e68b1
HK
7167
7168 procedure Process_Component_For_Adjust (Decl : Node_Id);
7169 -- Process the declaration of a single controlled component
7170
7171 ----------------------------------
7172 -- Process_Component_For_Adjust --
7173 ----------------------------------
7174
7175 procedure Process_Component_For_Adjust (Decl : Node_Id) is
2168d7cc
AC
7176 Id : constant Entity_Id := Defining_Identifier (Decl);
7177 Typ : constant Entity_Id := Etype (Id);
7178
7179 Adj_Call : Node_Id;
70482933 7180
df3e68b1 7181 begin
7bf911b5 7182 -- begin
df3e68b1 7183 -- [Deep_]Adjust (V.Id);
7bf911b5 7184
df3e68b1
HK
7185 -- exception
7186 -- when others =>
7187 -- if not Raised then
7188 -- Raised := True;
7189 -- Save_Occurrence (E, Get_Current_Excep.all.all);
7190 -- end if;
7191 -- end;
7192
2168d7cc 7193 Adj_Call :=
df3e68b1
HK
7194 Make_Adjust_Call (
7195 Obj_Ref =>
7196 Make_Selected_Component (Loc,
cfae2bed
AC
7197 Prefix => Make_Identifier (Loc, Name_V),
7198 Selector_Name => Make_Identifier (Loc, Chars (Id))),
7199 Typ => Typ);
df3e68b1 7200
2168d7cc
AC
7201 -- Guard against a missing [Deep_]Adjust when the component
7202 -- type was not properly frozen.
7203
7204 if Present (Adj_Call) then
7205 if Exceptions_OK then
7206 Adj_Call :=
7207 Make_Block_Statement (Loc,
7208 Handled_Statement_Sequence =>
7209 Make_Handled_Sequence_Of_Statements (Loc,
7210 Statements => New_List (Adj_Call),
7211 Exception_Handlers => New_List (
7212 Build_Exception_Handler (Finalizer_Data))));
7213 end if;
70482933 7214
2168d7cc
AC
7215 Append_To (Stmts, Adj_Call);
7216 end if;
df3e68b1 7217 end Process_Component_For_Adjust;
70482933 7218
2168d7cc
AC
7219 -- Local variables
7220
7221 Decl : Node_Id;
7222 Decl_Id : Entity_Id;
7223 Decl_Typ : Entity_Id;
7224 Has_POC : Boolean;
7225 Num_Comps : Nat;
321c24f7 7226 Var_Case : Node_Id;
2168d7cc 7227
df3e68b1 7228 -- Start of processing for Process_Component_List_For_Adjust
70482933 7229
df3e68b1
HK
7230 begin
7231 -- Perform an initial check, determine the number of controlled
7232 -- components in the current list and whether at least one of them
7233 -- is per-object constrained.
70482933 7234
df3e68b1 7235 Preprocess_Components (Comps, Num_Comps, Has_POC);
70482933 7236
df3e68b1
HK
7237 -- The processing in this routine is done in the following order:
7238 -- 1) Regular components
7239 -- 2) Per-object constrained components
7240 -- 3) Variant parts
70482933 7241
df3e68b1 7242 if Num_Comps > 0 then
70482933 7243
df3e68b1 7244 -- Process all regular components in order of declarations
70482933 7245
df3e68b1
HK
7246 Decl := First_Non_Pragma (Component_Items (Comps));
7247 while Present (Decl) loop
7248 Decl_Id := Defining_Identifier (Decl);
7249 Decl_Typ := Etype (Decl_Id);
70482933 7250
df3e68b1 7251 -- Skip _parent as well as per-object constrained components
70482933 7252
df3e68b1
HK
7253 if Chars (Decl_Id) /= Name_uParent
7254 and then Needs_Finalization (Decl_Typ)
7255 then
7256 if Has_Access_Constraint (Decl_Id)
7257 and then No (Expression (Decl))
7258 then
7259 null;
7260 else
7261 Process_Component_For_Adjust (Decl);
7262 end if;
7263 end if;
70482933 7264
df3e68b1
HK
7265 Next_Non_Pragma (Decl);
7266 end loop;
70482933 7267
df3e68b1
HK
7268 -- Process all per-object constrained components in order of
7269 -- declarations.
70482933 7270
df3e68b1
HK
7271 if Has_POC then
7272 Decl := First_Non_Pragma (Component_Items (Comps));
7273 while Present (Decl) loop
7274 Decl_Id := Defining_Identifier (Decl);
7275 Decl_Typ := Etype (Decl_Id);
70482933 7276
df3e68b1 7277 -- Skip _parent
70482933 7278
df3e68b1
HK
7279 if Chars (Decl_Id) /= Name_uParent
7280 and then Needs_Finalization (Decl_Typ)
7281 and then Has_Access_Constraint (Decl_Id)
7282 and then No (Expression (Decl))
7283 then
7284 Process_Component_For_Adjust (Decl);
7285 end if;
70482933 7286
df3e68b1
HK
7287 Next_Non_Pragma (Decl);
7288 end loop;
7289 end if;
70482933
RK
7290 end if;
7291
df3e68b1 7292 -- Process all variants, if any
70482933 7293
df3e68b1
HK
7294 Var_Case := Empty;
7295 if Present (Variant_Part (Comps)) then
7296 declare
7297 Var_Alts : constant List_Id := New_List;
7298 Var : Node_Id;
70482933 7299
df3e68b1
HK
7300 begin
7301 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
7302 while Present (Var) loop
7303
7304 -- Generate:
7305 -- when <discrete choices> =>
7306 -- <adjust statements>
7307
7308 Append_To (Var_Alts,
7309 Make_Case_Statement_Alternative (Loc,
7310 Discrete_Choices =>
7311 New_Copy_List (Discrete_Choices (Var)),
2c1b72d7 7312 Statements =>
df3e68b1
HK
7313 Process_Component_List_For_Adjust (
7314 Component_List (Var))));
7315
7316 Next_Non_Pragma (Var);
7317 end loop;
7318
7319 -- Generate:
7320 -- case V.<discriminant> is
7321 -- when <discrete choices 1> =>
7322 -- <adjust statements 1>
7323 -- ...
7324 -- when <discrete choices N> =>
7325 -- <adjust statements N>
7326 -- end case;
7327
7328 Var_Case :=
7329 Make_Case_Statement (Loc,
7330 Expression =>
7331 Make_Selected_Component (Loc,
2c1b72d7 7332 Prefix => Make_Identifier (Loc, Name_V),
df3e68b1
HK
7333 Selector_Name =>
7334 Make_Identifier (Loc,
2c1b72d7 7335 Chars => Chars (Name (Variant_Part (Comps))))),
df3e68b1
HK
7336 Alternatives => Var_Alts);
7337 end;
7338 end if;
70482933 7339
df3e68b1 7340 -- Add the variant case statement to the list of statements
70482933 7341
df3e68b1
HK
7342 if Present (Var_Case) then
7343 Append_To (Stmts, Var_Case);
7344 end if;
70482933 7345
df3e68b1
HK
7346 -- If the component list did not have any controlled components
7347 -- nor variants, return null.
c364d9be 7348
df3e68b1
HK
7349 if Is_Empty_List (Stmts) then
7350 Append_To (Stmts, Make_Null_Statement (Loc));
7351 end if;
c364d9be 7352
df3e68b1
HK
7353 return Stmts;
7354 end Process_Component_List_For_Adjust;
70482933 7355
321c24f7
AC
7356 -- Local variables
7357
a6d25cad 7358 Bod_Stmts : List_Id := No_List;
321c24f7
AC
7359 Finalizer_Decls : List_Id := No_List;
7360 Rec_Def : Node_Id;
7361
df3e68b1 7362 -- Start of processing for Build_Adjust_Statements
70482933 7363
df3e68b1 7364 begin
2d1debf8
AC
7365 Finalizer_Decls := New_List;
7366 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
70482933 7367
df3e68b1
HK
7368 if Nkind (Typ_Def) = N_Derived_Type_Definition then
7369 Rec_Def := Record_Extension_Part (Typ_Def);
7370 else
7371 Rec_Def := Typ_Def;
7372 end if;
70482933 7373
df3e68b1 7374 -- Create an adjust sequence for all record components
c364d9be 7375
df3e68b1
HK
7376 if Present (Component_List (Rec_Def)) then
7377 Bod_Stmts :=
7378 Process_Component_List_For_Adjust (Component_List (Rec_Def));
7379 end if;
8a7988f5 7380
df3e68b1
HK
7381 -- A derived record type must adjust all inherited components. This
7382 -- action poses the following problem:
886b5a18 7383
df3e68b1
HK
7384 -- procedure Deep_Adjust (Obj : in out Parent_Typ) is
7385 -- begin
7386 -- Adjust (Obj);
7387 -- ...
886b5a18 7388
df3e68b1
HK
7389 -- procedure Deep_Adjust (Obj : in out Derived_Typ) is
7390 -- begin
7391 -- Deep_Adjust (Obj._parent);
7392 -- ...
7393 -- Adjust (Obj);
7394 -- ...
886b5a18 7395
df3e68b1
HK
7396 -- Adjusting the derived type will invoke Adjust of the parent and
7397 -- then that of the derived type. This is undesirable because both
7398 -- routines may modify shared components. Only the Adjust of the
7399 -- derived type should be invoked.
886b5a18 7400
df3e68b1
HK
7401 -- To prevent this double adjustment of shared components,
7402 -- Deep_Adjust uses a flag to control the invocation of Adjust:
886b5a18 7403
df3e68b1
HK
7404 -- procedure Deep_Adjust
7405 -- (Obj : in out Some_Type;
7406 -- Flag : Boolean := True)
7407 -- is
7408 -- begin
7409 -- if Flag then
7410 -- Adjust (Obj);
7411 -- end if;
7412 -- ...
886b5a18 7413
7c092960 7414 -- When Deep_Adjust is invoked for field _parent, a value of False is
df3e68b1 7415 -- provided for the flag:
886b5a18 7416
df3e68b1
HK
7417 -- Deep_Adjust (Obj._parent, False);
7418
cfae2bed 7419 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
df3e68b1
HK
7420 declare
7421 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
7422 Adj_Stmt : Node_Id;
7423 Call : Node_Id;
c364d9be 7424
df3e68b1
HK
7425 begin
7426 if Needs_Finalization (Par_Typ) then
7427 Call :=
2c1b72d7 7428 Make_Adjust_Call
4ac2bbbd 7429 (Obj_Ref =>
2c1b72d7
AC
7430 Make_Selected_Component (Loc,
7431 Prefix => Make_Identifier (Loc, Name_V),
7432 Selector_Name =>
7433 Make_Identifier (Loc, Name_uParent)),
4ac2bbbd
AC
7434 Typ => Par_Typ,
7435 Skip_Self => True);
df3e68b1
HK
7436
7437 -- Generate:
7bf911b5 7438 -- begin
df3e68b1 7439 -- Deep_Adjust (V._parent, False);
7bf911b5 7440
df3e68b1
HK
7441 -- exception
7442 -- when Id : others =>
7443 -- if not Raised then
7444 -- Raised := True;
7445 -- Save_Occurrence (E,
7446 -- Get_Current_Excep.all.all);
7447 -- end if;
7448 -- end;
7449
7450 if Present (Call) then
7451 Adj_Stmt := Call;
7452
7453 if Exceptions_OK then
7454 Adj_Stmt :=
7455 Make_Block_Statement (Loc,
7456 Handled_Statement_Sequence =>
7457 Make_Handled_Sequence_Of_Statements (Loc,
2c1b72d7 7458 Statements => New_List (Adj_Stmt),
df3e68b1 7459 Exception_Handlers => New_List (
886b5a18 7460 Build_Exception_Handler (Finalizer_Data))));
df3e68b1 7461 end if;
70482933 7462
df3e68b1
HK
7463 Prepend_To (Bod_Stmts, Adj_Stmt);
7464 end if;
7465 end if;
7466 end;
70482933
RK
7467 end if;
7468
df3e68b1
HK
7469 -- Adjust the object. This action must be performed last after all
7470 -- components have been adjusted.
7471
7472 if Is_Controlled (Typ) then
7473 declare
7474 Adj_Stmt : Node_Id;
7475 Proc : Entity_Id;
8a7988f5 7476
df3e68b1 7477 begin
ca811241 7478 Proc := Find_Optional_Prim_Op (Typ, Name_Adjust);
df3e68b1
HK
7479
7480 -- Generate:
7481 -- if F then
7bf911b5 7482 -- begin
df3e68b1 7483 -- Adjust (V);
7bf911b5 7484
df3e68b1
HK
7485 -- exception
7486 -- when others =>
7487 -- if not Raised then
7488 -- Raised := True;
7489 -- Save_Occurrence (E,
7490 -- Get_Current_Excep.all.all);
7491 -- end if;
7492 -- end;
7493 -- end if;
7494
7495 if Present (Proc) then
7496 Adj_Stmt :=
7497 Make_Procedure_Call_Statement (Loc,
e4494292 7498 Name => New_Occurrence_Of (Proc, Loc),
df3e68b1
HK
7499 Parameter_Associations => New_List (
7500 Make_Identifier (Loc, Name_V)));
7501
7502 if Exceptions_OK then
7503 Adj_Stmt :=
7504 Make_Block_Statement (Loc,
7505 Handled_Statement_Sequence =>
7506 Make_Handled_Sequence_Of_Statements (Loc,
2c1b72d7 7507 Statements => New_List (Adj_Stmt),
df3e68b1
HK
7508 Exception_Handlers => New_List (
7509 Build_Exception_Handler
36b8f95f 7510 (Finalizer_Data))));
df3e68b1 7511 end if;
70482933 7512
df3e68b1
HK
7513 Append_To (Bod_Stmts,
7514 Make_If_Statement (Loc,
2c1b72d7 7515 Condition => Make_Identifier (Loc, Name_F),
df3e68b1
HK
7516 Then_Statements => New_List (Adj_Stmt)));
7517 end if;
7518 end;
70482933
RK
7519 end if;
7520
df3e68b1
HK
7521 -- At this point either all adjustment statements have been generated
7522 -- or the type is not controlled.
70482933 7523
df3e68b1
HK
7524 if Is_Empty_List (Bod_Stmts) then
7525 Append_To (Bod_Stmts, Make_Null_Statement (Loc));
70482933 7526
df3e68b1 7527 return Bod_Stmts;
70482933 7528
df3e68b1
HK
7529 -- Generate:
7530 -- declare
14848f57 7531 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
7532 -- <or>
7533 -- Abort : constant Boolean := False; -- no abort
7534
7f37fff1 7535 -- E : Exception_Occurrence;
df3e68b1 7536 -- Raised : Boolean := False;
70482933 7537
df3e68b1 7538 -- begin
df3e68b1 7539 -- <adjust statements>
70482933 7540
ca5af305
AC
7541 -- if Raised and then not Abort then
7542 -- Raise_From_Controlled_Operation (E);
df3e68b1
HK
7543 -- end if;
7544 -- end;
70482933 7545
df3e68b1
HK
7546 else
7547 if Exceptions_OK then
7bf911b5 7548 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
df3e68b1 7549 end if;
70482933 7550
df3e68b1
HK
7551 return
7552 New_List (
7553 Make_Block_Statement (Loc,
2c1b72d7 7554 Declarations =>
36b8f95f 7555 Finalizer_Decls,
df3e68b1 7556 Handled_Statement_Sequence =>
2c1b72d7 7557 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
df3e68b1
HK
7558 end if;
7559 end Build_Adjust_Statements;
7560
7561 -------------------------------
7562 -- Build_Finalize_Statements --
7563 -------------------------------
7564
7565 function Build_Finalize_Statements (Typ : Entity_Id) return List_Id is
321c24f7
AC
7566 Loc : constant Source_Ptr := Sloc (Typ);
7567 Typ_Def : constant Node_Id := Type_Definition (Parent (Typ));
7bf911b5 7568
02248717 7569 Counter : Nat := 0;
321c24f7 7570 Finalizer_Data : Finalization_Exception_Data;
7c88e46a 7571 Last_POC_Call : Node_Id := Empty;
df3e68b1 7572
df3e68b1 7573 function Process_Component_List_For_Finalize
7c88e46a
SB
7574 (Comps : Node_Id;
7575 In_Variant_Part : Boolean := False) return List_Id;
df3e68b1
HK
7576 -- Build all necessary finalization statements for a single component
7577 -- list. The statements may include a jump circuitry if flag Is_Local
7c88e46a
SB
7578 -- is enabled. In_Variant_Part indicates whether this is a recursive
7579 -- call.
df3e68b1
HK
7580
7581 -----------------------------------------
7582 -- Process_Component_List_For_Finalize --
7583 -----------------------------------------
7584
7585 function Process_Component_List_For_Finalize
7c88e46a
SB
7586 (Comps : Node_Id;
7587 In_Variant_Part : Boolean := False) return List_Id
df3e68b1 7588 is
df3e68b1 7589 procedure Process_Component_For_Finalize
7e6060af
AC
7590 (Decl : Node_Id;
7591 Alts : List_Id;
7592 Decls : List_Id;
7593 Stmts : List_Id;
7594 Num_Comps : in out Nat);
df3e68b1
HK
7595 -- Process the declaration of a single controlled component. If
7596 -- flag Is_Local is enabled, create the corresponding label and
7597 -- jump circuitry. Alts is the list of case alternatives, Decls
7598 -- is the top level declaration list where labels are declared
7e6060af
AC
7599 -- and Stmts is the list of finalization actions. Num_Comps
7600 -- denotes the current number of components needing finalization.
df3e68b1
HK
7601
7602 ------------------------------------
7603 -- Process_Component_For_Finalize --
7604 ------------------------------------
7605
7606 procedure Process_Component_For_Finalize
7e6060af
AC
7607 (Decl : Node_Id;
7608 Alts : List_Id;
7609 Decls : List_Id;
7610 Stmts : List_Id;
7611 Num_Comps : in out Nat)
df3e68b1
HK
7612 is
7613 Id : constant Entity_Id := Defining_Identifier (Decl);
7614 Typ : constant Entity_Id := Etype (Id);
2168d7cc 7615 Fin_Call : Node_Id;
70482933 7616
df3e68b1
HK
7617 begin
7618 if Is_Local then
7619 declare
7620 Label : Node_Id;
7621 Label_Id : Entity_Id;
7622
7623 begin
7624 -- Generate:
7625 -- LN : label;
7626
7627 Label_Id :=
7628 Make_Identifier (Loc,
7629 Chars => New_External_Name ('L', Num_Comps));
7630 Set_Entity (Label_Id,
7631 Make_Defining_Identifier (Loc, Chars (Label_Id)));
7632 Label := Make_Label (Loc, Label_Id);
7633
7634 Append_To (Decls,
7635 Make_Implicit_Label_Declaration (Loc,
7636 Defining_Identifier => Entity (Label_Id),
2c1b72d7 7637 Label_Construct => Label));
df3e68b1
HK
7638
7639 -- Generate:
7640 -- when N =>
7641 -- goto LN;
7642
7643 Append_To (Alts,
7644 Make_Case_Statement_Alternative (Loc,
7645 Discrete_Choices => New_List (
7646 Make_Integer_Literal (Loc, Num_Comps)),
7647
7648 Statements => New_List (
7649 Make_Goto_Statement (Loc,
7650 Name =>
e4494292 7651 New_Occurrence_Of (Entity (Label_Id), Loc)))));
df3e68b1
HK
7652
7653 -- Generate:
7654 -- <<LN>>
7655
7656 Append_To (Stmts, Label);
7657
7658 -- Decrease the number of components to be processed.
7659 -- This action yields a new Label_Id in future calls.
7660
7661 Num_Comps := Num_Comps - 1;
7662 end;
7663 end if;
70482933 7664
df3e68b1
HK
7665 -- Generate:
7666 -- [Deep_]Finalize (V.Id); -- No_Exception_Propagation
7667
7668 -- begin -- Exception handlers allowed
7669 -- [Deep_]Finalize (V.Id);
7670 -- exception
7671 -- when others =>
7672 -- if not Raised then
7673 -- Raised := True;
7674 -- Save_Occurrence (E,
7675 -- Get_Current_Excep.all.all);
7676 -- end if;
7677 -- end;
7678
2168d7cc 7679 Fin_Call :=
2c1b72d7
AC
7680 Make_Final_Call
7681 (Obj_Ref =>
7682 Make_Selected_Component (Loc,
7683 Prefix => Make_Identifier (Loc, Name_V),
7684 Selector_Name => Make_Identifier (Loc, Chars (Id))),
7685 Typ => Typ);
df3e68b1 7686
2168d7cc
AC
7687 -- Guard against a missing [Deep_]Finalize when the component
7688 -- type was not properly frozen.
7689
7690 if Present (Fin_Call) then
7691 if Exceptions_OK then
7692 Fin_Call :=
7693 Make_Block_Statement (Loc,
7694 Handled_Statement_Sequence =>
7695 Make_Handled_Sequence_Of_Statements (Loc,
7696 Statements => New_List (Fin_Call),
7697 Exception_Handlers => New_List (
7698 Build_Exception_Handler (Finalizer_Data))));
7699 end if;
70482933 7700
2168d7cc
AC
7701 Append_To (Stmts, Fin_Call);
7702 end if;
df3e68b1 7703 end Process_Component_For_Finalize;
70482933 7704
321c24f7
AC
7705 -- Local variables
7706
7707 Alts : List_Id;
a6d25cad 7708 Counter_Id : Entity_Id := Empty;
321c24f7
AC
7709 Decl : Node_Id;
7710 Decl_Id : Entity_Id;
7711 Decl_Typ : Entity_Id;
7712 Decls : List_Id;
7713 Has_POC : Boolean;
7714 Jump_Block : Node_Id;
7715 Label : Node_Id;
7716 Label_Id : Entity_Id;
7e6060af 7717 Num_Comps : Nat;
321c24f7
AC
7718 Stmts : List_Id;
7719 Var_Case : Node_Id;
7720
df3e68b1 7721 -- Start of processing for Process_Component_List_For_Finalize
70482933 7722
df3e68b1
HK
7723 begin
7724 -- Perform an initial check, look for controlled and per-object
7725 -- constrained components.
70482933 7726
df3e68b1 7727 Preprocess_Components (Comps, Num_Comps, Has_POC);
70482933 7728
df3e68b1
HK
7729 -- Create a state counter to service the current component list.
7730 -- This step is performed before the variants are inspected in
7731 -- order to generate the same state counter names as those from
7732 -- Build_Initialize_Statements.
70482933 7733
36295779 7734 if Num_Comps > 0 and then Is_Local then
df3e68b1 7735 Counter := Counter + 1;
70482933 7736
df3e68b1
HK
7737 Counter_Id :=
7738 Make_Defining_Identifier (Loc,
7739 Chars => New_External_Name ('C', Counter));
7740 end if;
70482933 7741
df3e68b1
HK
7742 -- Process the component in the following order:
7743 -- 1) Variants
7744 -- 2) Per-object constrained components
7745 -- 3) Regular components
70482933 7746
df3e68b1 7747 -- Start with the variant parts
70482933 7748
df3e68b1
HK
7749 Var_Case := Empty;
7750 if Present (Variant_Part (Comps)) then
7751 declare
7752 Var_Alts : constant List_Id := New_List;
7753 Var : Node_Id;
70482933 7754
df3e68b1
HK
7755 begin
7756 Var := First_Non_Pragma (Variants (Variant_Part (Comps)));
7757 while Present (Var) loop
7758
7759 -- Generate:
7760 -- when <discrete choices> =>
7761 -- <finalize statements>
7762
7763 Append_To (Var_Alts,
7764 Make_Case_Statement_Alternative (Loc,
7765 Discrete_Choices =>
7766 New_Copy_List (Discrete_Choices (Var)),
7767 Statements =>
7768 Process_Component_List_For_Finalize (
7c88e46a
SB
7769 Component_List (Var),
7770 In_Variant_Part => True)));
df3e68b1
HK
7771
7772 Next_Non_Pragma (Var);
7773 end loop;
7774
7775 -- Generate:
7776 -- case V.<discriminant> is
7777 -- when <discrete choices 1> =>
7778 -- <finalize statements 1>
7779 -- ...
7780 -- when <discrete choices N> =>
7781 -- <finalize statements N>
7782 -- end case;
7783
7784 Var_Case :=
7785 Make_Case_Statement (Loc,
7786 Expression =>
7787 Make_Selected_Component (Loc,
cfae2bed 7788 Prefix => Make_Identifier (Loc, Name_V),
df3e68b1
HK
7789 Selector_Name =>
7790 Make_Identifier (Loc,
cfae2bed 7791 Chars => Chars (Name (Variant_Part (Comps))))),
df3e68b1
HK
7792 Alternatives => Var_Alts);
7793 end;
7794 end if;
70482933 7795
df3e68b1
HK
7796 -- The current component list does not have a single controlled
7797 -- component, however it may contain variants. Return the case
7798 -- statement for the variants or nothing.
70482933 7799
df3e68b1
HK
7800 if Num_Comps = 0 then
7801 if Present (Var_Case) then
7802 return New_List (Var_Case);
7803 else
7804 return New_List (Make_Null_Statement (Loc));
7805 end if;
7806 end if;
70482933 7807
df3e68b1 7808 -- Prepare all lists
70482933 7809
df3e68b1
HK
7810 Alts := New_List;
7811 Decls := New_List;
7812 Stmts := New_List;
dcfa065d 7813
df3e68b1 7814 -- Process all per-object constrained components in reverse order
70482933 7815
df3e68b1
HK
7816 if Has_POC then
7817 Decl := Last_Non_Pragma (Component_Items (Comps));
7818 while Present (Decl) loop
7819 Decl_Id := Defining_Identifier (Decl);
7820 Decl_Typ := Etype (Decl_Id);
70482933 7821
df3e68b1 7822 -- Skip _parent
70482933 7823
df3e68b1
HK
7824 if Chars (Decl_Id) /= Name_uParent
7825 and then Needs_Finalization (Decl_Typ)
7826 and then Has_Access_Constraint (Decl_Id)
7827 and then No (Expression (Decl))
7828 then
7e6060af
AC
7829 Process_Component_For_Finalize
7830 (Decl, Alts, Decls, Stmts, Num_Comps);
df3e68b1 7831 end if;
70482933 7832
df3e68b1
HK
7833 Prev_Non_Pragma (Decl);
7834 end loop;
7835 end if;
70482933 7836
7c88e46a
SB
7837 if not In_Variant_Part then
7838 Last_POC_Call := Last (Stmts);
7839 -- In the case of a type extension, the deep-finalize call
7840 -- for the _Parent component will be inserted here.
7841 end if;
7842
df3e68b1 7843 -- Process the rest of the components in reverse order
70482933 7844
df3e68b1
HK
7845 Decl := Last_Non_Pragma (Component_Items (Comps));
7846 while Present (Decl) loop
7847 Decl_Id := Defining_Identifier (Decl);
7848 Decl_Typ := Etype (Decl_Id);
70482933 7849
df3e68b1 7850 -- Skip _parent
70482933 7851
df3e68b1
HK
7852 if Chars (Decl_Id) /= Name_uParent
7853 and then Needs_Finalization (Decl_Typ)
7854 then
7855 -- Skip per-object constrained components since they were
7856 -- handled in the above step.
70482933 7857
df3e68b1
HK
7858 if Has_Access_Constraint (Decl_Id)
7859 and then No (Expression (Decl))
7860 then
7861 null;
7862 else
7e6060af
AC
7863 Process_Component_For_Finalize
7864 (Decl, Alts, Decls, Stmts, Num_Comps);
df3e68b1
HK
7865 end if;
7866 end if;
70482933 7867
df3e68b1
HK
7868 Prev_Non_Pragma (Decl);
7869 end loop;
70482933 7870
df3e68b1
HK
7871 -- Generate:
7872 -- declare
7873 -- LN : label; -- If Is_Local is enabled
7874 -- ... .
7875 -- L0 : label; .
7876
7877 -- begin .
7878 -- case CounterX is .
7879 -- when N => .
7880 -- goto LN; .
7881 -- ... .
7882 -- when 1 => .
7883 -- goto L1; .
7884 -- when others => .
7885 -- goto L0; .
7886 -- end case; .
7887
7888 -- <<LN>> -- If Is_Local is enabled
7889 -- begin
7890 -- [Deep_]Finalize (V.CompY);
7891 -- exception
7892 -- when Id : others =>
7893 -- if not Raised then
7894 -- Raised := True;
7895 -- Save_Occurrence (E,
7896 -- Get_Current_Excep.all.all);
7897 -- end if;
7898 -- end;
7899 -- ...
7900 -- <<L0>> -- If Is_Local is enabled
7901 -- end;
7902
7903 if Is_Local then
7904
7905 -- Add the declaration of default jump location L0, its
7906 -- corresponding alternative and its place in the statements.
7907
cfae2bed 7908 Label_Id := Make_Identifier (Loc, New_External_Name ('L', 0));
df3e68b1
HK
7909 Set_Entity (Label_Id,
7910 Make_Defining_Identifier (Loc, Chars (Label_Id)));
7911 Label := Make_Label (Loc, Label_Id);
7912
7913 Append_To (Decls, -- declaration
7914 Make_Implicit_Label_Declaration (Loc,
7915 Defining_Identifier => Entity (Label_Id),
cfae2bed 7916 Label_Construct => Label));
df3e68b1
HK
7917
7918 Append_To (Alts, -- alternative
7919 Make_Case_Statement_Alternative (Loc,
7920 Discrete_Choices => New_List (
7921 Make_Others_Choice (Loc)),
7922
7923 Statements => New_List (
7924 Make_Goto_Statement (Loc,
e4494292 7925 Name => New_Occurrence_Of (Entity (Label_Id), Loc)))));
df3e68b1
HK
7926
7927 Append_To (Stmts, Label); -- statement
7928
7929 -- Create the jump block
7930
7931 Prepend_To (Stmts,
7932 Make_Case_Statement (Loc,
cfae2bed 7933 Expression => Make_Identifier (Loc, Chars (Counter_Id)),
df3e68b1
HK
7934 Alternatives => Alts));
7935 end if;
70482933 7936
df3e68b1
HK
7937 Jump_Block :=
7938 Make_Block_Statement (Loc,
2c1b72d7 7939 Declarations => Decls,
df3e68b1 7940 Handled_Statement_Sequence =>
2c1b72d7 7941 Make_Handled_Sequence_Of_Statements (Loc, Stmts));
70482933 7942
df3e68b1
HK
7943 if Present (Var_Case) then
7944 return New_List (Var_Case, Jump_Block);
7945 else
7946 return New_List (Jump_Block);
7947 end if;
7948 end Process_Component_List_For_Finalize;
70482933 7949
321c24f7
AC
7950 -- Local variables
7951
a6d25cad 7952 Bod_Stmts : List_Id := No_List;
321c24f7
AC
7953 Finalizer_Decls : List_Id := No_List;
7954 Rec_Def : Node_Id;
7955
df3e68b1 7956 -- Start of processing for Build_Finalize_Statements
70482933
RK
7957
7958 begin
2d1debf8
AC
7959 Finalizer_Decls := New_List;
7960 Build_Object_Declarations (Finalizer_Data, Finalizer_Decls, Loc);
70482933 7961
df3e68b1
HK
7962 if Nkind (Typ_Def) = N_Derived_Type_Definition then
7963 Rec_Def := Record_Extension_Part (Typ_Def);
7964 else
7965 Rec_Def := Typ_Def;
7966 end if;
70482933 7967
df3e68b1 7968 -- Create a finalization sequence for all record components
70482933 7969
df3e68b1
HK
7970 if Present (Component_List (Rec_Def)) then
7971 Bod_Stmts :=
7972 Process_Component_List_For_Finalize (Component_List (Rec_Def));
7973 end if;
70482933 7974
df3e68b1
HK
7975 -- A derived record type must finalize all inherited components. This
7976 -- action poses the following problem:
886b5a18 7977
df3e68b1
HK
7978 -- procedure Deep_Finalize (Obj : in out Parent_Typ) is
7979 -- begin
7980 -- Finalize (Obj);
7981 -- ...
886b5a18 7982
df3e68b1
HK
7983 -- procedure Deep_Finalize (Obj : in out Derived_Typ) is
7984 -- begin
7985 -- Deep_Finalize (Obj._parent);
7986 -- ...
7987 -- Finalize (Obj);
7988 -- ...
886b5a18 7989
df3e68b1
HK
7990 -- Finalizing the derived type will invoke Finalize of the parent and
7991 -- then that of the derived type. This is undesirable because both
7992 -- routines may modify shared components. Only the Finalize of the
7993 -- derived type should be invoked.
886b5a18 7994
df3e68b1
HK
7995 -- To prevent this double adjustment of shared components,
7996 -- Deep_Finalize uses a flag to control the invocation of Finalize:
886b5a18 7997
df3e68b1
HK
7998 -- procedure Deep_Finalize
7999 -- (Obj : in out Some_Type;
8000 -- Flag : Boolean := True)
8001 -- is
8002 -- begin
8003 -- if Flag then
8004 -- Finalize (Obj);
8005 -- end if;
8006 -- ...
886b5a18 8007
7c4d86c9 8008 -- When Deep_Finalize is invoked for field _parent, a value of False
df3e68b1 8009 -- is provided for the flag:
886b5a18 8010
df3e68b1
HK
8011 -- Deep_Finalize (Obj._parent, False);
8012
41c79d60 8013 if Is_Tagged_Type (Typ) and then Is_Derived_Type (Typ) then
df3e68b1
HK
8014 declare
8015 Par_Typ : constant Entity_Id := Parent_Field_Type (Typ);
8016 Call : Node_Id;
8017 Fin_Stmt : Node_Id;
70482933 8018
df3e68b1
HK
8019 begin
8020 if Needs_Finalization (Par_Typ) then
8021 Call :=
2c1b72d7 8022 Make_Final_Call
4ac2bbbd 8023 (Obj_Ref =>
2c1b72d7
AC
8024 Make_Selected_Component (Loc,
8025 Prefix => Make_Identifier (Loc, Name_V),
8026 Selector_Name =>
8027 Make_Identifier (Loc, Name_uParent)),
4ac2bbbd
AC
8028 Typ => Par_Typ,
8029 Skip_Self => True);
df3e68b1
HK
8030
8031 -- Generate:
7bf911b5 8032 -- begin
df3e68b1 8033 -- Deep_Finalize (V._parent, False);
7bf911b5 8034
df3e68b1
HK
8035 -- exception
8036 -- when Id : others =>
8037 -- if not Raised then
8038 -- Raised := True;
8039 -- Save_Occurrence (E,
8040 -- Get_Current_Excep.all.all);
8041 -- end if;
8042 -- end;
8043
8044 if Present (Call) then
8045 Fin_Stmt := Call;
8046
8047 if Exceptions_OK then
8048 Fin_Stmt :=
8049 Make_Block_Statement (Loc,
8050 Handled_Statement_Sequence =>
8051 Make_Handled_Sequence_Of_Statements (Loc,
2c1b72d7 8052 Statements => New_List (Fin_Stmt),
df3e68b1
HK
8053 Exception_Handlers => New_List (
8054 Build_Exception_Handler
36b8f95f 8055 (Finalizer_Data))));
df3e68b1 8056 end if;
70482933 8057
7c88e46a
SB
8058 -- The intended component finalization order is
8059 -- 1) POC components of extension
8060 -- 2) _Parent component
8061 -- 3) non-POC components of extension.
8062 --
8063 -- With this "finalize the parent part in the middle"
8064 -- ordering, we can avoid the need for making two
8065 -- calls to the parent's subprogram in the way that
8066 -- is necessary for Init_Procs. This does have the
8067 -- peculiar (but legal) consequence that the parent's
8068 -- non-POC components are finalized before the
8069 -- non-POC extension components. This violates the
8070 -- usual "finalize in reverse declaration order"
8071 -- principle, but that's ok (see Ada RM 7.6.1(9)).
8072 --
8073 -- Last_POC_Call should be non-empty if the extension
8074 -- has at least one POC. Interactions with variant
8075 -- parts are incorrectly ignored.
8076
8077 if Present (Last_POC_Call) then
8078 Insert_After (Last_POC_Call, Fin_Stmt);
8079 else
8080 -- At this point, we could look for the common case
8081 -- where there are no POC components anywhere in
8082 -- sight (inherited or not) and, in that common case,
8083 -- call Append_To instead of Prepend_To. That would
8084 -- result in finalizing the parent part after, rather
8085 -- than before, the extension components. That might
8086 -- be more intuitive (as discussed in preceding
8087 -- comment), but it is not required.
8088 Prepend_To (Bod_Stmts, Fin_Stmt);
8089 end if;
df3e68b1
HK
8090 end if;
8091 end if;
8092 end;
8093 end if;
70482933 8094
df3e68b1
HK
8095 -- Finalize the object. This action must be performed first before
8096 -- all components have been finalized.
70482933 8097
41c79d60 8098 if Is_Controlled (Typ) and then not Is_Local then
df3e68b1
HK
8099 declare
8100 Fin_Stmt : Node_Id;
8101 Proc : Entity_Id;
70482933 8102
df3e68b1 8103 begin
ca811241 8104 Proc := Find_Optional_Prim_Op (Typ, Name_Finalize);
df3e68b1
HK
8105
8106 -- Generate:
8107 -- if F then
df3e68b1
HK
8108 -- begin
8109 -- Finalize (V);
7bf911b5 8110
df3e68b1
HK
8111 -- exception
8112 -- when others =>
8113 -- if not Raised then
8114 -- Raised := True;
8115 -- Save_Occurrence (E,
8116 -- Get_Current_Excep.all.all);
8117 -- end if;
8118 -- end;
8119 -- end if;
8120
8121 if Present (Proc) then
8122 Fin_Stmt :=
8123 Make_Procedure_Call_Statement (Loc,
e4494292 8124 Name => New_Occurrence_Of (Proc, Loc),
df3e68b1
HK
8125 Parameter_Associations => New_List (
8126 Make_Identifier (Loc, Name_V)));
8127
8128 if Exceptions_OK then
8129 Fin_Stmt :=
8130 Make_Block_Statement (Loc,
8131 Handled_Statement_Sequence =>
8132 Make_Handled_Sequence_Of_Statements (Loc,
2c1b72d7 8133 Statements => New_List (Fin_Stmt),
df3e68b1
HK
8134 Exception_Handlers => New_List (
8135 Build_Exception_Handler
36b8f95f 8136 (Finalizer_Data))));
df3e68b1 8137 end if;
70482933 8138
df3e68b1
HK
8139 Prepend_To (Bod_Stmts,
8140 Make_If_Statement (Loc,
2c1b72d7 8141 Condition => Make_Identifier (Loc, Name_F),
df3e68b1
HK
8142 Then_Statements => New_List (Fin_Stmt)));
8143 end if;
8144 end;
70482933 8145 end if;
70482933 8146
df3e68b1
HK
8147 -- At this point either all finalization statements have been
8148 -- generated or the type is not controlled.
70482933 8149
df3e68b1
HK
8150 if No (Bod_Stmts) then
8151 return New_List (Make_Null_Statement (Loc));
70482933 8152
df3e68b1
HK
8153 -- Generate:
8154 -- declare
14848f57 8155 -- Abort : constant Boolean := Triggered_By_Abort;
f9ad6b62
AC
8156 -- <or>
8157 -- Abort : constant Boolean := False; -- no abort
8158
7f37fff1 8159 -- E : Exception_Occurrence;
df3e68b1 8160 -- Raised : Boolean := False;
70482933 8161
df3e68b1 8162 -- begin
df3e68b1 8163 -- <finalize statements>
70482933 8164
ca5af305
AC
8165 -- if Raised and then not Abort then
8166 -- Raise_From_Controlled_Operation (E);
df3e68b1
HK
8167 -- end if;
8168 -- end;
70482933 8169
df3e68b1
HK
8170 else
8171 if Exceptions_OK then
7bf911b5 8172 Append_To (Bod_Stmts, Build_Raise_Statement (Finalizer_Data));
df3e68b1 8173 end if;
70482933 8174
df3e68b1
HK
8175 return
8176 New_List (
8177 Make_Block_Statement (Loc,
2c1b72d7 8178 Declarations =>
36b8f95f 8179 Finalizer_Decls,
df3e68b1 8180 Handled_Statement_Sequence =>
2c1b72d7 8181 Make_Handled_Sequence_Of_Statements (Loc, Bod_Stmts)));
df3e68b1
HK
8182 end if;
8183 end Build_Finalize_Statements;
70482933 8184
df3e68b1
HK
8185 -----------------------
8186 -- Parent_Field_Type --
8187 -----------------------
70482933 8188
df3e68b1
HK
8189 function Parent_Field_Type (Typ : Entity_Id) return Entity_Id is
8190 Field : Entity_Id;
70482933 8191
df3e68b1
HK
8192 begin
8193 Field := First_Entity (Typ);
8194 while Present (Field) loop
8195 if Chars (Field) = Name_uParent then
8196 return Etype (Field);
8197 end if;
70482933 8198
df3e68b1
HK
8199 Next_Entity (Field);
8200 end loop;
70482933 8201
df3e68b1 8202 -- A derived tagged type should always have a parent field
70482933 8203
df3e68b1
HK
8204 raise Program_Error;
8205 end Parent_Field_Type;
70482933 8206
df3e68b1
HK
8207 ---------------------------
8208 -- Preprocess_Components --
8209 ---------------------------
70482933 8210
df3e68b1
HK
8211 procedure Preprocess_Components
8212 (Comps : Node_Id;
b3143037 8213 Num_Comps : out Nat;
df3e68b1
HK
8214 Has_POC : out Boolean)
8215 is
8216 Decl : Node_Id;
8217 Id : Entity_Id;
8218 Typ : Entity_Id;
70482933 8219
df3e68b1
HK
8220 begin
8221 Num_Comps := 0;
8222 Has_POC := False;
70482933 8223
df3e68b1
HK
8224 Decl := First_Non_Pragma (Component_Items (Comps));
8225 while Present (Decl) loop
8226 Id := Defining_Identifier (Decl);
8227 Typ := Etype (Id);
70482933 8228
df3e68b1 8229 -- Skip field _parent
fbf5a39b 8230
df3e68b1
HK
8231 if Chars (Id) /= Name_uParent
8232 and then Needs_Finalization (Typ)
8233 then
8234 Num_Comps := Num_Comps + 1;
fbf5a39b 8235
df3e68b1
HK
8236 if Has_Access_Constraint (Id)
8237 and then No (Expression (Decl))
8238 then
8239 Has_POC := True;
8240 end if;
fbf5a39b 8241 end if;
70482933 8242
df3e68b1
HK
8243 Next_Non_Pragma (Decl);
8244 end loop;
8245 end Preprocess_Components;
fbf5a39b 8246
df3e68b1 8247 -- Start of processing for Make_Deep_Record_Body
fbf5a39b 8248
df3e68b1
HK
8249 begin
8250 case Prim is
8251 when Address_Case =>
8252 return Make_Finalize_Address_Stmts (Typ);
8253
8254 when Adjust_Case =>
8255 return Build_Adjust_Statements (Typ);
70482933
RK
8256
8257 when Finalize_Case =>
df3e68b1 8258 return Build_Finalize_Statements (Typ);
fbf5a39b 8259
df3e68b1
HK
8260 when Initialize_Case =>
8261 declare
8262 Loc : constant Source_Ptr := Sloc (Typ);
fbf5a39b 8263
df3e68b1
HK
8264 begin
8265 if Is_Controlled (Typ) then
8266 return New_List (
8267 Make_Procedure_Call_Statement (Loc,
2c1b72d7 8268 Name =>
e4494292 8269 New_Occurrence_Of
2c1b72d7 8270 (Find_Prim_Op (Typ, Name_Of (Prim)), Loc),
df3e68b1
HK
8271 Parameter_Associations => New_List (
8272 Make_Identifier (Loc, Name_V))));
8273 else
8274 return Empty_List;
8275 end if;
8276 end;
70482933
RK
8277 end case;
8278 end Make_Deep_Record_Body;
8279
8280 ----------------------
8281 -- Make_Final_Call --
8282 ----------------------
8283
8284 function Make_Final_Call
4ac2bbbd
AC
8285 (Obj_Ref : Node_Id;
8286 Typ : Entity_Id;
8287 Skip_Self : Boolean := False) return Node_Id
70482933 8288 is
9267014b
JS
8289 Loc : constant Source_Ptr := Sloc (Obj_Ref);
8290 Atyp : Entity_Id;
8291 Prot_Typ : Entity_Id := Empty;
8292 Fin_Id : Entity_Id := Empty;
8293 Ref : Node_Id;
8294 Utyp : Entity_Id;
70482933
RK
8295
8296 begin
2168d7cc
AC
8297 Ref := Obj_Ref;
8298
df3e68b1
HK
8299 -- Recover the proper type which contains [Deep_]Finalize
8300
70482933
RK
8301 if Is_Class_Wide_Type (Typ) then
8302 Utyp := Root_Type (Typ);
6a2e5d0f 8303 Atyp := Utyp;
70482933
RK
8304
8305 elsif Is_Concurrent_Type (Typ) then
8306 Utyp := Corresponding_Record_Type (Typ);
6a2e5d0f 8307 Atyp := Empty;
2168d7cc 8308 Ref := Convert_Concurrent (Ref, Typ);
70482933
RK
8309
8310 elsif Is_Private_Type (Typ)
198064c0 8311 and then Present (Underlying_Type (Typ))
a3fbecee 8312 and then Is_Concurrent_Type (Underlying_Type (Typ))
70482933 8313 then
a3fbecee 8314 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
6a2e5d0f 8315 Atyp := Typ;
a3fbecee 8316 Ref := Convert_Concurrent (Ref, Underlying_Type (Typ));
df3e68b1 8317
70482933
RK
8318 else
8319 Utyp := Typ;
6a2e5d0f 8320 Atyp := Typ;
70482933
RK
8321 end if;
8322
8323 Utyp := Underlying_Type (Base_Type (Utyp));
df3e68b1 8324 Set_Assignment_OK (Ref);
70482933 8325
1fb63e89 8326 -- Deal with untagged derivation of private views. If the parent type
df3e68b1
HK
8327 -- is a protected type, Deep_Finalize is found on the corresponding
8328 -- record of the ancestor.
8329
8330 if Is_Untagged_Derivation (Typ) then
8331 if Is_Protected_Type (Typ) then
8332 Utyp := Corresponding_Record_Type (Root_Type (Base_Type (Typ)));
8333 else
8334 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
8335
8336 if Is_Protected_Type (Utyp) then
8337 Utyp := Corresponding_Record_Type (Utyp);
8338 end if;
8339 end if;
8340
8341 Ref := Unchecked_Convert_To (Utyp, Ref);
8342 Set_Assignment_OK (Ref);
8343 end if;
8344
8345 -- Deal with derived private types which do not inherit primitives from
8346 -- their parents. In this case, [Deep_]Finalize can be found in the full
8347 -- view of the parent type.
8348
2168d7cc
AC
8349 if Present (Utyp)
8350 and then Is_Tagged_Type (Utyp)
df3e68b1
HK
8351 and then Is_Derived_Type (Utyp)
8352 and then Is_Empty_Elmt_List (Primitive_Operations (Utyp))
8353 and then Is_Private_Type (Etype (Utyp))
8354 and then Present (Full_View (Etype (Utyp)))
8355 then
8356 Utyp := Full_View (Etype (Utyp));
8357 Ref := Unchecked_Convert_To (Utyp, Ref);
8358 Set_Assignment_OK (Ref);
8359 end if;
8360
8361 -- When dealing with the completion of a private type, use the base type
8362 -- instead.
8363
2168d7cc 8364 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
6a2e5d0f 8365 pragma Assert (Present (Atyp) and then Is_Private_Type (Atyp));
df3e68b1
HK
8366
8367 Utyp := Base_Type (Utyp);
8368 Ref := Unchecked_Convert_To (Utyp, Ref);
8369 Set_Assignment_OK (Ref);
8370 end if;
8371
9267014b
JS
8372 -- Detect if Typ is a protected type or an expanded protected type and
8373 -- store the relevant type within Prot_Typ for later processing.
8374
8375 if Is_Protected_Type (Typ) then
8376 Prot_Typ := Typ;
8377
8378 elsif Ekind (Typ) = E_Record_Type
8379 and then Present (Corresponding_Concurrent_Type (Typ))
8380 and then Is_Protected_Type (Corresponding_Concurrent_Type (Typ))
8381 then
8382 Prot_Typ := Corresponding_Concurrent_Type (Typ);
8383 end if;
8384
2168d7cc
AC
8385 -- The underlying type may not be present due to a missing full view. In
8386 -- this case freezing did not take place and there is no [Deep_]Finalize
8387 -- primitive to call.
8388
8389 if No (Utyp) then
8390 return Empty;
8391
8392 elsif Skip_Self then
df3e68b1 8393 if Has_Controlled_Component (Utyp) then
4ac2bbbd 8394 if Is_Tagged_Type (Utyp) then
ca811241 8395 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
4ac2bbbd
AC
8396 else
8397 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
8398 end if;
df3e68b1
HK
8399 end if;
8400
d3f70b35 8401 -- Class-wide types, interfaces and types with controlled components
df3e68b1
HK
8402
8403 elsif Is_Class_Wide_Type (Typ)
8404 or else Is_Interface (Typ)
8405 or else Has_Controlled_Component (Utyp)
8406 then
8407 if Is_Tagged_Type (Utyp) then
ca811241 8408 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
df3e68b1
HK
8409 else
8410 Fin_Id := TSS (Utyp, TSS_Deep_Finalize);
8411 end if;
8412
d3cb4cc0
AC
8413 -- Derivations from [Limited_]Controlled
8414
8415 elsif Is_Controlled (Utyp) then
8416 if Has_Controlled_Component (Utyp) then
ca811241 8417 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
d3cb4cc0 8418 else
ca811241 8419 Fin_Id := Find_Optional_Prim_Op (Utyp, Name_Of (Finalize_Case));
d3cb4cc0
AC
8420 end if;
8421
d3f70b35
AC
8422 -- Tagged types
8423
8424 elsif Is_Tagged_Type (Utyp) then
ca811241 8425 Fin_Id := Find_Optional_Prim_Op (Utyp, TSS_Deep_Finalize);
df3e68b1 8426
14803949
AC
8427 -- Protected types: these also require finalization even though they
8428 -- are not marked controlled explicitly.
8429
9267014b 8430 elsif Present (Prot_Typ) then
14803949
AC
8431 -- Protected objects do not need to be finalized on restricted
8432 -- runtimes.
8433
8434 if Restricted_Profile then
8435 return Empty;
8436
8437 -- ??? Only handle the simple case for now. Will not support a record
8438 -- or array containing protected objects.
8439
9267014b 8440 elsif Is_Simple_Protected_Type (Prot_Typ) then
14803949
AC
8441 Fin_Id := RTE (RE_Finalize_Protection);
8442 else
8443 raise Program_Error;
8444 end if;
df3e68b1 8445 else
d3f70b35 8446 raise Program_Error;
df3e68b1
HK
8447 end if;
8448
8449 if Present (Fin_Id) then
8450
8451 -- When finalizing a class-wide object, do not convert to the root
8452 -- type in order to produce a dispatching call.
8453
8454 if Is_Class_Wide_Type (Typ) then
8455 null;
8456
8457 -- Ensure that a finalization routine is at least decorated in order
8458 -- to inspect the object parameter.
8459
8460 elsif Analyzed (Fin_Id)
8461 or else Ekind (Fin_Id) = E_Procedure
8462 then
8463 -- In certain cases, such as the creation of Stream_Read, the
8464 -- visible entity of the type is its full view. Since Stream_Read
8465 -- will have to create an object of type Typ, the local object
8466 -- will be finalzed by the scope finalizer generated later on. The
8467 -- object parameter of Deep_Finalize will always use the private
8468 -- view of the type. To avoid such a clash between a private and a
8469 -- full view, perform an unchecked conversion of the object
8470 -- reference to the private view.
8471
8472 declare
8473 Formal_Typ : constant Entity_Id :=
8474 Etype (First_Formal (Fin_Id));
8475 begin
8476 if Is_Private_Type (Formal_Typ)
8477 and then Present (Full_View (Formal_Typ))
8478 and then Full_View (Formal_Typ) = Utyp
8479 then
8480 Ref := Unchecked_Convert_To (Formal_Typ, Ref);
8481 end if;
8482 end;
8483
25a76d62
EB
8484 -- If the object is unanalyzed, set its expected type for use in
8485 -- Convert_View in case an additional conversion is needed.
8486
8487 if No (Etype (Ref))
8488 and then Nkind (Ref) /= N_Unchecked_Type_Conversion
8489 then
8490 Set_Etype (Ref, Typ);
8491 end if;
8492
df3e68b1
HK
8493 Ref := Convert_View (Fin_Id, Ref);
8494 end if;
8495
4ac2bbbd
AC
8496 return
8497 Make_Call (Loc,
8498 Proc_Id => Fin_Id,
2168d7cc 8499 Param => Ref,
4ac2bbbd 8500 Skip_Self => Skip_Self);
df3e68b1
HK
8501 else
8502 return Empty;
8503 end if;
8504 end Make_Final_Call;
8505
8506 --------------------------------
8507 -- Make_Finalize_Address_Body --
8508 --------------------------------
8509
8510 procedure Make_Finalize_Address_Body (Typ : Entity_Id) is
ca5af305
AC
8511 Is_Task : constant Boolean :=
8512 Ekind (Typ) = E_Record_Type
8513 and then Is_Concurrent_Record_Type (Typ)
8514 and then Ekind (Corresponding_Concurrent_Type (Typ)) =
36295779 8515 E_Task_Type;
d3f70b35
AC
8516 Loc : constant Source_Ptr := Sloc (Typ);
8517 Proc_Id : Entity_Id;
ca5af305 8518 Stmts : List_Id;
d3f70b35 8519
df3e68b1 8520 begin
ca5af305
AC
8521 -- The corresponding records of task types are not controlled by design.
8522 -- For the sake of completeness, create an empty Finalize_Address to be
8523 -- used in task class-wide allocations.
8524
8525 if Is_Task then
8526 null;
8527
df3e68b1
HK
8528 -- Nothing to do if the type is not controlled or it already has a
8529 -- TSS entry for Finalize_Address. Skip class-wide subtypes which do not
8530 -- come from source. These are usually generated for completeness and
8531 -- do not need the Finalize_Address primitive.
8532
ca5af305 8533 elsif not Needs_Finalization (Typ)
df3e68b1
HK
8534 or else Present (TSS (Typ, TSS_Finalize_Address))
8535 or else
8536 (Is_Class_Wide_Type (Typ)
886b5a18
AC
8537 and then Ekind (Root_Type (Typ)) = E_Record_Subtype
8538 and then not Comes_From_Source (Root_Type (Typ)))
df3e68b1
HK
8539 then
8540 return;
8541 end if;
8542
94295b25
AC
8543 -- Do not generate Finalize_Address routine for CodePeer
8544
89b6c83e
AC
8545 if CodePeer_Mode then
8546 return;
8547 end if;
8548
d3f70b35
AC
8549 Proc_Id :=
8550 Make_Defining_Identifier (Loc,
8551 Make_TSS_Name (Typ, TSS_Finalize_Address));
df3e68b1 8552
d3f70b35 8553 -- Generate:
886b5a18 8554
d3f70b35
AC
8555 -- procedure <Typ>FD (V : System.Address) is
8556 -- begin
ca5af305 8557 -- null; -- for tasks
886b5a18 8558
ca5af305 8559 -- declare -- for all other types
d3f70b35
AC
8560 -- type Pnn is access all Typ;
8561 -- for Pnn'Storage_Size use 0;
8562 -- begin
8563 -- [Deep_]Finalize (Pnn (V).all);
8564 -- end;
8565 -- end TypFD;
df3e68b1 8566
ca5af305
AC
8567 if Is_Task then
8568 Stmts := New_List (Make_Null_Statement (Loc));
8569 else
8570 Stmts := Make_Finalize_Address_Stmts (Typ);
8571 end if;
8572
d3f70b35
AC
8573 Discard_Node (
8574 Make_Subprogram_Body (Loc,
8575 Specification =>
8576 Make_Procedure_Specification (Loc,
8577 Defining_Unit_Name => Proc_Id,
df3e68b1 8578
d3f70b35
AC
8579 Parameter_Specifications => New_List (
8580 Make_Parameter_Specification (Loc,
8581 Defining_Identifier =>
8582 Make_Defining_Identifier (Loc, Name_V),
8583 Parameter_Type =>
e4494292 8584 New_Occurrence_Of (RTE (RE_Address), Loc)))),
df3e68b1 8585
d3f70b35 8586 Declarations => No_List,
df3e68b1 8587
d3f70b35
AC
8588 Handled_Statement_Sequence =>
8589 Make_Handled_Sequence_Of_Statements (Loc,
ca5af305 8590 Statements => Stmts)));
df3e68b1 8591
d3f70b35 8592 Set_TSS (Typ, Proc_Id);
df3e68b1
HK
8593 end Make_Finalize_Address_Body;
8594
8595 ---------------------------------
8596 -- Make_Finalize_Address_Stmts --
8597 ---------------------------------
8598
8599 function Make_Finalize_Address_Stmts (Typ : Entity_Id) return List_Id is
2168d7cc
AC
8600 Loc : constant Source_Ptr := Sloc (Typ);
8601
8602 Decls : List_Id;
8603 Desig_Typ : Entity_Id;
8604 Fin_Block : Node_Id;
8605 Fin_Call : Node_Id;
8606 Obj_Expr : Node_Id;
8607 Ptr_Typ : Entity_Id;
70482933 8608
df3e68b1
HK
8609 begin
8610 if Is_Array_Type (Typ) then
8611 if Is_Constrained (First_Subtype (Typ)) then
2168d7cc 8612 Desig_Typ := First_Subtype (Typ);
f4d379b8 8613 else
2168d7cc 8614 Desig_Typ := Base_Type (Typ);
f4d379b8
HK
8615 end if;
8616
df3e68b1
HK
8617 -- Class-wide types of constrained root types
8618
8619 elsif Is_Class_Wide_Type (Typ)
8620 and then Has_Discriminants (Root_Type (Typ))
2c1b72d7
AC
8621 and then not
8622 Is_Empty_Elmt_List (Discriminant_Constraint (Root_Type (Typ)))
df3e68b1
HK
8623 then
8624 declare
886b5a18 8625 Parent_Typ : Entity_Id;
f4d379b8 8626
df3e68b1
HK
8627 begin
8628 -- Climb the parent type chain looking for a non-constrained type
f4d379b8 8629
886b5a18 8630 Parent_Typ := Root_Type (Typ);
df3e68b1
HK
8631 while Parent_Typ /= Etype (Parent_Typ)
8632 and then Has_Discriminants (Parent_Typ)
2c1b72d7
AC
8633 and then not
8634 Is_Empty_Elmt_List (Discriminant_Constraint (Parent_Typ))
df3e68b1
HK
8635 loop
8636 Parent_Typ := Etype (Parent_Typ);
8637 end loop;
70482933 8638
df3e68b1
HK
8639 -- Handle views created for tagged types with unknown
8640 -- discriminants.
70482933 8641
df3e68b1
HK
8642 if Is_Underlying_Record_View (Parent_Typ) then
8643 Parent_Typ := Underlying_Record_View (Parent_Typ);
8644 end if;
8645
2168d7cc 8646 Desig_Typ := Class_Wide_Type (Underlying_Type (Parent_Typ));
df3e68b1
HK
8647 end;
8648
8649 -- General case
8650
8651 else
2168d7cc 8652 Desig_Typ := Typ;
70482933
RK
8653 end if;
8654
8655 -- Generate:
df3e68b1
HK
8656 -- type Ptr_Typ is access all Typ;
8657 -- for Ptr_Typ'Storage_Size use 0;
8658
2168d7cc
AC
8659 Ptr_Typ := Make_Temporary (Loc, 'P');
8660
df3e68b1
HK
8661 Decls := New_List (
8662 Make_Full_Type_Declaration (Loc,
8663 Defining_Identifier => Ptr_Typ,
cfae2bed 8664 Type_Definition =>
df3e68b1 8665 Make_Access_To_Object_Definition (Loc,
cfae2bed 8666 All_Present => True,
2168d7cc 8667 Subtype_Indication => New_Occurrence_Of (Desig_Typ, Loc))),
df3e68b1
HK
8668
8669 Make_Attribute_Definition_Clause (Loc,
e4494292 8670 Name => New_Occurrence_Of (Ptr_Typ, Loc),
2c1b72d7
AC
8671 Chars => Name_Storage_Size,
8672 Expression => Make_Integer_Literal (Loc, 0)));
df3e68b1
HK
8673
8674 Obj_Expr := Make_Identifier (Loc, Name_V);
8675
8676 -- Unconstrained arrays require special processing in order to retrieve
8677 -- the elements. To achieve this, we have to skip the dope vector which
d9b056ea 8678 -- lays in front of the elements and then use a thin pointer to perform
df3e68b1
HK
8679 -- the address-to-access conversion.
8680
8681 if Is_Array_Type (Typ)
8682 and then not Is_Constrained (First_Subtype (Typ))
70482933 8683 then
df3e68b1 8684 declare
203ddcea 8685 Dope_Id : Entity_Id;
70482933 8686
df3e68b1 8687 begin
82a79441 8688 -- Ensure that Ptr_Typ is a thin pointer; generate:
df3e68b1 8689 -- for Ptr_Typ'Size use System.Address'Size;
70482933 8690
df3e68b1
HK
8691 Append_To (Decls,
8692 Make_Attribute_Definition_Clause (Loc,
e4494292 8693 Name => New_Occurrence_Of (Ptr_Typ, Loc),
2c1b72d7 8694 Chars => Name_Size,
df3e68b1
HK
8695 Expression =>
8696 Make_Integer_Literal (Loc, System_Address_Size)));
70482933 8697
df3e68b1 8698 -- Generate:
203ddcea 8699 -- Dnn : constant Storage_Offset :=
2168d7cc 8700 -- Desig_Typ'Descriptor_Size / Storage_Unit;
df3e68b1
HK
8701
8702 Dope_Id := Make_Temporary (Loc, 'D');
8703
8704 Append_To (Decls,
8705 Make_Object_Declaration (Loc,
8706 Defining_Identifier => Dope_Id,
2c1b72d7
AC
8707 Constant_Present => True,
8708 Object_Definition =>
e4494292 8709 New_Occurrence_Of (RTE (RE_Storage_Offset), Loc),
203ddcea
AC
8710 Expression =>
8711 Make_Op_Divide (Loc,
8712 Left_Opnd =>
8713 Make_Attribute_Reference (Loc,
2168d7cc 8714 Prefix => New_Occurrence_Of (Desig_Typ, Loc),
203ddcea
AC
8715 Attribute_Name => Name_Descriptor_Size),
8716 Right_Opnd =>
8717 Make_Integer_Literal (Loc, System_Storage_Unit))));
df3e68b1
HK
8718
8719 -- Shift the address from the start of the dope vector to the
8720 -- start of the elements:
8721 --
8722 -- V + Dnn
8723 --
8724 -- Note that this is done through a wrapper routine since RTSfind
8725 -- cannot retrieve operations with string names of the form "+".
8726
8727 Obj_Expr :=
8728 Make_Function_Call (Loc,
2c1b72d7 8729 Name =>
e4494292 8730 New_Occurrence_Of (RTE (RE_Add_Offset_To_Address), Loc),
df3e68b1
HK
8731 Parameter_Associations => New_List (
8732 Obj_Expr,
e4494292 8733 New_Occurrence_Of (Dope_Id, Loc)));
df3e68b1 8734 end;
70482933
RK
8735 end if;
8736
2168d7cc
AC
8737 Fin_Call :=
8738 Make_Final_Call (
8739 Obj_Ref =>
8740 Make_Explicit_Dereference (Loc,
8741 Prefix => Unchecked_Convert_To (Ptr_Typ, Obj_Expr)),
8742 Typ => Desig_Typ);
8743
8744 if Present (Fin_Call) then
8745 Fin_Block :=
8746 Make_Block_Statement (Loc,
8747 Declarations => Decls,
8748 Handled_Statement_Sequence =>
8749 Make_Handled_Sequence_Of_Statements (Loc,
8750 Statements => New_List (Fin_Call)));
df3e68b1 8751
2168d7cc
AC
8752 -- Otherwise previous errors or a missing full view may prevent the
8753 -- proper freezing of the designated type. If this is the case, there
8754 -- is no [Deep_]Finalize primitive to call.
df3e68b1 8755
2168d7cc
AC
8756 else
8757 Fin_Block := Make_Null_Statement (Loc);
8758 end if;
8759
8760 return New_List (Fin_Block);
df3e68b1 8761 end Make_Finalize_Address_Stmts;
70482933 8762
dbe13a37
ES
8763 -------------------------------------
8764 -- Make_Handler_For_Ctrl_Operation --
8765 -------------------------------------
8766
8767 -- Generate:
8768
8769 -- when E : others =>
ca5af305 8770 -- Raise_From_Controlled_Operation (E);
dbe13a37
ES
8771
8772 -- or:
8773
8774 -- when others =>
8775 -- raise Program_Error [finalize raised exception];
8776
8777 -- depending on whether Raise_From_Controlled_Operation is available
8778
8779 function Make_Handler_For_Ctrl_Operation
8780 (Loc : Source_Ptr) return Node_Id
8781 is
8782 E_Occ : Entity_Id;
8783 -- Choice parameter (for the first case above)
8784
8785 Raise_Node : Node_Id;
8786 -- Procedure call or raise statement
8787
8788 begin
57d3adcd
AC
8789 -- Standard run-time: add choice parameter E and pass it to
8790 -- Raise_From_Controlled_Operation so that the original exception
7ae0d98c
AC
8791 -- name and message can be recorded in the exception message for
8792 -- Program_Error.
dbe13a37 8793
7ae0d98c 8794 if RTE_Available (RE_Raise_From_Controlled_Operation) then
dbe13a37 8795 E_Occ := Make_Defining_Identifier (Loc, Name_E);
df3e68b1
HK
8796 Raise_Node :=
8797 Make_Procedure_Call_Statement (Loc,
2c1b72d7 8798 Name =>
e4494292 8799 New_Occurrence_Of
f9ad6b62 8800 (RTE (RE_Raise_From_Controlled_Operation), Loc),
df3e68b1 8801 Parameter_Associations => New_List (
e4494292 8802 New_Occurrence_Of (E_Occ, Loc)));
dbe13a37 8803
d72e7628 8804 -- Restricted run-time: exception messages are not supported
dbe13a37 8805
df3e68b1 8806 else
dbe13a37 8807 E_Occ := Empty;
df3e68b1
HK
8808 Raise_Node :=
8809 Make_Raise_Program_Error (Loc,
8810 Reason => PE_Finalize_Raised_Exception);
dbe13a37
ES
8811 end if;
8812
df3e68b1
HK
8813 return
8814 Make_Implicit_Exception_Handler (Loc,
8815 Exception_Choices => New_List (Make_Others_Choice (Loc)),
8816 Choice_Parameter => E_Occ,
8817 Statements => New_List (Raise_Node));
dbe13a37
ES
8818 end Make_Handler_For_Ctrl_Operation;
8819
70482933
RK
8820 --------------------
8821 -- Make_Init_Call --
8822 --------------------
8823
8824 function Make_Init_Call
df3e68b1
HK
8825 (Obj_Ref : Node_Id;
8826 Typ : Entity_Id) return Node_Id
70482933 8827 is
df3e68b1 8828 Loc : constant Source_Ptr := Sloc (Obj_Ref);
70482933 8829 Is_Conc : Boolean;
70482933 8830 Proc : Entity_Id;
df3e68b1 8831 Ref : Node_Id;
70482933 8832 Utyp : Entity_Id;
70482933
RK
8833
8834 begin
2168d7cc
AC
8835 Ref := Obj_Ref;
8836
df3e68b1
HK
8837 -- Deal with the type and object reference. Depending on the context, an
8838 -- object reference may need several conversions.
8839
70482933
RK
8840 if Is_Concurrent_Type (Typ) then
8841 Is_Conc := True;
8842 Utyp := Corresponding_Record_Type (Typ);
2168d7cc 8843 Ref := Convert_Concurrent (Ref, Typ);
70482933
RK
8844
8845 elsif Is_Private_Type (Typ)
8846 and then Present (Full_View (Typ))
8847 and then Is_Concurrent_Type (Underlying_Type (Typ))
8848 then
8849 Is_Conc := True;
8850 Utyp := Corresponding_Record_Type (Underlying_Type (Typ));
2168d7cc 8851 Ref := Convert_Concurrent (Ref, Underlying_Type (Typ));
70482933
RK
8852
8853 else
8854 Is_Conc := False;
8855 Utyp := Typ;
70482933
RK
8856 end if;
8857
df3e68b1 8858 Utyp := Underlying_Type (Base_Type (Utyp));
2168d7cc 8859 Set_Assignment_OK (Ref);
70482933 8860
1fb63e89 8861 -- Deal with untagged derivation of private views
70482933 8862
41c79d60 8863 if Is_Untagged_Derivation (Typ) and then not Is_Conc then
70482933 8864 Utyp := Underlying_Type (Root_Type (Base_Type (Typ)));
df3e68b1 8865 Ref := Unchecked_Convert_To (Utyp, Ref);
cfae2bed 8866
a4640a39
AC
8867 -- The following is to prevent problems with UC see 1.156 RH ???
8868
df3e68b1 8869 Set_Assignment_OK (Ref);
70482933
RK
8870 end if;
8871
df3e68b1
HK
8872 -- If the underlying_type is a subtype, then we are dealing with the
8873 -- completion of a private type. We need to access the base type and
8874 -- generate a conversion to it.
70482933 8875
2168d7cc 8876 if Present (Utyp) and then Utyp /= Base_Type (Utyp) then
70482933
RK
8877 pragma Assert (Is_Private_Type (Typ));
8878 Utyp := Base_Type (Utyp);
df3e68b1 8879 Ref := Unchecked_Convert_To (Utyp, Ref);
70482933
RK
8880 end if;
8881
2168d7cc
AC
8882 -- The underlying type may not be present due to a missing full view.
8883 -- In this case freezing did not take place and there is no suitable
8884 -- [Deep_]Initialize primitive to call.
14803949 8885 -- If Typ is protected then no additional processing is needed either.
2168d7cc 8886
14803949
AC
8887 if No (Utyp)
8888 or else Is_Protected_Type (Typ)
8889 then
2168d7cc
AC
8890 return Empty;
8891 end if;
8892
df3e68b1 8893 -- Select the appropriate version of initialize
70482933 8894
df3e68b1
HK
8895 if Has_Controlled_Component (Utyp) then
8896 Proc := TSS (Utyp, Deep_Name_Of (Initialize_Case));
df3e68b1
HK
8897 else
8898 Proc := Find_Prim_Op (Utyp, Name_Of (Initialize_Case));
8899 Check_Visibly_Controlled (Initialize_Case, Typ, Proc, Ref);
70482933
RK
8900 end if;
8901
1804faa4
AC
8902 -- If initialization procedure for an array of controlled objects is
8903 -- trivial, do not generate a useless call to it.
dbea36c6
ES
8904 -- The initialization procedure may be missing altogether in the case
8905 -- of a derived container whose components have trivial initialization.
1804faa4 8906
dbea36c6
ES
8907 if No (Proc)
8908 or else (Is_Array_Type (Utyp) and then Is_Trivial_Subprogram (Proc))
1804faa4
AC
8909 or else
8910 (not Comes_From_Source (Proc)
8911 and then Present (Alias (Proc))
8912 and then Is_Trivial_Subprogram (Alias (Proc)))
8913 then
14803949 8914 return Empty;
1804faa4
AC
8915 end if;
8916
df3e68b1
HK
8917 -- The object reference may need another conversion depending on the
8918 -- type of the formal and that of the actual.
8919
8920 Ref := Convert_View (Proc, Ref);
8921
70482933 8922 -- Generate:
df3e68b1 8923 -- [Deep_]Initialize (Ref);
70482933 8924
df3e68b1
HK
8925 return
8926 Make_Procedure_Call_Statement (Loc,
2168d7cc 8927 Name => New_Occurrence_Of (Proc, Loc),
df3e68b1
HK
8928 Parameter_Associations => New_List (Ref));
8929 end Make_Init_Call;
70482933 8930
df3e68b1
HK
8931 ------------------------------
8932 -- Make_Local_Deep_Finalize --
8933 ------------------------------
70482933 8934
df3e68b1
HK
8935 function Make_Local_Deep_Finalize
8936 (Typ : Entity_Id;
8937 Nam : Entity_Id) return Node_Id
8938 is
8939 Loc : constant Source_Ptr := Sloc (Typ);
8940 Formals : List_Id;
70482933 8941
df3e68b1
HK
8942 begin
8943 Formals := New_List (
70482933 8944
df3e68b1 8945 -- V : in out Typ
fbf5a39b 8946
df3e68b1 8947 Make_Parameter_Specification (Loc,
2c1b72d7
AC
8948 Defining_Identifier => Make_Defining_Identifier (Loc, Name_V),
8949 In_Present => True,
8950 Out_Present => True,
e4494292 8951 Parameter_Type => New_Occurrence_Of (Typ, Loc)),
70482933 8952
df3e68b1 8953 -- F : Boolean := True
70482933 8954
df3e68b1 8955 Make_Parameter_Specification (Loc,
2c1b72d7 8956 Defining_Identifier => Make_Defining_Identifier (Loc, Name_F),
e4494292
RD
8957 Parameter_Type => New_Occurrence_Of (Standard_Boolean, Loc),
8958 Expression => New_Occurrence_Of (Standard_True, Loc)));
df3e68b1
HK
8959
8960 -- Add the necessary number of counters to represent the initialization
8961 -- state of an object.
8962
8963 return
8964 Make_Subprogram_Body (Loc,
8965 Specification =>
8966 Make_Procedure_Specification (Loc,
2c1b72d7 8967 Defining_Unit_Name => Nam,
df3e68b1
HK
8968 Parameter_Specifications => Formals),
8969
8970 Declarations => No_List,
8971
8972 Handled_Statement_Sequence =>
8973 Make_Handled_Sequence_Of_Statements (Loc,
2c1b72d7 8974 Statements => Make_Deep_Record_Body (Finalize_Case, Typ, True)));
df3e68b1
HK
8975 end Make_Local_Deep_Finalize;
8976
b254da66
AC
8977 ------------------------------------
8978 -- Make_Set_Finalize_Address_Call --
8979 ------------------------------------
8980
8981 function Make_Set_Finalize_Address_Call
59e6b23c 8982 (Loc : Source_Ptr;
b254da66
AC
8983 Ptr_Typ : Entity_Id) return Node_Id
8984 is
b6a56408
AC
8985 -- It is possible for Ptr_Typ to be a partial view, if the access type
8986 -- is a full view declared in the private part of a nested package, and
8987 -- the finalization actions take place when completing analysis of the
8988 -- enclosing unit. For this reason use Underlying_Type twice below.
cd1a470a 8989
760804f3 8990 Desig_Typ : constant Entity_Id :=
cd1a470a
AC
8991 Available_View
8992 (Designated_Type (Underlying_Type (Ptr_Typ)));
760804f3 8993 Fin_Addr : constant Entity_Id := Finalize_Address (Desig_Typ);
cd1a470a
AC
8994 Fin_Mas : constant Entity_Id :=
8995 Finalization_Master (Underlying_Type (Ptr_Typ));
b254da66
AC
8996
8997 begin
760804f3
AC
8998 -- Both the finalization master and primitive Finalize_Address must be
8999 -- available.
b254da66 9000
760804f3 9001 pragma Assert (Present (Fin_Addr) and Present (Fin_Mas));
0d566e01 9002
b254da66 9003 -- Generate:
760804f3
AC
9004 -- Set_Finalize_Address
9005 -- (<Ptr_Typ>FM, <Desig_Typ>FD'Unrestricted_Access);
b254da66 9006
94bbf008 9007 return
b254da66 9008 Make_Procedure_Call_Statement (Loc,
59e6b23c 9009 Name =>
e4494292 9010 New_Occurrence_Of (RTE (RE_Set_Finalize_Address), Loc),
b254da66 9011 Parameter_Associations => New_List (
760804f3
AC
9012 New_Occurrence_Of (Fin_Mas, Loc),
9013
b254da66 9014 Make_Attribute_Reference (Loc,
760804f3 9015 Prefix => New_Occurrence_Of (Fin_Addr, Loc),
b254da66
AC
9016 Attribute_Name => Name_Unrestricted_Access)));
9017 end Make_Set_Finalize_Address_Call;
9018
70482933
RK
9019 --------------------------
9020 -- Make_Transient_Block --
9021 --------------------------
9022
70482933
RK
9023 function Make_Transient_Block
9024 (Loc : Source_Ptr;
df3e68b1
HK
9025 Action : Node_Id;
9026 Par : Node_Id) return Node_Id
70482933 9027 is
f32eb591
AC
9028 function Manages_Sec_Stack (Id : Entity_Id) return Boolean;
9029 -- Determine whether scoping entity Id manages the secondary stack
70482933 9030
f2c2cdfb
HK
9031 function Within_Loop_Statement (N : Node_Id) return Boolean;
9032 -- Return True when N appears within a loop and no block is containing N
01bd58f5 9033
f32eb591
AC
9034 -----------------------
9035 -- Manages_Sec_Stack --
9036 -----------------------
70482933 9037
f32eb591
AC
9038 function Manages_Sec_Stack (Id : Entity_Id) return Boolean is
9039 begin
7a71a7c4 9040 case Ekind (Id) is
c1fd002c 9041
7a71a7c4
AC
9042 -- An exception handler with a choice parameter utilizes a dummy
9043 -- block to provide a declarative region. Such a block should not
9044 -- be considered because it never manifests in the tree and can
9045 -- never release the secondary stack.
70482933 9046
7a71a7c4
AC
9047 when E_Block =>
9048 return
9049 Uses_Sec_Stack (Id) and then not Is_Exception_Handler (Id);
70482933 9050
7a71a7c4
AC
9051 when E_Entry
9052 | E_Entry_Family
9053 | E_Function
9054 | E_Procedure
9055 =>
9056 return Uses_Sec_Stack (Id);
9057
9058 when others =>
9059 return False;
9060 end case;
f32eb591 9061 end Manages_Sec_Stack;
70482933 9062
f2c2cdfb
HK
9063 ---------------------------
9064 -- Within_Loop_Statement --
9065 ---------------------------
9066
9067 function Within_Loop_Statement (N : Node_Id) return Boolean is
9068 Par : Node_Id := Parent (N);
9069
9070 begin
4a08c95c
AC
9071 while Nkind (Par) not in
9072 N_Handled_Sequence_Of_Statements | N_Loop_Statement |
9073 N_Package_Specification | N_Proper_Body
f2c2cdfb
HK
9074 loop
9075 pragma Assert (Present (Par));
9076 Par := Parent (Par);
9077 end loop;
9078
9079 return Nkind (Par) = N_Loop_Statement;
9080 end Within_Loop_Statement;
9081
f32eb591 9082 -- Local variables
70482933 9083
f32eb591
AC
9084 Decls : constant List_Id := New_List;
9085 Instrs : constant List_Id := New_List (Action);
9086 Trans_Id : constant Entity_Id := Current_Scope;
70482933 9087
f32eb591
AC
9088 Block : Node_Id;
9089 Insert : Node_Id;
9090 Scop : Entity_Id;
70482933 9091
f32eb591 9092 -- Start of processing for Make_Transient_Block
70482933 9093
f32eb591
AC
9094 begin
9095 -- Even though the transient block is tasked with managing the secondary
9096 -- stack, the block may forgo this functionality depending on how the
9097 -- secondary stack is managed by enclosing scopes.
70482933 9098
f32eb591 9099 if Manages_Sec_Stack (Trans_Id) then
75a957f5 9100
f32eb591
AC
9101 -- Determine whether an enclosing scope already manages the secondary
9102 -- stack.
75a957f5 9103
f32eb591
AC
9104 Scop := Scope (Trans_Id);
9105 while Present (Scop) loop
70482933 9106
7a71a7c4
AC
9107 -- It should not be possible to reach Standard without hitting one
9108 -- of the other cases first unless Standard was manually pushed.
f32eb591 9109
7a71a7c4 9110 if Scop = Standard_Standard then
f32eb591
AC
9111 exit;
9112
9113 -- The transient block is within a function which returns on the
9114 -- secondary stack. Take a conservative approach and assume that
9115 -- the value on the secondary stack is part of the result. Note
9116 -- that it is not possible to detect this dependency without flow
9117 -- analysis which the compiler does not have. Letting the object
9118 -- live longer than the transient block will not leak any memory
9119 -- because the caller will reclaim the total storage used by the
9120 -- function.
9121
9122 elsif Ekind (Scop) = E_Function
9123 and then Sec_Stack_Needed_For_Return (Scop)
9124 then
9125 Set_Uses_Sec_Stack (Trans_Id, False);
9126 exit;
9127
7a71a7c4
AC
9128 -- The transient block must manage the secondary stack when the
9129 -- block appears within a loop in order to reclaim the memory at
9130 -- each iteration.
9131
9132 elsif Ekind (Scop) = E_Loop then
9133 exit;
9134
01bd58f5
JM
9135 -- Ditto when the block appears without a block that does not
9136 -- manage the secondary stack and is located within a loop.
9137
9138 elsif Ekind (Scop) = E_Block
9139 and then not Manages_Sec_Stack (Scop)
9140 and then Present (Block_Node (Scop))
9141 and then Within_Loop_Statement (Block_Node (Scop))
9142 then
9143 exit;
9144
7a71a7c4
AC
9145 -- The transient block does not need to manage the secondary stack
9146 -- when there is an enclosing construct which already does that.
f32eb591
AC
9147 -- This optimization saves on SS_Mark and SS_Release calls but may
9148 -- allow objects to live a little longer than required.
9149
7a71a7c4
AC
9150 -- The transient block must manage the secondary stack when switch
9151 -- -gnatd.s (strict management) is in effect.
9152
9153 elsif Manages_Sec_Stack (Scop) and then not Debug_Flag_Dot_S then
f32eb591
AC
9154 Set_Uses_Sec_Stack (Trans_Id, False);
9155 exit;
7a71a7c4
AC
9156
9157 -- Prevent the search from going too far because transient blocks
9158 -- are bounded by packages and subprogram scopes.
9159
4a08c95c
AC
9160 elsif Ekind (Scop) in E_Entry
9161 | E_Entry_Family
9162 | E_Function
9163 | E_Package
9164 | E_Procedure
9165 | E_Subprogram_Body
7a71a7c4
AC
9166 then
9167 exit;
f32eb591
AC
9168 end if;
9169
9170 Scop := Scope (Scop);
9171 end loop;
70482933
RK
9172 end if;
9173
df3e68b1 9174 -- Create the transient block. Set the parent now since the block itself
f32eb591
AC
9175 -- is not part of the tree. The current scope is the E_Block entity that
9176 -- has been pushed by Establish_Transient_Scope.
9177
9178 pragma Assert (Ekind (Trans_Id) = E_Block);
70482933 9179
df3e68b1 9180 Block :=
70482933 9181 Make_Block_Statement (Loc,
f32eb591 9182 Identifier => New_Occurrence_Of (Trans_Id, Loc),
2c1b72d7 9183 Declarations => Decls,
70482933 9184 Handled_Statement_Sequence =>
2c1b72d7
AC
9185 Make_Handled_Sequence_Of_Statements (Loc, Statements => Instrs),
9186 Has_Created_Identifier => True);
df3e68b1
HK
9187 Set_Parent (Block, Par);
9188
9189 -- Insert actions stuck in the transient scopes as well as all freezing
8071b771
AC
9190 -- nodes needed by those actions. Do not insert cleanup actions here,
9191 -- they will be transferred to the newly created block.
df3e68b1 9192
8e888920
AC
9193 Insert_Actions_In_Scope_Around
9194 (Action, Clean => False, Manage_SS => False);
df3e68b1
HK
9195
9196 Insert := Prev (Action);
f32eb591 9197
df3e68b1 9198 if Present (Insert) then
f32eb591 9199 Freeze_All (First_Entity (Trans_Id), Insert);
df3e68b1 9200 end if;
70482933 9201
36295779
AC
9202 -- Transfer cleanup actions to the newly created block
9203
9204 declare
9205 Cleanup_Actions : List_Id
9206 renames Scope_Stack.Table (Scope_Stack.Last).
9207 Actions_To_Be_Wrapped (Cleanup);
9208 begin
9209 Set_Cleanup_Actions (Block, Cleanup_Actions);
9210 Cleanup_Actions := No_List;
9211 end;
9212
886b5a18
AC
9213 -- When the transient scope was established, we pushed the entry for the
9214 -- transient scope onto the scope stack, so that the scope was active
9215 -- for the installation of finalizable entities etc. Now we must remove
9216 -- this entry, since we have constructed a proper block.
70482933
RK
9217
9218 Pop_Scope;
9219
df3e68b1 9220 return Block;
70482933
RK
9221 end Make_Transient_Block;
9222
9223 ------------------------
9224 -- Node_To_Be_Wrapped --
9225 ------------------------
9226
9227 function Node_To_Be_Wrapped return Node_Id is
9228 begin
9229 return Scope_Stack.Table (Scope_Stack.Last).Node_To_Be_Wrapped;
9230 end Node_To_Be_Wrapped;
9231
36295779
AC
9232 ----------------------------
9233 -- Store_Actions_In_Scope --
9234 ----------------------------
70482933 9235
36295779
AC
9236 procedure Store_Actions_In_Scope (AK : Scope_Action_Kind; L : List_Id) is
9237 SE : Scope_Stack_Entry renames Scope_Stack.Table (Scope_Stack.Last);
9238 Actions : List_Id renames SE.Actions_To_Be_Wrapped (AK);
70482933
RK
9239
9240 begin
fff7a6d9 9241 if Is_Empty_List (Actions) then
36295779 9242 Actions := L;
70482933
RK
9243
9244 if Is_List_Member (SE.Node_To_Be_Wrapped) then
9245 Set_Parent (L, Parent (SE.Node_To_Be_Wrapped));
9246 else
9247 Set_Parent (L, SE.Node_To_Be_Wrapped);
9248 end if;
9249
9250 Analyze_List (L);
36295779
AC
9251
9252 elsif AK = Before then
9253 Insert_List_After_And_Analyze (Last (Actions), L);
9254
9255 else
9256 Insert_List_Before_And_Analyze (First (Actions), L);
70482933 9257 end if;
36295779
AC
9258 end Store_Actions_In_Scope;
9259
9260 ----------------------------------
9261 -- Store_After_Actions_In_Scope --
9262 ----------------------------------
9263
9264 procedure Store_After_Actions_In_Scope (L : List_Id) is
9265 begin
9266 Store_Actions_In_Scope (After, L);
70482933
RK
9267 end Store_After_Actions_In_Scope;
9268
9269 -----------------------------------
9270 -- Store_Before_Actions_In_Scope --
9271 -----------------------------------
9272
9273 procedure Store_Before_Actions_In_Scope (L : List_Id) is
70482933 9274 begin
36295779
AC
9275 Store_Actions_In_Scope (Before, L);
9276 end Store_Before_Actions_In_Scope;
70482933 9277
36295779
AC
9278 -----------------------------------
9279 -- Store_Cleanup_Actions_In_Scope --
9280 -----------------------------------
70482933 9281
36295779
AC
9282 procedure Store_Cleanup_Actions_In_Scope (L : List_Id) is
9283 begin
9284 Store_Actions_In_Scope (Cleanup, L);
9285 end Store_Cleanup_Actions_In_Scope;
70482933 9286
f68289d8
GD
9287 ------------------
9288 -- Unnest_Block --
9289 ------------------
9290
9291 procedure Unnest_Block (Decl : Node_Id) is
9292 Loc : constant Source_Ptr := Sloc (Decl);
9293 Ent : Entity_Id;
9294 Local_Body : Node_Id;
9295 Local_Call : Node_Id;
9296 Local_Proc : Entity_Id;
9297 Local_Scop : Entity_Id;
9298
9299 begin
9300 Local_Scop := Entity (Identifier (Decl));
9301 Ent := First_Entity (Local_Scop);
9302
a8d89c45 9303 Local_Proc := Make_Temporary (Loc, 'P');
f68289d8
GD
9304
9305 Local_Body :=
9306 Make_Subprogram_Body (Loc,
9307 Specification =>
9308 Make_Procedure_Specification (Loc,
9309 Defining_Unit_Name => Local_Proc),
9310 Declarations => Declarations (Decl),
9311 Handled_Statement_Sequence =>
9312 Handled_Statement_Sequence (Decl));
9313
05746958
GD
9314 -- Handlers in the block may contain nested subprograms that require
9315 -- unnesting.
9316
9317 Check_Unnesting_In_Handlers (Local_Body);
9318
f68289d8
GD
9319 Rewrite (Decl, Local_Body);
9320 Analyze (Decl);
9321 Set_Has_Nested_Subprogram (Local_Proc);
9322
9323 Local_Call :=
9324 Make_Procedure_Call_Statement (Loc,
9325 Name => New_Occurrence_Of (Local_Proc, Loc));
9326
9327 Insert_After (Decl, Local_Call);
9328 Analyze (Local_Call);
9329
9330 -- The new subprogram has the same scope as the original block
9331
9332 Set_Scope (Local_Proc, Scope (Local_Scop));
9333
9334 -- And the entity list of the new procedure is that of the block
9335
9336 Set_First_Entity (Local_Proc, Ent);
9337
9338 -- Reset the scopes of all the entities to the new procedure
9339
9340 while Present (Ent) loop
9341 Set_Scope (Ent, Local_Proc);
9342 Next_Entity (Ent);
9343 end loop;
9344 end Unnest_Block;
9345
05746958
GD
9346 -------------------------
9347 -- Unnest_If_Statement --
9348 -------------------------
9349
9350 procedure Unnest_If_Statement (If_Stmt : Node_Id) is
9351
9352 procedure Check_Stmts_For_Subp_Unnesting (Stmts : in out List_Id);
9353 -- A list of statements (that may be a list associated with a then,
9354 -- elsif, or else part of an if-statement) is traversed at the top
9355 -- level to determine whether it contains a subprogram body, and if so,
9356 -- the statements will be replaced with a new procedure body containing
9357 -- the statements followed by a call to the procedure. The individual
9358 -- statements may also be blocks, loops, or other if statements that
9359 -- themselves may require contain nested subprograms needing unnesting.
9360
9361 procedure Check_Stmts_For_Subp_Unnesting (Stmts : in out List_Id) is
9362 Subp_Found : Boolean := False;
9363
9364 begin
9365 if Is_Empty_List (Stmts) then
9366 return;
9367 end if;
9368
9369 declare
9370 Stmt : Node_Id := First (Stmts);
9371 begin
9372 while Present (Stmt) loop
9373 if Nkind (Stmt) = N_Subprogram_Body then
9374 Subp_Found := True;
9375 exit;
9376 end if;
9377
9378 Next (Stmt);
9379 end loop;
9380 end;
9381
9382 -- The statements themselves may be blocks, loops, etc. that in turn
9383 -- contain nested subprograms requiring an unnesting transformation.
9384 -- We perform this traversal after looking for subprogram bodies, to
9385 -- avoid considering procedures created for one of those statements
9386 -- (such as a block rewritten as a procedure) as a nested subprogram
9387 -- of the statement list (which could result in an unneeded wrapper
9388 -- procedure).
9389
9390 Check_Unnesting_In_Decls_Or_Stmts (Stmts);
9391
9392 -- If there was a top-level subprogram body in the statement list,
9393 -- then perform an unnesting transformation on the list by replacing
9394 -- the statements with a wrapper procedure body containing the
9395 -- original statements followed by a call to that procedure.
9396
9397 if Subp_Found then
9398 Unnest_Statement_List (Stmts);
9399 end if;
9400 end Check_Stmts_For_Subp_Unnesting;
9401
9402 -- Local variables
9403
9404 Then_Stmts : List_Id := Then_Statements (If_Stmt);
9405 Else_Stmts : List_Id := Else_Statements (If_Stmt);
9406
9407 -- Start of processing for Unnest_If_Statement
9408
9409 begin
9410 Check_Stmts_For_Subp_Unnesting (Then_Stmts);
9411 Set_Then_Statements (If_Stmt, Then_Stmts);
9412
9413 if not Is_Empty_List (Elsif_Parts (If_Stmt)) then
9414 declare
9415 Elsif_Part : Node_Id :=
9416 First (Elsif_Parts (If_Stmt));
9417 Elsif_Stmts : List_Id;
9418 begin
9419 while Present (Elsif_Part) loop
9420 Elsif_Stmts := Then_Statements (Elsif_Part);
9421
9422 Check_Stmts_For_Subp_Unnesting (Elsif_Stmts);
9423 Set_Then_Statements (Elsif_Part, Elsif_Stmts);
9424
9425 Next (Elsif_Part);
9426 end loop;
9427 end;
9428 end if;
9429
9430 Check_Stmts_For_Subp_Unnesting (Else_Stmts);
9431 Set_Else_Statements (If_Stmt, Else_Stmts);
9432 end Unnest_If_Statement;
9433
7e536bfd
GD
9434 -----------------
9435 -- Unnest_Loop --
9436 -----------------
9437
9438 procedure Unnest_Loop (Loop_Stmt : Node_Id) is
9439 Loc : constant Source_Ptr := Sloc (Loop_Stmt);
9440 Ent : Entity_Id;
9441 Local_Body : Node_Id;
9442 Local_Call : Node_Id;
9443 Local_Proc : Entity_Id;
9444 Local_Scop : Entity_Id;
9445 Loop_Copy : constant Node_Id :=
9446 Relocate_Node (Loop_Stmt);
9447 begin
9448 Local_Scop := Entity (Identifier (Loop_Stmt));
9449 Ent := First_Entity (Local_Scop);
9450
a8d89c45 9451 Local_Proc := Make_Temporary (Loc, 'P');
7e536bfd
GD
9452
9453 Local_Body :=
9454 Make_Subprogram_Body (Loc,
9455 Specification =>
9456 Make_Procedure_Specification (Loc,
9457 Defining_Unit_Name => Local_Proc),
9458 Declarations => Empty_List,
9459 Handled_Statement_Sequence =>
9460 Make_Handled_Sequence_Of_Statements (Loc,
9461 Statements => New_List (Loop_Copy)));
9462
7e536bfd
GD
9463 Rewrite (Loop_Stmt, Local_Body);
9464 Analyze (Loop_Stmt);
9465
9466 Set_Has_Nested_Subprogram (Local_Proc);
9467
9468 Local_Call :=
9469 Make_Procedure_Call_Statement (Loc,
9470 Name => New_Occurrence_Of (Local_Proc, Loc));
9471
9472 Insert_After (Loop_Stmt, Local_Call);
9473 Analyze (Local_Call);
9474
9475 -- New procedure has the same scope as the original loop, and the scope
9476 -- of the loop is the new procedure.
9477
9478 Set_Scope (Local_Proc, Scope (Local_Scop));
9479 Set_Scope (Local_Scop, Local_Proc);
9480
9481 -- The entity list of the new procedure is that of the loop
9482
9483 Set_First_Entity (Local_Proc, Ent);
9484
9485 -- Note that the entities associated with the loop don't need to have
9486 -- their Scope fields reset, since they're still associated with the
9487 -- same loop entity that now belongs to the copied loop statement.
9488 end Unnest_Loop;
9489
05746958
GD
9490 ---------------------------
9491 -- Unnest_Statement_List --
9492 ---------------------------
9493
9494 procedure Unnest_Statement_List (Stmts : in out List_Id) is
9495 Loc : constant Source_Ptr := Sloc (First (Stmts));
9496 Local_Body : Node_Id;
9497 Local_Call : Node_Id;
9498 Local_Proc : Entity_Id;
9499 New_Stmts : constant List_Id := Empty_List;
9500
9501 begin
a8d89c45 9502 Local_Proc := Make_Temporary (Loc, 'P');
05746958
GD
9503
9504 Local_Body :=
9505 Make_Subprogram_Body (Loc,
9506 Specification =>
9507 Make_Procedure_Specification (Loc,
9508 Defining_Unit_Name => Local_Proc),
9509 Declarations => Empty_List,
9510 Handled_Statement_Sequence =>
9511 Make_Handled_Sequence_Of_Statements (Loc,
9512 Statements => Stmts));
9513
9514 Append_To (New_Stmts, Local_Body);
9515
9516 Analyze (Local_Body);
9517
9518 Set_Has_Nested_Subprogram (Local_Proc);
9519
9520 Local_Call :=
9521 Make_Procedure_Call_Statement (Loc,
9522 Name => New_Occurrence_Of (Local_Proc, Loc));
9523
9524 Append_To (New_Stmts, Local_Call);
9525 Analyze (Local_Call);
9526
9527 -- Traverse the statements, and for any that are declarations or
9528 -- subprogram bodies that have entities, set the Scope of those
9529 -- entities to the new procedure's Entity_Id.
9530
9531 declare
9532 Stmt : Node_Id := First (Stmts);
9533
9534 begin
9535 while Present (Stmt) loop
9536 case Nkind (Stmt) is
9537 when N_Declaration
9538 | N_Renaming_Declaration
9539 =>
9540 Set_Scope (Defining_Identifier (Stmt), Local_Proc);
9541
9542 when N_Subprogram_Body =>
9543 Set_Scope
9544 (Defining_Unit_Name (Specification (Stmt)), Local_Proc);
9545
9546 when others =>
9547 null;
9548 end case;
9549
9550 Next (Stmt);
9551 end loop;
9552 end;
9553
9554 Stmts := New_Stmts;
9555 end Unnest_Statement_List;
9556
70482933
RK
9557 --------------------------------
9558 -- Wrap_Transient_Declaration --
9559 --------------------------------
9560
9561 -- If a transient scope has been established during the processing of the
9562 -- Expression of an Object_Declaration, it is not possible to wrap the
9563 -- declaration into a transient block as usual case, otherwise the object
9564 -- would be itself declared in the wrong scope. Therefore, all entities (if
9565 -- any) defined in the transient block are moved to the proper enclosing
8071b771 9566 -- scope. Furthermore, if they are controlled variables they are finalized
70482933
RK
9567 -- right after the declaration. The finalization list of the transient
9568 -- scope is defined as a renaming of the enclosing one so during their
cfae2bed
AC
9569 -- initialization they will be attached to the proper finalization list.
9570 -- For instance, the following declaration :
70482933
RK
9571
9572 -- X : Typ := F (G (A), G (B));
9573
9574 -- (where G(A) and G(B) return controlled values, expanded as _v1 and _v2)
9575 -- is expanded into :
9576
70482933 9577 -- X : Typ := [ complex Expression-Action ];
df3e68b1
HK
9578 -- [Deep_]Finalize (_v1);
9579 -- [Deep_]Finalize (_v2);
70482933
RK
9580
9581 procedure Wrap_Transient_Declaration (N : Node_Id) is
8e888920
AC
9582 Curr_S : Entity_Id;
9583 Encl_S : Entity_Id;
23685ae6 9584
70482933 9585 begin
8e888920
AC
9586 Curr_S := Current_Scope;
9587 Encl_S := Scope (Curr_S);
9588
57d3adcd 9589 -- Insert all actions including cleanup generated while analyzing or
8e888920
AC
9590 -- expanding the transient context back into the tree. Manage the
9591 -- secondary stack when the object declaration appears in a library
57d3adcd 9592 -- level package [body].
8e888920
AC
9593
9594 Insert_Actions_In_Scope_Around
9595 (N => N,
9596 Clean => True,
9597 Manage_SS =>
535a8637 9598 Uses_Sec_Stack (Curr_S)
8e888920 9599 and then Nkind (N) = N_Object_Declaration
4a08c95c 9600 and then Ekind (Encl_S) in E_Package | E_Package_Body
8e888920 9601 and then Is_Library_Level_Entity (Encl_S));
70482933
RK
9602 Pop_Scope;
9603
8e888920
AC
9604 -- Relocate local entities declared within the transient scope to the
9605 -- enclosing scope. This action sets their Is_Public flag accordingly.
9606
9607 Transfer_Entities (Curr_S, Encl_S);
70482933 9608
8e888920 9609 -- Mark the enclosing dynamic scope to ensure that the secondary stack
535a8637 9610 -- is properly released upon exiting the said scope.
70482933 9611
535a8637 9612 if Uses_Sec_Stack (Curr_S) then
8e888920 9613 Curr_S := Enclosing_Dynamic_Scope (Curr_S);
70482933 9614
8e888920
AC
9615 -- Do not mark a function that returns on the secondary stack as the
9616 -- reclamation is done by the caller.
70482933 9617
8e888920 9618 if Ekind (Curr_S) = E_Function
5cfde7a0 9619 and then Needs_Secondary_Stack (Etype (Curr_S))
70482933
RK
9620 then
9621 null;
8e888920
AC
9622
9623 -- Otherwise mark the enclosing dynamic scope
9624
70482933 9625 else
8e888920 9626 Set_Uses_Sec_Stack (Curr_S);
17c5c8a5 9627 Check_Restriction (No_Secondary_Stack, N);
70482933
RK
9628 end if;
9629 end if;
9630 end Wrap_Transient_Declaration;
9631
9632 -------------------------------
9633 -- Wrap_Transient_Expression --
9634 -------------------------------
9635
70482933 9636 procedure Wrap_Transient_Expression (N : Node_Id) is
df3e68b1 9637 Loc : constant Source_Ptr := Sloc (N);
d8a764c4 9638 Expr : Node_Id := Relocate_Node (N);
df3e68b1
HK
9639 Temp : constant Entity_Id := Make_Temporary (Loc, 'E', N);
9640 Typ : constant Entity_Id := Etype (N);
70482933
RK
9641
9642 begin
df3e68b1 9643 -- Generate:
cfae2bed 9644
df3e68b1
HK
9645 -- Temp : Typ;
9646 -- declare
9647 -- M : constant Mark_Id := SS_Mark;
9648 -- procedure Finalizer is ... (See Build_Finalizer)
41c79d60 9649
df3e68b1 9650 -- begin
d8a764c4
AC
9651 -- Temp := <Expr>; -- general case
9652 -- Temp := (if <Expr> then True else False); -- boolean case
41c79d60 9653
df3e68b1
HK
9654 -- at end
9655 -- Finalizer;
9656 -- end;
9657
40c21e91 9658 -- A special case is made for Boolean expressions so that the back end
061828e3 9659 -- knows to generate a conditional branch instruction, if running with
40c21e91
PMR
9660 -- -fpreserve-control-flow. This ensures that a control-flow change
9661 -- signaling the decision outcome occurs before the cleanup actions.
d8a764c4 9662
061828e3 9663 if Opt.Suppress_Control_Flow_Optimizations
7dbd3de9 9664 and then Is_Boolean_Type (Typ)
061828e3 9665 then
4058ddcc
AC
9666 Expr :=
9667 Make_If_Expression (Loc,
9668 Expressions => New_List (
9669 Expr,
9670 New_Occurrence_Of (Standard_True, Loc),
9671 New_Occurrence_Of (Standard_False, Loc)));
d8a764c4
AC
9672 end if;
9673
70482933
RK
9674 Insert_Actions (N, New_List (
9675 Make_Object_Declaration (Loc,
df3e68b1 9676 Defining_Identifier => Temp,
e4494292 9677 Object_Definition => New_Occurrence_Of (Typ, Loc)),
70482933
RK
9678
9679 Make_Transient_Block (Loc,
9680 Action =>
9681 Make_Assignment_Statement (Loc,
e4494292 9682 Name => New_Occurrence_Of (Temp, Loc),
df3e68b1 9683 Expression => Expr),
2c1b72d7 9684 Par => Parent (N))));
70482933 9685
bbf14e13
AC
9686 if Debug_Generated_Code then
9687 Set_Debug_Info_Needed (Temp);
9688 end if;
9689
e4494292 9690 Rewrite (N, New_Occurrence_Of (Temp, Loc));
df3e68b1 9691 Analyze_And_Resolve (N, Typ);
70482933
RK
9692 end Wrap_Transient_Expression;
9693
9694 ------------------------------
9695 -- Wrap_Transient_Statement --
9696 ------------------------------
9697
70482933 9698 procedure Wrap_Transient_Statement (N : Node_Id) is
df3e68b1
HK
9699 Loc : constant Source_Ptr := Sloc (N);
9700 New_Stmt : constant Node_Id := Relocate_Node (N);
70482933
RK
9701
9702 begin
df3e68b1
HK
9703 -- Generate:
9704 -- declare
9705 -- M : constant Mark_Id := SS_Mark;
9706 -- procedure Finalizer is ... (See Build_Finalizer)
9707 --
9708 -- begin
9709 -- <New_Stmt>;
9710 --
9711 -- at end
9712 -- Finalizer;
9713 -- end;
9714
9715 Rewrite (N,
9716 Make_Transient_Block (Loc,
9717 Action => New_Stmt,
9718 Par => Parent (N)));
70482933
RK
9719
9720 -- With the scope stack back to normal, we can call analyze on the
9721 -- resulting block. At this point, the transient scope is being
9722 -- treated like a perfectly normal scope, so there is nothing
9723 -- special about it.
9724
9725 -- Note: Wrap_Transient_Statement is called with the node already
9726 -- analyzed (i.e. Analyzed (N) is True). This is important, since
9727 -- otherwise we would get a recursive processing of the node when
9728 -- we do this Analyze call.
9729
9730 Analyze (N);
9731 end Wrap_Transient_Statement;
9732
9733end Exp_Ch7;
This page took 7.25301 seconds and 5 git commands to generate.