OSDN Git Service

* 41intnam.ads, 42intnam.ads, 4aintnam.ads, 4cintnam.ads,
[pf3gnuchains/gcc-fork.git] / gcc / ada / inline.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                               I N L I N E                                --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --                            $Revision$
10 --                                                                          --
11 --          Copyright (C) 1992-2001 Free Software Foundation, Inc.          --
12 --                                                                          --
13 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
14 -- terms of the  GNU General Public License as published  by the Free Soft- --
15 -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
16 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
17 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
18 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
19 -- for  more details.  You should have  received  a copy of the GNU General --
20 -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
21 -- to  the Free Software Foundation,  59 Temple Place - Suite 330,  Boston, --
22 -- MA 02111-1307, USA.                                                      --
23 --                                                                          --
24 -- GNAT was originally developed  by the GNAT team at  New York University. --
25 -- It is now maintained by Ada Core Technologies Inc (http://www.gnat.com). --
26 --                                                                          --
27 ------------------------------------------------------------------------------
28
29 with Atree;    use Atree;
30 with Einfo;    use Einfo;
31 with Elists;   use Elists;
32 with Errout;   use Errout;
33 with Exp_Ch7;  use Exp_Ch7;
34 with Exp_Ch11; use Exp_Ch11;
35 with Exp_Tss;  use Exp_Tss;
36 with Fname;    use Fname;
37 with Fname.UF; use Fname.UF;
38 with Lib;      use Lib;
39 with Nlists;   use Nlists;
40 with Opt;      use Opt;
41 with Sem_Ch8;  use Sem_Ch8;
42 with Sem_Ch10; use Sem_Ch10;
43 with Sem_Ch12; use Sem_Ch12;
44 with Sem_Util; use Sem_Util;
45 with Sinfo;    use Sinfo;
46 with Snames;   use Snames;
47 with Stand;    use Stand;
48 with Uname;    use Uname;
49
50 package body Inline is
51
52    --------------------
53    -- Inlined Bodies --
54    --------------------
55
56    --  Inlined functions are actually placed in line by the backend if the
57    --  corresponding bodies are available (i.e. compiled). Whenever we find
58    --  a call to an inlined subprogram, we add the name of the enclosing
59    --  compilation unit to a worklist. After all compilation, and after
60    --  expansion of generic bodies, we traverse the list of pending bodies
61    --  and compile them as well.
62
63    package Inlined_Bodies is new Table.Table (
64      Table_Component_Type => Entity_Id,
65      Table_Index_Type     => Int,
66      Table_Low_Bound      => 0,
67      Table_Initial        => Alloc.Inlined_Bodies_Initial,
68      Table_Increment      => Alloc.Inlined_Bodies_Increment,
69      Table_Name           => "Inlined_Bodies");
70
71    -----------------------
72    -- Inline Processing --
73    -----------------------
74
75    --  For each call to an inlined subprogram, we make entries in a table
76    --  that stores caller and callee, and indicates a prerequisite from
77    --  one to the other. We also record the compilation unit that contains
78    --  the callee. After analyzing the bodies of all such compilation units,
79    --  we produce a list of subprograms in  topological order, for use by the
80    --  back-end. If P2 is a prerequisite of P1, then P1 calls P2, and for
81    --  proper inlining the back-end must analyze the body of P2 before that of
82    --  P1. The code below guarantees that the transitive closure of inlined
83    --  subprograms called from the main compilation unit is made available to
84    --  the code generator.
85
86    Last_Inlined : Entity_Id := Empty;
87
88    --  For each entry in the table we keep a list of successors in topological
89    --  order, i.e. callers of the current subprogram.
90
91    type Subp_Index is new Nat;
92    No_Subp : constant Subp_Index := 0;
93
94    --  The subprogram entities are hashed into the Inlined table.
95
96    Num_Hash_Headers : constant := 512;
97
98    Hash_Headers : array (Subp_Index range 0 .. Num_Hash_Headers - 1)
99                                                           of Subp_Index;
100
101    type Succ_Index is new Nat;
102    No_Succ : constant Succ_Index := 0;
103
104    type Succ_Info is record
105       Subp : Subp_Index;
106       Next : Succ_Index;
107    end record;
108
109    --  The following table stores list elements for the successor lists.
110    --  These lists cannot be chained directly through entries in the Inlined
111    --  table, because a given subprogram can appear in several such lists.
112
113    package Successors is new Table.Table (
114       Table_Component_Type => Succ_Info,
115       Table_Index_Type     => Succ_Index,
116       Table_Low_Bound      => 1,
117       Table_Initial        => Alloc.Successors_Initial,
118       Table_Increment      => Alloc.Successors_Increment,
119       Table_Name           => "Successors");
120
121    type Subp_Info is record
122       Name        : Entity_Id  := Empty;
123       First_Succ  : Succ_Index := No_Succ;
124       Count       : Integer    := 0;
125       Listed      : Boolean    := False;
126       Main_Call   : Boolean    := False;
127       Next        : Subp_Index := No_Subp;
128       Next_Nopred : Subp_Index := No_Subp;
129    end record;
130
131    package Inlined is new Table.Table (
132       Table_Component_Type => Subp_Info,
133       Table_Index_Type     => Subp_Index,
134       Table_Low_Bound      => 1,
135       Table_Initial        => Alloc.Inlined_Initial,
136       Table_Increment      => Alloc.Inlined_Increment,
137       Table_Name           => "Inlined");
138
139    -----------------------
140    -- Local Subprograms --
141    -----------------------
142
143    function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean;
144    --  Return True if Scop is in the main unit or its spec, or in a
145    --  parent of the main unit if it is a child unit.
146
147    procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty);
148    --  Make two entries in Inlined table, for an inlined subprogram being
149    --  called, and for the inlined subprogram that contains the call. If
150    --  the call is in the main compilation unit, Caller is Empty.
151
152    function Add_Subp (E : Entity_Id) return Subp_Index;
153    --  Make entry in Inlined table for subprogram E, or return table index
154    --  that already holds E.
155
156    function Has_Initialized_Type (E : Entity_Id) return Boolean;
157    --  If a candidate for inlining contains type declarations for types with
158    --  non-trivial initialization procedures, they are not worth inlining.
159
160    function Is_Nested (E : Entity_Id) return Boolean;
161    --  If the function is nested inside some other function, it will
162    --  always be compiled if that function is, so don't add it to the
163    --  inline list. We cannot compile a nested function outside the
164    --  scope of the containing function anyway. This is also the case if
165    --  the function is defined in a task body or within an entry (for
166    --  example, an initialization procedure).
167
168    procedure Add_Inlined_Subprogram (Index : Subp_Index);
169    --  Add subprogram to Inlined List once all of its predecessors have been
170    --  placed on the list. Decrement the count of all its successors, and
171    --  add them to list (recursively) if count drops to zero.
172
173    ------------------------------
174    -- Deferred Cleanup Actions --
175    ------------------------------
176
177    --  The cleanup actions for scopes that contain instantiations is delayed
178    --  until after expansion of those instantiations, because they may
179    --  contain finalizable objects or tasks that affect the cleanup code.
180    --  A scope that contains instantiations only needs to be finalized once,
181    --  even if it contains more than one instance. We keep a list of scopes
182    --  that must still be finalized, and call cleanup_actions after all the
183    --  instantiations have been completed.
184
185    To_Clean : Elist_Id;
186
187    procedure Add_Scope_To_Clean (Inst : Entity_Id);
188    --  Build set of scopes on which cleanup actions must be performed.
189
190    procedure Cleanup_Scopes;
191    --  Complete cleanup actions on scopes that need it.
192
193    --------------
194    -- Add_Call --
195    --------------
196
197    procedure Add_Call (Called : Entity_Id; Caller : Entity_Id := Empty) is
198       P1 : Subp_Index := Add_Subp (Called);
199       P2 : Subp_Index;
200       J  : Succ_Index;
201
202    begin
203       if Present (Caller) then
204          P2 := Add_Subp (Caller);
205
206          --  Add P2 to the list of successors of P1, if not already there.
207          --  Note that P2 may contain more than one call to P1, and only
208          --  one needs to be recorded.
209
210          J := Inlined.Table (P1).First_Succ;
211
212          while J /= No_Succ loop
213
214             if Successors.Table (J).Subp = P2 then
215                return;
216             end if;
217
218             J := Successors.Table (J).Next;
219          end loop;
220
221          --  On exit, make a successor entry for P2.
222
223          Successors.Increment_Last;
224          Successors.Table (Successors.Last).Subp := P2;
225          Successors.Table (Successors.Last).Next :=
226                              Inlined.Table (P1).First_Succ;
227          Inlined.Table (P1).First_Succ := Successors.Last;
228
229          Inlined.Table (P2).Count := Inlined.Table (P2).Count + 1;
230
231       else
232          Inlined.Table (P1).Main_Call := True;
233       end if;
234    end Add_Call;
235
236    ----------------------
237    -- Add_Inlined_Body --
238    ----------------------
239
240    procedure Add_Inlined_Body (E : Entity_Id) is
241       Pack : Entity_Id;
242       Comp_Unit : Node_Id;
243
244       function Must_Inline return Boolean;
245       --  Inlining is only done if the call statement N is in the main unit,
246       --  or within the body of another inlined subprogram.
247
248       function Must_Inline return Boolean is
249          Scop : Entity_Id := Current_Scope;
250          Comp : Node_Id;
251
252       begin
253          --  Check if call is in main unit.
254
255          while Scope (Scop) /= Standard_Standard
256            and then not Is_Child_Unit (Scop)
257          loop
258             Scop := Scope (Scop);
259          end loop;
260
261          Comp := Parent (Scop);
262
263          while Nkind (Comp) /= N_Compilation_Unit loop
264             Comp := Parent (Comp);
265          end loop;
266
267          if (Comp = Cunit (Main_Unit)
268            or else Comp = Library_Unit (Cunit (Main_Unit)))
269          then
270             Add_Call (E);
271             return True;
272          end if;
273
274          --  Call is not in main unit. See if it's in some inlined
275          --  subprogram.
276
277          Scop := Current_Scope;
278          while Scope (Scop) /= Standard_Standard
279            and then not Is_Child_Unit (Scop)
280          loop
281             if Is_Overloadable (Scop)
282               and then Is_Inlined (Scop)
283             then
284                Add_Call (E, Scop);
285                return True;
286             end if;
287
288             Scop := Scope (Scop);
289          end loop;
290
291          return False;
292
293       end Must_Inline;
294
295    --  Start of processing for Add_Inlined_Body
296
297    begin
298       --  Find unit containing E, and add to list of inlined bodies if needed.
299       --  If the body is already present, no need to load any other unit. This
300       --  is the case for an initialization procedure, which appears in the
301       --  package declaration that contains the type. It is also the case if
302       --  the body has already been analyzed. Finally, if the unit enclosing
303       --  E is an instance, the instance body will be analyzed in any case,
304       --  and there is no need to add the enclosing unit (whose body might not
305       --  be available).
306
307       --  Library-level functions must be handled specially, because there is
308       --  no enclosing package to retrieve. In this case, it is the body of
309       --  the function that will have to be loaded.
310
311       if not Is_Abstract (E) and then not Is_Nested (E)
312         and then Convention (E) /= Convention_Protected
313       then
314          Pack := Scope (E);
315
316          if Must_Inline
317            and then Ekind (Pack) = E_Package
318          then
319             Set_Is_Called (E);
320             Comp_Unit := Parent (Pack);
321
322             if Pack = Standard_Standard then
323
324                --  Library-level inlined function. Add function iself to
325                --  list of needed units.
326
327                Inlined_Bodies.Increment_Last;
328                Inlined_Bodies.Table (Inlined_Bodies.Last) := E;
329
330             elsif Is_Generic_Instance (Pack) then
331                null;
332
333             elsif not Is_Inlined (Pack)
334               and then not Has_Completion (E)
335               and then not Scope_In_Main_Unit (Pack)
336             then
337                Set_Is_Inlined (Pack);
338                Inlined_Bodies.Increment_Last;
339                Inlined_Bodies.Table (Inlined_Bodies.Last) := Pack;
340             end if;
341          end if;
342       end if;
343    end Add_Inlined_Body;
344
345    ----------------------------
346    -- Add_Inlined_Subprogram --
347    ----------------------------
348
349    procedure Add_Inlined_Subprogram (Index : Subp_Index) is
350       E    : constant Entity_Id := Inlined.Table (Index).Name;
351       Succ : Succ_Index;
352       Subp : Subp_Index;
353
354    begin
355       --  Insert the current subprogram in the list of inlined subprograms
356
357       if not Scope_In_Main_Unit (E)
358         and then Is_Inlined (E)
359         and then not Is_Nested (E)
360         and then not Has_Initialized_Type (E)
361       then
362          if No (Last_Inlined) then
363             Set_First_Inlined_Subprogram (Cunit (Main_Unit), E);
364          else
365             Set_Next_Inlined_Subprogram (Last_Inlined, E);
366          end if;
367
368          Last_Inlined := E;
369       end if;
370
371       Inlined.Table (Index).Listed := True;
372       Succ := Inlined.Table (Index).First_Succ;
373
374       while Succ /= No_Succ loop
375          Subp := Successors.Table (Succ).Subp;
376          Inlined.Table (Subp).Count := Inlined.Table (Subp).Count - 1;
377
378          if Inlined.Table (Subp).Count = 0 then
379             Add_Inlined_Subprogram (Subp);
380          end if;
381
382          Succ := Successors.Table (Succ).Next;
383       end loop;
384    end Add_Inlined_Subprogram;
385
386    ------------------------
387    -- Add_Scope_To_Clean --
388    ------------------------
389
390    procedure Add_Scope_To_Clean (Inst : Entity_Id) is
391       Elmt : Elmt_Id;
392       Scop : Entity_Id := Enclosing_Dynamic_Scope (Inst);
393
394    begin
395       --  If the instance appears in a library-level package declaration,
396       --  all finalization is global, and nothing needs doing here.
397
398       if Scop = Standard_Standard then
399          return;
400       end if;
401
402       Elmt := First_Elmt (To_Clean);
403
404       while Present (Elmt) loop
405
406          if Node (Elmt) = Scop then
407             return;
408          end if;
409
410          Elmt := Next_Elmt (Elmt);
411       end loop;
412
413       Append_Elmt (Scop, To_Clean);
414    end Add_Scope_To_Clean;
415
416    --------------
417    -- Add_Subp --
418    --------------
419
420    function Add_Subp (E : Entity_Id) return Subp_Index is
421       Index : Subp_Index := Subp_Index (E) mod Num_Hash_Headers;
422       J     : Subp_Index;
423
424       procedure New_Entry;
425       --  Initialize entry in Inlined table.
426
427       procedure New_Entry is
428       begin
429          Inlined.Increment_Last;
430          Inlined.Table (Inlined.Last).Name        := E;
431          Inlined.Table (Inlined.Last).First_Succ  := No_Succ;
432          Inlined.Table (Inlined.Last).Count       := 0;
433          Inlined.Table (Inlined.Last).Listed      := False;
434          Inlined.Table (Inlined.Last).Main_Call   := False;
435          Inlined.Table (Inlined.Last).Next        := No_Subp;
436          Inlined.Table (Inlined.Last).Next_Nopred := No_Subp;
437       end New_Entry;
438
439    --  Start of processing for Add_Subp
440
441    begin
442       if Hash_Headers (Index) = No_Subp then
443          New_Entry;
444          Hash_Headers (Index) := Inlined.Last;
445          return Inlined.Last;
446
447       else
448          J := Hash_Headers (Index);
449
450          while J /= No_Subp loop
451
452             if Inlined.Table (J).Name = E then
453                return J;
454             else
455                Index := J;
456                J := Inlined.Table (J).Next;
457             end if;
458          end loop;
459
460          --  On exit, subprogram was not found. Enter in table. Index is
461          --  the current last entry on the hash chain.
462
463          New_Entry;
464          Inlined.Table (Index).Next := Inlined.Last;
465          return Inlined.Last;
466       end if;
467    end Add_Subp;
468
469    ----------------------------
470    -- Analyze_Inlined_Bodies --
471    ----------------------------
472
473    procedure Analyze_Inlined_Bodies is
474       Comp_Unit : Node_Id;
475       J         : Int;
476       Pack      : Entity_Id;
477       S         : Succ_Index;
478
479    begin
480       Analyzing_Inlined_Bodies := False;
481
482       if Serious_Errors_Detected = 0 then
483          New_Scope (Standard_Standard);
484
485          J := 0;
486          while J <= Inlined_Bodies.Last
487            and then Serious_Errors_Detected = 0
488          loop
489             Pack := Inlined_Bodies.Table (J);
490
491             while Present (Pack)
492               and then Scope (Pack) /= Standard_Standard
493               and then not Is_Child_Unit (Pack)
494             loop
495                Pack := Scope (Pack);
496             end loop;
497
498             Comp_Unit := Parent (Pack);
499
500             while Present (Comp_Unit)
501               and then Nkind (Comp_Unit) /= N_Compilation_Unit
502             loop
503                Comp_Unit := Parent (Comp_Unit);
504             end loop;
505
506             --  Load the body, unless it the main unit, or is an instance
507             --  whose body has already been analyzed.
508
509             if Present (Comp_Unit)
510               and then Comp_Unit /= Cunit (Main_Unit)
511               and then Body_Required (Comp_Unit)
512               and then (Nkind (Unit (Comp_Unit)) /= N_Package_Declaration
513                          or else No (Corresponding_Body (Unit (Comp_Unit))))
514             then
515                declare
516                   Bname : constant Unit_Name_Type :=
517                             Get_Body_Name (Get_Unit_Name (Unit (Comp_Unit)));
518
519                   OK : Boolean;
520
521                begin
522                   if not Is_Loaded (Bname) then
523                      Load_Needed_Body (Comp_Unit, OK);
524
525                      if not OK then
526                         Error_Msg_Unit_1 := Bname;
527                         Error_Msg_N
528                           ("one or more inlined subprograms accessed in $!",
529                            Comp_Unit);
530                         Error_Msg_Name_1 :=
531                           Get_File_Name (Bname, Subunit => False);
532                         Error_Msg_N ("\but file{ was not found!", Comp_Unit);
533                         raise Unrecoverable_Error;
534                      end if;
535                   end if;
536                end;
537             end if;
538
539             J := J + 1;
540          end loop;
541
542          --  The analysis of required bodies may have produced additional
543          --  generic instantiations. To obtain further inlining, we perform
544          --  another round of generic body instantiations. Establishing a
545          --  fully recursive loop between inlining and generic instantiations
546          --  is unlikely to yield more than this one additional pass.
547
548          Instantiate_Bodies;
549
550          --  The list of inlined subprograms is an overestimate, because
551          --  it includes inlined functions called from functions that are
552          --  compiled as part of an inlined package, but are not themselves
553          --  called. An accurate computation of just those subprograms that
554          --  are needed requires that we perform a transitive closure over
555          --  the call graph, starting from calls in the main program. Here
556          --  we do one step of the inverse transitive closure, and reset
557          --  the Is_Called flag on subprograms all of whose callers are not.
558
559          for Index in Inlined.First .. Inlined.Last loop
560             S := Inlined.Table (Index).First_Succ;
561
562             if S /= No_Succ
563               and then not Inlined.Table (Index).Main_Call
564             then
565                Set_Is_Called (Inlined.Table (Index).Name, False);
566
567                while S /= No_Succ loop
568
569                   if Is_Called
570                     (Inlined.Table (Successors.Table (S).Subp).Name)
571                    or else Inlined.Table (Successors.Table (S).Subp).Main_Call
572                   then
573                      Set_Is_Called (Inlined.Table (Index).Name);
574                      exit;
575                   end if;
576
577                   S := Successors.Table (S).Next;
578                end loop;
579             end if;
580          end loop;
581
582          --  Now that the units are compiled, chain the subprograms within
583          --  that are called and inlined. Produce list of inlined subprograms
584          --  sorted in  topological order. Start with all subprograms that
585          --  have no prerequisites, i.e. inlined subprograms that do not call
586          --  other inlined subprograms.
587
588          for Index in Inlined.First .. Inlined.Last loop
589
590             if Is_Called (Inlined.Table (Index).Name)
591               and then Inlined.Table (Index).Count = 0
592               and then not Inlined.Table (Index).Listed
593             then
594                Add_Inlined_Subprogram (Index);
595             end if;
596          end loop;
597
598          --  Because Add_Inlined_Subprogram treats recursively nodes that have
599          --  no prerequisites left, at the end of the loop all subprograms
600          --  must have been listed. If there are any unlisted subprograms
601          --  left, there must be some recursive chains that cannot be inlined.
602
603          for Index in Inlined.First .. Inlined.Last loop
604             if Is_Called (Inlined.Table (Index).Name)
605               and then Inlined.Table (Index).Count /= 0
606               and then not Is_Predefined_File_Name
607                 (Unit_File_Name
608                   (Get_Source_Unit (Inlined.Table (Index).Name)))
609             then
610                Error_Msg_N
611                  ("& cannot be inlined?", Inlined.Table (Index).Name);
612                --  A warning on the first one might be sufficient.
613             end if;
614          end loop;
615
616          Pop_Scope;
617       end if;
618    end Analyze_Inlined_Bodies;
619
620    --------------------------------
621    --  Check_Body_For_Inlining --
622    --------------------------------
623
624    procedure Check_Body_For_Inlining (N : Node_Id; P : Entity_Id) is
625       Bname : Unit_Name_Type;
626       E     : Entity_Id;
627       OK    : Boolean;
628
629    begin
630       if Is_Compilation_Unit (P)
631         and then not Is_Generic_Instance (P)
632       then
633          Bname := Get_Body_Name (Get_Unit_Name (Unit (N)));
634          E := First_Entity (P);
635
636          while Present (E) loop
637             if Has_Pragma_Inline (E) then
638                if not Is_Loaded (Bname) then
639                   Load_Needed_Body (N, OK);
640
641                   if not OK
642                     and then Ineffective_Inline_Warnings
643                   then
644                      Error_Msg_Unit_1 := Bname;
645                      Error_Msg_N
646                        ("unable to inline subprograms defined in $?", P);
647                      Error_Msg_N ("\body not found?", P);
648                      return;
649                   end if;
650                end if;
651
652                return;
653             end if;
654
655             Next_Entity (E);
656          end loop;
657       end if;
658    end Check_Body_For_Inlining;
659
660    --------------------
661    -- Cleanup_Scopes --
662    --------------------
663
664    procedure Cleanup_Scopes is
665       Elmt : Elmt_Id;
666       Decl : Node_Id;
667       Scop : Entity_Id;
668
669    begin
670       Elmt := First_Elmt (To_Clean);
671
672       while Present (Elmt) loop
673          Scop := Node (Elmt);
674
675          if Ekind (Scop) = E_Entry then
676             Scop := Protected_Body_Subprogram (Scop);
677          end if;
678
679          if Ekind (Scop) = E_Block then
680             Decl := Parent (Block_Node (Scop));
681
682          else
683             Decl := Unit_Declaration_Node (Scop);
684
685             if Nkind (Decl) = N_Subprogram_Declaration
686               or else Nkind (Decl) = N_Task_Type_Declaration
687               or else Nkind (Decl) = N_Subprogram_Body_Stub
688             then
689                Decl := Unit_Declaration_Node (Corresponding_Body (Decl));
690             end if;
691          end if;
692
693          New_Scope (Scop);
694          Expand_Cleanup_Actions (Decl);
695          End_Scope;
696
697          Elmt := Next_Elmt (Elmt);
698       end loop;
699    end Cleanup_Scopes;
700
701    --------------------------
702    -- Has_Initialized_Type --
703    --------------------------
704
705    function Has_Initialized_Type (E : Entity_Id) return Boolean is
706       E_Body : constant Node_Id := Get_Subprogram_Body (E);
707       Decl   : Node_Id;
708
709    begin
710       if No (E_Body) then        --  imported subprogram
711          return False;
712
713       else
714          Decl := First (Declarations (E_Body));
715
716          while Present (Decl) loop
717
718             if Nkind (Decl) = N_Full_Type_Declaration
719               and then Present (Init_Proc (Defining_Identifier (Decl)))
720             then
721                return True;
722             end if;
723
724             Next (Decl);
725          end loop;
726       end if;
727
728       return False;
729    end Has_Initialized_Type;
730
731    ----------------
732    -- Initialize --
733    ----------------
734
735    procedure Initialize is
736    begin
737       Analyzing_Inlined_Bodies := False;
738       Pending_Descriptor.Init;
739       Pending_Instantiations.Init;
740       Inlined_Bodies.Init;
741       Successors.Init;
742       Inlined.Init;
743
744       for J in Hash_Headers'Range loop
745          Hash_Headers (J) := No_Subp;
746       end loop;
747    end Initialize;
748
749    ------------------------
750    -- Instantiate_Bodies --
751    ------------------------
752
753    --  Generic bodies contain all the non-local references, so an
754    --  instantiation does not need any more context than Standard
755    --  itself, even if the instantiation appears in an inner scope.
756    --  Generic associations have verified that the contract model is
757    --  satisfied, so that any error that may occur in the analysis of
758    --  the body is an internal error.
759
760    procedure Instantiate_Bodies is
761       J    : Int;
762       Info : Pending_Body_Info;
763
764    begin
765       if Serious_Errors_Detected = 0 then
766
767          Expander_Active :=  (Operating_Mode = Opt.Generate_Code);
768          New_Scope (Standard_Standard);
769          To_Clean := New_Elmt_List;
770
771          if Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
772             Start_Generic;
773          end if;
774
775          --  A body instantiation may generate additional instantiations, so
776          --  the following loop must scan to the end of a possibly expanding
777          --  set (that's why we can't simply use a FOR loop here).
778
779          J := 0;
780
781          while J <= Pending_Instantiations.Last
782            and then Serious_Errors_Detected = 0
783          loop
784
785             Info := Pending_Instantiations.Table (J);
786
787             --  If the  instantiation node is absent, it has been removed
788             --  as part of unreachable code.
789
790             if No (Info.Inst_Node) then
791                null;
792
793             elsif Nkind (Info. Act_Decl) = N_Package_Declaration then
794                Instantiate_Package_Body (Info);
795                Add_Scope_To_Clean (Defining_Entity (Info.Act_Decl));
796
797             else
798                Instantiate_Subprogram_Body (Info);
799             end if;
800
801             J := J + 1;
802          end loop;
803
804          --  Reset the table of instantiations. Additional instantiations
805          --  may be added through inlining, when additional bodies are
806          --  analyzed.
807
808          Pending_Instantiations.Init;
809
810          --  We can now complete the cleanup actions of scopes that contain
811          --  pending instantiations (skipped for generic units, since we
812          --  never need any cleanups in generic units).
813          --  pending instantiations.
814
815          if Expander_Active
816            and then not Is_Generic_Unit (Main_Unit_Entity)
817          then
818             Cleanup_Scopes;
819
820             --  Also generate subprogram descriptors that were delayed
821
822             for J in Pending_Descriptor.First .. Pending_Descriptor.Last loop
823                declare
824                   Ent : constant Entity_Id := Pending_Descriptor.Table (J);
825
826                begin
827                   if Is_Subprogram (Ent) then
828                      Generate_Subprogram_Descriptor_For_Subprogram
829                        (Get_Subprogram_Body (Ent), Ent);
830
831                   elsif Ekind (Ent) = E_Package then
832                      Generate_Subprogram_Descriptor_For_Package
833                        (Parent (Declaration_Node (Ent)), Ent);
834
835                   elsif Ekind (Ent) = E_Package_Body then
836                      Generate_Subprogram_Descriptor_For_Package
837                        (Declaration_Node (Ent), Ent);
838                   end if;
839                end;
840             end loop;
841
842          elsif Is_Generic_Unit (Cunit_Entity (Main_Unit)) then
843             End_Generic;
844          end if;
845
846          Pop_Scope;
847       end if;
848    end Instantiate_Bodies;
849
850    ---------------
851    -- Is_Nested --
852    ---------------
853
854    function Is_Nested (E : Entity_Id) return Boolean is
855       Scop : Entity_Id := Scope (E);
856
857    begin
858       while Scop /= Standard_Standard loop
859          if Ekind (Scop) in Subprogram_Kind then
860             return True;
861
862          elsif Ekind (Scop) = E_Task_Type
863            or else Ekind (Scop) = E_Entry
864            or else Ekind (Scop) = E_Entry_Family then
865             return True;
866          end if;
867
868          Scop := Scope (Scop);
869       end loop;
870
871       return False;
872    end Is_Nested;
873
874    ----------
875    -- Lock --
876    ----------
877
878    procedure Lock is
879    begin
880       Pending_Instantiations.Locked := True;
881       Inlined_Bodies.Locked := True;
882       Successors.Locked := True;
883       Inlined.Locked := True;
884       Pending_Instantiations.Release;
885       Inlined_Bodies.Release;
886       Successors.Release;
887       Inlined.Release;
888    end Lock;
889
890    --------------------------
891    -- Remove_Dead_Instance --
892    --------------------------
893
894    procedure Remove_Dead_Instance (N : Node_Id) is
895       J    : Int;
896
897    begin
898       J := 0;
899
900       while J <= Pending_Instantiations.Last loop
901
902          if Pending_Instantiations.Table (J).Inst_Node = N then
903             Pending_Instantiations.Table (J).Inst_Node := Empty;
904             return;
905          end if;
906
907          J := J + 1;
908       end loop;
909    end Remove_Dead_Instance;
910
911    ------------------------
912    -- Scope_In_Main_Unit --
913    ------------------------
914
915    function Scope_In_Main_Unit (Scop : Entity_Id) return Boolean is
916       Comp : Node_Id;
917       S    : Entity_Id := Scop;
918       Ent  : Entity_Id := Cunit_Entity (Main_Unit);
919
920    begin
921       --  The scope may be within the main unit, or it may be an ancestor
922       --  of the main unit, if the main unit is a child unit. In both cases
923       --  it makes no sense to process the body before the main unit. In
924       --  the second case, this may lead to circularities if a parent body
925       --  depends on a child spec, and we are analyzing the child.
926
927       while Scope (S) /= Standard_Standard
928         and then not Is_Child_Unit (S)
929       loop
930          S := Scope (S);
931       end loop;
932
933       Comp := Parent (S);
934
935       while Present (Comp)
936         and then Nkind (Comp) /= N_Compilation_Unit
937       loop
938          Comp := Parent (Comp);
939       end loop;
940
941       if Is_Child_Unit (Ent) then
942
943          while Present (Ent)
944            and then Is_Child_Unit (Ent)
945          loop
946             if Scope (Ent) = S then
947                return True;
948             end if;
949
950             Ent := Scope (Ent);
951          end loop;
952       end if;
953
954       return
955         Comp = Cunit (Main_Unit)
956           or else Comp = Library_Unit (Cunit (Main_Unit));
957    end Scope_In_Main_Unit;
958
959 end Inline;