OSDN Git Service

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