OSDN Git Service

* function.h (incomming_args): Break out of struct function.
[pf3gnuchains/gcc-fork.git] / gcc / ada / exp_ch9.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT COMPILER COMPONENTS                         --
4 --                                                                          --
5 --                              E X P _ C H 9                               --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --          Copyright (C) 1992-2008, Free Software Foundation, Inc.         --
10 --                                                                          --
11 -- GNAT is free software;  you can  redistribute it  and/or modify it under --
12 -- terms of the  GNU General Public License as published  by the Free Soft- --
13 -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14 -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
17 -- for  more details.  You should have  received  a copy of the GNU General --
18 -- Public License  distributed with GNAT; see file COPYING3.  If not, go to --
19 -- http://www.gnu.org/licenses for a complete copy of the license.          --
20 --                                                                          --
21 -- GNAT was originally developed  by the GNAT team at  New York University. --
22 -- Extensive contributions were provided by Ada Core Technologies Inc.      --
23 --                                                                          --
24 ------------------------------------------------------------------------------
25
26 with Atree;    use Atree;
27 with Checks;   use Checks;
28 with Einfo;    use Einfo;
29 with Elists;   use Elists;
30 with Errout;   use Errout;
31 with Exp_Ch3;  use Exp_Ch3;
32 with Exp_Ch11; use Exp_Ch11;
33 with Exp_Ch6;  use Exp_Ch6;
34 with Exp_Dbug; use Exp_Dbug;
35 with Exp_Sel;  use Exp_Sel;
36 with Exp_Smem; use Exp_Smem;
37 with Exp_Tss;  use Exp_Tss;
38 with Exp_Util; use Exp_Util;
39 with Freeze;   use Freeze;
40 with Hostparm;
41 with Itypes;   use Itypes;
42 with Namet;    use Namet;
43 with Nlists;   use Nlists;
44 with Nmake;    use Nmake;
45 with Opt;      use Opt;
46 with Restrict; use Restrict;
47 with Rident;   use Rident;
48 with Rtsfind;  use Rtsfind;
49 with Sem;      use Sem;
50 with Sem_Ch6;  use Sem_Ch6;
51 with Sem_Ch8;  use Sem_Ch8;
52 with Sem_Ch11; use Sem_Ch11;
53 with Sem_Elab; use Sem_Elab;
54 with Sem_Res;  use Sem_Res;
55 with Sem_Util; use Sem_Util;
56 with Sinfo;    use Sinfo;
57 with Snames;   use Snames;
58 with Stand;    use Stand;
59 with Targparm; use Targparm;
60 with Tbuild;   use Tbuild;
61 with Uintp;    use Uintp;
62
63 package body Exp_Ch9 is
64
65    --  The following constant establishes the upper bound for the index of
66    --  an entry family. It is used to limit the allocated size of protected
67    --  types with defaulted discriminant of an integer type, when the bound
68    --  of some entry family depends on a discriminant. The limitation to
69    --  entry families of 128K should be reasonable in all cases, and is a
70    --  documented implementation restriction. It will be lifted when protected
71    --  entry families are re-implemented as a single ordered queue.
72
73    Entry_Family_Bound : constant Int := 2**16;
74
75    -----------------------
76    -- Local Subprograms --
77    -----------------------
78
79    function Actual_Index_Expression
80      (Sloc  : Source_Ptr;
81       Ent   : Entity_Id;
82       Index : Node_Id;
83       Tsk   : Entity_Id) return Node_Id;
84    --  Compute the index position for an entry call. Tsk is the target task. If
85    --  the bounds of some entry family depend on discriminants, the expression
86    --  computed by this function uses the discriminants of the target task.
87
88    procedure Add_Object_Pointer
89      (Loc      : Source_Ptr;
90       Conc_Typ : Entity_Id;
91       Decls    : List_Id);
92    --  Prepend an object pointer declaration to the declaration list Decls.
93    --  This object pointer is initialized to a type conversion of the System.
94    --  Address pointer passed to entry barrier functions and entry body
95    --  procedures.
96
97    procedure Add_Formal_Renamings
98      (Spec  : Node_Id;
99       Decls : List_Id;
100       Ent   : Entity_Id;
101       Loc   : Source_Ptr);
102    --  Create renaming declarations for the formals, inside the procedure that
103    --  implements an entry body. The renamings make the original names of the
104    --  formals accessible to gdb, and serve no other purpose.
105    --    Spec is the specification of the procedure being built.
106    --    Decls is the list of declarations to be enhanced.
107    --    Ent is the entity for the original entry body.
108
109    function Build_Accept_Body (Astat : Node_Id) return Node_Id;
110    --  Transform accept statement into a block with added exception handler.
111    --  Used both for simple accept statements and for accept alternatives in
112    --  select statements. Astat is the accept statement.
113
114    function Build_Barrier_Function
115      (N   : Node_Id;
116       Ent : Entity_Id;
117       Pid : Node_Id) return Node_Id;
118    --  Build the function body returning the value of the barrier expression
119    --  for the specified entry body.
120
121    function Build_Barrier_Function_Specification
122      (Loc    : Source_Ptr;
123       Def_Id : Entity_Id) return Node_Id;
124    --  Build a specification for a function implementing the protected entry
125    --  barrier of the specified entry body.
126
127    function Build_Entry_Count_Expression
128      (Concurrent_Type : Node_Id;
129       Component_List  : List_Id;
130       Loc             : Source_Ptr) return Node_Id;
131    --  Compute number of entries for concurrent object. This is a count of
132    --  simple entries, followed by an expression that computes the length
133    --  of the range of each entry family. A single array with that size is
134    --  allocated for each concurrent object of the type.
135
136    function Build_Parameter_Block
137      (Loc     : Source_Ptr;
138       Actuals : List_Id;
139       Formals : List_Id;
140       Decls   : List_Id) return Entity_Id;
141    --  Generate an access type for each actual parameter in the list Actuals.
142    --  Create an encapsulating record that contains all the actuals and return
143    --  its type. Generate:
144    --    type Ann1 is access all <actual1-type>
145    --    ...
146    --    type AnnN is access all <actualN-type>
147    --    type Pnn is record
148    --       <formal1> : Ann1;
149    --       ...
150    --       <formalN> : AnnN;
151    --    end record;
152
153    function Build_Wrapper_Body
154      (Loc      : Source_Ptr;
155       Proc_Nam : Entity_Id;
156       Obj_Typ  : Entity_Id;
157       Formals  : List_Id) return Node_Id;
158    --  Ada 2005 (AI-345): Build the body that wraps a primitive operation
159    --  associated with a protected or task type. This is required to implement
160    --  dispatching calls through interfaces. Proc_Nam is the entry name to be
161    --  wrapped, Obj_Typ is the type of the newly added formal parameter to
162    --  handle object notation, Formals are the original entry formals that will
163    --  be explicitly replicated.
164
165    function Build_Wrapper_Spec
166      (Loc      : Source_Ptr;
167       Proc_Nam : Entity_Id;
168       Obj_Typ  : Entity_Id;
169       Formals  : List_Id) return Node_Id;
170    --  Ada 2005 (AI-345): Build the specification of a primitive operation
171    --  associated with a protected or task type. This is required implement
172    --  dispatching calls through interfaces. Proc_Nam is the entry name to be
173    --  wrapped, Obj_Typ is the type of the newly added formal parameter to
174    --  handle object notation, Formals are the original entry formals that will
175    --  be explicitly replicated.
176
177    function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id;
178    --  Build the function that translates the entry index in the call
179    --  (which depends on the size of entry families) into an index into the
180    --  Entry_Bodies_Array, to determine the body and barrier function used
181    --  in a protected entry call. A pointer to this function appears in every
182    --  protected object.
183
184    function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id;
185    --  Build subprogram declaration for previous one
186
187    function Build_Protected_Entry
188      (N   : Node_Id;
189       Ent : Entity_Id;
190       Pid : Node_Id) return Node_Id;
191    --  Build the procedure implementing the statement sequence of the specified
192    --  entry body.
193
194    function Build_Protected_Entry_Specification
195      (Loc    : Source_Ptr;
196       Def_Id : Entity_Id;
197       Ent_Id : Entity_Id) return Node_Id;
198    --  Build a specification for the procedure implementing the statemens of
199    --  the specified entry body. Add attributes associating it with the entry
200    --  defining identifier Ent_Id.
201
202    function Build_Protected_Spec
203      (N           : Node_Id;
204       Obj_Type    : Entity_Id;
205       Ident       : Entity_Id;
206       Unprotected : Boolean := False) return List_Id;
207    --  Utility shared by Build_Protected_Sub_Spec and Expand_Access_Protected_
208    --  Subprogram_Type. Builds signature of protected subprogram, adding the
209    --  formal that corresponds to the object itself. For an access to protected
210    --  subprogram, there is no object type to specify, so the parameter has
211    --  type Address and mode In. An indirect call through such a pointer will
212    --  convert the address to a reference to the actual object. The object is
213    --  a limited record and therefore a by_reference type.
214
215    function Build_Protected_Subprogram_Body
216      (N         : Node_Id;
217       Pid       : Node_Id;
218       N_Op_Spec : Node_Id) return Node_Id;
219    --  This function is used to construct the protected version of a protected
220    --  subprogram. Its statement sequence first defers abort, then locks
221    --  the associated protected object, and then enters a block that contains
222    --  a call to the unprotected version of the subprogram (for details, see
223    --  Build_Unprotected_Subprogram_Body). This block statement requires
224    --  a cleanup handler that unlocks the object in all cases.
225    --  (see Exp_Ch7.Expand_Cleanup_Actions).
226
227    function Build_Selected_Name
228      (Prefix      : Entity_Id;
229       Selector    : Entity_Id;
230       Append_Char : Character := ' ') return Name_Id;
231    --  Build a name in the form of Prefix__Selector, with an optional
232    --  character appended. This is used for internal subprograms generated
233    --  for operations of protected types, including barrier functions.
234    --  For the subprograms generated for entry bodies and entry barriers,
235    --  the generated name includes a sequence number that makes names
236    --  unique in the presence of entry overloading. This is necessary
237    --  because entry body procedures and barrier functions all have the
238    --  same signature.
239
240    procedure Build_Simple_Entry_Call
241      (N       : Node_Id;
242       Concval : Node_Id;
243       Ename   : Node_Id;
244       Index   : Node_Id);
245    --  Some comments here would be useful ???
246
247    function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id;
248    --  This routine constructs a specification for the procedure that we will
249    --  build for the task body for task type T. The spec has the form:
250    --
251    --    procedure tnameB (_Task : access tnameV);
252    --
253    --  where name is the character name taken from the task type entity that
254    --  is passed as the argument to the procedure, and tnameV is the task
255    --  value type that is associated with the task type.
256
257    function Build_Unprotected_Subprogram_Body
258      (N   : Node_Id;
259       Pid : Node_Id) return Node_Id;
260    --  This routine constructs the unprotected version of a protected
261    --  subprogram body, which is contains all of the code in the
262    --  original, unexpanded body. This is the version of the protected
263    --  subprogram that is called from all protected operations on the same
264    --  object, including the protected version of the same subprogram.
265
266    procedure Collect_Entry_Families
267      (Loc          : Source_Ptr;
268       Cdecls       : List_Id;
269       Current_Node : in out Node_Id;
270       Conctyp      : Entity_Id);
271    --  For each entry family in a concurrent type, create an anonymous array
272    --  type of the right size, and add a component to the corresponding_record.
273
274    function Concurrent_Object
275      (Spec_Id  : Entity_Id;
276       Conc_Typ : Entity_Id) return Entity_Id;
277    --  Given a subprogram entity Spec_Id and concurrent type Conc_Typ, return
278    --  the entity associated with the concurrent object in the Protected_Body_
279    --  Subprogram or the Task_Body_Procedure of Spec_Id. The returned entity
280    --  denotes formal parameter _O, _object or _task.
281
282    function Copy_Result_Type (Res : Node_Id) return Node_Id;
283    --  Copy the result type of a function specification, when building the
284    --  internal operation corresponding to a protected function, or when
285    --  expanding an access to protected function. If the result is an anonymous
286    --  access to subprogram itself, we need to create a new signature with the
287    --  same parameter names and the same resolved types, but with new entities
288    --  for the formals.
289
290    procedure Debug_Private_Data_Declarations (Decls : List_Id);
291    --  Decls is a list which may contain the declarations created by Install_
292    --  Private_Data_Declarations. All generated entities are marked as needing
293    --  debug info and debug nodes are manually generation where necessary. This
294    --  step of the expansion must to be done after private data has been moved
295    --  to its final resting scope to ensure proper visibility of debug objects.
296
297    function Family_Offset
298      (Loc  : Source_Ptr;
299       Hi   : Node_Id;
300       Lo   : Node_Id;
301       Ttyp : Entity_Id;
302       Cap  : Boolean) return Node_Id;
303    --  Compute (Hi - Lo) for two entry family indices. Hi is the index in
304    --  an accept statement, or the upper bound in the discrete subtype of
305    --  an entry declaration. Lo is the corresponding lower bound. Ttyp is
306    --  the concurrent type of the entry. If Cap is true, the result is
307    --  capped according to Entry_Family_Bound.
308
309    function Family_Size
310      (Loc  : Source_Ptr;
311       Hi   : Node_Id;
312       Lo   : Node_Id;
313       Ttyp : Entity_Id;
314       Cap  : Boolean) return Node_Id;
315    --  Compute (Hi - Lo) + 1 Max 0, to determine the number of entries in
316    --  a family, and handle properly the superflat case. This is equivalent
317    --  to the use of 'Length on the index type, but must use Family_Offset
318    --  to handle properly the case of bounds that depend on discriminants.
319    --  If Cap is true, the result is capped according to Entry_Family_Bound.
320
321    procedure Extract_Dispatching_Call
322      (N        : Node_Id;
323       Call_Ent : out Entity_Id;
324       Object   : out Entity_Id;
325       Actuals  : out List_Id;
326       Formals  : out List_Id);
327    --  Given a dispatching call, extract the entity of the name of the call,
328    --  its object parameter, its actual parameters and the formal parameters
329    --  of the overridden interface-level version.
330
331    procedure Extract_Entry
332      (N       : Node_Id;
333       Concval : out Node_Id;
334       Ename   : out Node_Id;
335       Index   : out Node_Id);
336    --  Given an entry call, returns the associated concurrent object,
337    --  the entry name, and the entry family index.
338
339    function Find_Task_Or_Protected_Pragma
340      (T : Node_Id;
341       P : Name_Id) return Node_Id;
342    --  Searches the task or protected definition T for the first occurrence
343    --  of the pragma whose name is given by P. The caller has ensured that
344    --  the pragma is present in the task definition. A special case is that
345    --  when P is Name_uPriority, the call will also find Interrupt_Priority.
346    --  ??? Should be implemented with the rep item chain mechanism.
347
348    function Index_Object (Spec_Id : Entity_Id) return Entity_Id;
349    --  Given a subprogram identifier, return the entity which is associated
350    --  with the protection entry index in the Protected_Body_Subprogram or the
351    --  Task_Body_Procedure of Spec_Id. The returned entity denotes formal
352    --  parameter _E.
353
354    function Is_Potentially_Large_Family
355      (Base_Index : Entity_Id;
356       Conctyp    : Entity_Id;
357       Lo         : Node_Id;
358       Hi         : Node_Id) return Boolean;
359
360    function Null_Statements (Stats : List_Id) return Boolean;
361    --  Used to check DO-END sequence. Checks for equivalent of DO NULL; END.
362    --  Allows labels, and pragma Warnings/Unreferenced in the sequence as
363    --  well to still count as null. Returns True for a null sequence. The
364    --  argument is the list of statements from the DO-END sequence.
365
366    function Parameter_Block_Pack
367      (Loc     : Source_Ptr;
368       Blk_Typ : Entity_Id;
369       Actuals : List_Id;
370       Formals : List_Id;
371       Decls   : List_Id;
372       Stmts   : List_Id) return Entity_Id;
373    --  Set the components of the generated parameter block with the values of
374    --  the actual parameters. Generate aliased temporaries to capture the
375    --  values for types that are passed by copy. Otherwise generate a reference
376    --  to the actual's value. Return the address of the aggregate block.
377    --  Generate:
378    --    Jnn1 : alias <formal-type1>;
379    --    Jnn1 := <actual1>;
380    --    ...
381    --    P : Blk_Typ := (
382    --      Jnn1'unchecked_access;
383    --      <actual2>'reference;
384    --      ...);
385
386    function Parameter_Block_Unpack
387      (Loc     : Source_Ptr;
388       P       : Entity_Id;
389       Actuals : List_Id;
390       Formals : List_Id) return List_Id;
391    --  Retrieve the values of the components from the parameter block and
392    --  assign then to the original actual parameters. Generate:
393    --    <actual1> := P.<formal1>;
394    --    ...
395    --    <actualN> := P.<formalN>;
396
397    function Trivial_Accept_OK return Boolean;
398    --  If there is no DO-END block for an accept, or if the DO-END block has
399    --  only null statements, then it is possible to do the Rendezvous with much
400    --  less overhead using the Accept_Trivial routine in the run-time library.
401    --  However, this is not always a valid optimization. Whether it is valid or
402    --  not depends on the Task_Dispatching_Policy. The issue is whether a full
403    --  rescheduling action is required or not. In FIFO_Within_Priorities, such
404    --  a rescheduling is required, so this optimization is not allowed. This
405    --  function returns True if the optimization is permitted.
406
407    -----------------------------
408    -- Actual_Index_Expression --
409    -----------------------------
410
411    function Actual_Index_Expression
412      (Sloc  : Source_Ptr;
413       Ent   : Entity_Id;
414       Index : Node_Id;
415       Tsk   : Entity_Id) return Node_Id
416    is
417       Ttyp : constant Entity_Id := Etype (Tsk);
418       Expr : Node_Id;
419       Num  : Node_Id;
420       Lo   : Node_Id;
421       Hi   : Node_Id;
422       Prev : Entity_Id;
423       S    : Node_Id;
424
425       function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id;
426       --  Compute difference between bounds of entry family
427
428       --------------------------
429       -- Actual_Family_Offset --
430       --------------------------
431
432       function Actual_Family_Offset (Hi, Lo : Node_Id) return Node_Id is
433
434          function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id;
435          --  Replace a reference to a discriminant with a selected component
436          --  denoting the discriminant of the target task.
437
438          -----------------------------
439          -- Actual_Discriminant_Ref --
440          -----------------------------
441
442          function Actual_Discriminant_Ref (Bound : Node_Id) return Node_Id is
443             Typ : constant Entity_Id := Etype (Bound);
444             B   : Node_Id;
445
446          begin
447             if not Is_Entity_Name (Bound)
448               or else Ekind (Entity (Bound)) /= E_Discriminant
449             then
450                if Nkind (Bound) = N_Attribute_Reference then
451                   return Bound;
452                else
453                   B := New_Copy_Tree (Bound);
454                end if;
455
456             else
457                B :=
458                  Make_Selected_Component (Sloc,
459                    Prefix => New_Copy_Tree (Tsk),
460                    Selector_Name => New_Occurrence_Of (Entity (Bound), Sloc));
461
462                Analyze_And_Resolve (B, Typ);
463             end if;
464
465             return
466               Make_Attribute_Reference (Sloc,
467                 Attribute_Name => Name_Pos,
468                 Prefix => New_Occurrence_Of (Etype (Bound), Sloc),
469                 Expressions => New_List (B));
470          end Actual_Discriminant_Ref;
471
472       --  Start of processing for Actual_Family_Offset
473
474       begin
475          return
476            Make_Op_Subtract (Sloc,
477              Left_Opnd  => Actual_Discriminant_Ref (Hi),
478              Right_Opnd => Actual_Discriminant_Ref (Lo));
479       end Actual_Family_Offset;
480
481    --  Start of processing for Actual_Index_Expression
482
483    begin
484       --  The queues of entries and entry families appear in textual order in
485       --  the associated record. The entry index is computed as the sum of the
486       --  number of queues for all entries that precede the designated one, to
487       --  which is added the index expression, if this expression denotes a
488       --  member of a family.
489
490       --  The following is a place holder for the count of simple entries
491
492       Num := Make_Integer_Literal (Sloc, 1);
493
494       --  We construct an expression which is a series of addition operations.
495       --  See comments in Entry_Index_Expression, which is identical in
496       --  structure.
497
498       if Present (Index) then
499          S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
500
501          Expr :=
502            Make_Op_Add (Sloc,
503              Left_Opnd  => Num,
504
505              Right_Opnd =>
506                Actual_Family_Offset (
507                  Make_Attribute_Reference (Sloc,
508                    Attribute_Name => Name_Pos,
509                    Prefix => New_Reference_To (Base_Type (S), Sloc),
510                    Expressions => New_List (Relocate_Node (Index))),
511                  Type_Low_Bound (S)));
512       else
513          Expr := Num;
514       end if;
515
516       --  Now add lengths of preceding entries and entry families
517
518       Prev := First_Entity (Ttyp);
519
520       while Chars (Prev) /= Chars (Ent)
521         or else (Ekind (Prev) /= Ekind (Ent))
522         or else not Sem_Ch6.Type_Conformant (Ent, Prev)
523       loop
524          if Ekind (Prev) = E_Entry then
525             Set_Intval (Num, Intval (Num) + 1);
526
527          elsif Ekind (Prev) = E_Entry_Family then
528             S :=
529               Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
530
531             --  The need for the following full view retrieval stems from
532             --  this complex case of nested generics and tasking:
533
534             --     generic
535             --        type Formal_Index is range <>;
536             --        ...
537             --     package Outer is
538             --        type Index is private;
539             --        generic
540             --           ...
541             --        package Inner is
542             --           procedure P;
543             --        end Inner;
544             --     private
545             --        type Index is new Formal_Index range 1 .. 10;
546             --     end Outer;
547
548             --     package body Outer is
549             --        task type T is
550             --           entry Fam (Index);  --  (2)
551             --           entry E;
552             --        end T;
553             --        package body Inner is  --  (3)
554             --           procedure P is
555             --           begin
556             --              T.E;             --  (1)
557             --           end P;
558             --       end Inner;
559             --       ...
560
561             --  We are currently building the index expression for the entry
562             --  call "T.E" (1). Part of the expansion must mention the range
563             --  of the discrete type "Index" (2) of entry family "Fam".
564             --  However only the private view of type "Index" is available to
565             --  the inner generic (3) because there was no prior mention of
566             --  the type inside "Inner". This visibility requirement is
567             --  implicit and cannot be detected during the construction of
568             --  the generic trees and needs special handling.
569
570             if In_Instance_Body
571               and then Is_Private_Type (S)
572               and then Present (Full_View (S))
573             then
574                S := Full_View (S);
575             end if;
576
577             Lo := Type_Low_Bound  (S);
578             Hi := Type_High_Bound (S);
579
580             Expr :=
581               Make_Op_Add (Sloc,
582               Left_Opnd  => Expr,
583               Right_Opnd =>
584                 Make_Op_Add (Sloc,
585                   Left_Opnd =>
586                     Actual_Family_Offset (Hi, Lo),
587                   Right_Opnd =>
588                     Make_Integer_Literal (Sloc, 1)));
589
590          --  Other components are anonymous types to be ignored
591
592          else
593             null;
594          end if;
595
596          Next_Entity (Prev);
597       end loop;
598
599       return Expr;
600    end Actual_Index_Expression;
601
602    --------------------------
603    -- Add_Formal_Renamings --
604    --------------------------
605
606    procedure Add_Formal_Renamings
607      (Spec  : Node_Id;
608       Decls : List_Id;
609       Ent   : Entity_Id;
610       Loc   : Source_Ptr)
611    is
612       Ptr : constant Entity_Id :=
613               Defining_Identifier
614                 (Next (First (Parameter_Specifications (Spec))));
615       --  The name of the formal that holds the address of the parameter block
616       --  for the call.
617
618       Comp   : Entity_Id;
619       Decl   : Node_Id;
620       Formal : Entity_Id;
621       New_F  : Entity_Id;
622
623    begin
624       Formal := First_Formal (Ent);
625       while Present (Formal) loop
626          Comp := Entry_Component (Formal);
627          New_F :=
628            Make_Defining_Identifier (Sloc (Formal),
629              Chars => Chars (Formal));
630          Set_Etype (New_F, Etype (Formal));
631          Set_Scope (New_F, Ent);
632
633          --  Now we set debug info needed on New_F even though it does not
634          --  come from source, so that the debugger will get the right
635          --  information for these generated names.
636
637          Set_Debug_Info_Needed (New_F);
638
639          if Ekind (Formal) = E_In_Parameter then
640             Set_Ekind (New_F, E_Constant);
641          else
642             Set_Ekind (New_F, E_Variable);
643             Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
644          end if;
645
646          Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
647
648          Decl :=
649            Make_Object_Renaming_Declaration (Loc,
650            Defining_Identifier => New_F,
651            Subtype_Mark =>
652              New_Reference_To (Etype (Formal), Loc),
653            Name =>
654              Make_Explicit_Dereference (Loc,
655                Make_Selected_Component (Loc,
656                  Prefix =>
657                    Unchecked_Convert_To (Entry_Parameters_Type (Ent),
658                      Make_Identifier (Loc, Chars (Ptr))),
659                  Selector_Name =>
660                    New_Reference_To (Comp, Loc))));
661
662          Append (Decl, Decls);
663          Set_Renamed_Object (Formal, New_F);
664          Next_Formal (Formal);
665       end loop;
666    end Add_Formal_Renamings;
667
668    ------------------------
669    -- Add_Object_Pointer --
670    ------------------------
671
672    procedure Add_Object_Pointer
673      (Loc      : Source_Ptr;
674       Conc_Typ : Entity_Id;
675       Decls    : List_Id)
676    is
677       Rec_Typ : constant Entity_Id := Corresponding_Record_Type (Conc_Typ);
678       Decl    : Node_Id;
679       Obj_Ptr : Node_Id;
680
681    begin
682       --  Create the renaming declaration for the Protection object of a
683       --  protected type. _Object is used by Complete_Entry_Body.
684       --  ??? An attempt to make this a renaming was unsuccessful.
685
686       --  Build the entity for the access type
687
688       Obj_Ptr :=
689         Make_Defining_Identifier (Loc,
690           New_External_Name (Chars (Rec_Typ), 'P'));
691
692       --  Generate:
693       --    _object : poVP := poVP!O;
694
695       Decl :=
696         Make_Object_Declaration (Loc,
697           Defining_Identifier =>
698             Make_Defining_Identifier (Loc, Name_uObject),
699           Object_Definition =>
700             New_Reference_To (Obj_Ptr, Loc),
701           Expression =>
702             Unchecked_Convert_To (Obj_Ptr,
703               Make_Identifier (Loc, Name_uO)));
704       Set_Debug_Info_Needed (Defining_Identifier (Decl));
705       Prepend_To (Decls, Decl);
706
707       --  Generate:
708       --    type poVP is access poV;
709
710       Decl :=
711         Make_Full_Type_Declaration (Loc,
712           Defining_Identifier =>
713             Obj_Ptr,
714           Type_Definition =>
715             Make_Access_To_Object_Definition (Loc,
716           Subtype_Indication =>
717             New_Reference_To (Rec_Typ, Loc)));
718       Set_Debug_Info_Needed (Defining_Identifier (Decl));
719       Prepend_To (Decls, Decl);
720    end Add_Object_Pointer;
721
722    -----------------------
723    -- Build_Accept_Body --
724    -----------------------
725
726    function Build_Accept_Body (Astat : Node_Id) return  Node_Id is
727       Loc     : constant Source_Ptr := Sloc (Astat);
728       Stats   : constant Node_Id    := Handled_Statement_Sequence (Astat);
729       New_S   : Node_Id;
730       Hand    : Node_Id;
731       Call    : Node_Id;
732       Ohandle : Node_Id;
733
734    begin
735       --  At the end of the statement sequence, Complete_Rendezvous is called.
736       --  A label skipping the Complete_Rendezvous, and all other accept
737       --  processing, has already been added for the expansion of requeue
738       --  statements.
739
740       Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
741       Insert_Before (Last (Statements (Stats)), Call);
742       Analyze (Call);
743
744       --  If exception handlers are present, then append Complete_Rendezvous
745       --  calls to the handlers, and construct the required outer block.
746
747       if Present (Exception_Handlers (Stats)) then
748          Hand := First (Exception_Handlers (Stats));
749
750          while Present (Hand) loop
751             Call := Build_Runtime_Call (Loc, RE_Complete_Rendezvous);
752             Append (Call, Statements (Hand));
753             Analyze (Call);
754             Next (Hand);
755          end loop;
756
757          New_S :=
758            Make_Handled_Sequence_Of_Statements (Loc,
759              Statements => New_List (
760                Make_Block_Statement (Loc,
761                  Handled_Statement_Sequence => Stats)));
762
763       else
764          New_S := Stats;
765       end if;
766
767       --  At this stage we know that the new statement sequence does not
768       --  have an exception handler part, so we supply one to call
769       --  Exceptional_Complete_Rendezvous. This handler is
770
771       --    when all others =>
772       --       Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
773
774       --  We handle Abort_Signal to make sure that we properly catch the abort
775       --  case and wake up the caller.
776
777       Ohandle := Make_Others_Choice (Loc);
778       Set_All_Others (Ohandle);
779
780       Set_Exception_Handlers (New_S,
781         New_List (
782           Make_Implicit_Exception_Handler (Loc,
783             Exception_Choices => New_List (Ohandle),
784
785             Statements =>  New_List (
786               Make_Procedure_Call_Statement (Loc,
787                 Name => New_Reference_To (
788                   RTE (RE_Exceptional_Complete_Rendezvous), Loc),
789                 Parameter_Associations => New_List (
790                   Make_Function_Call (Loc,
791                     Name => New_Reference_To (
792                       RTE (RE_Get_GNAT_Exception), Loc))))))));
793
794       Set_Parent (New_S, Astat); -- temp parent for Analyze call
795       Analyze_Exception_Handlers (Exception_Handlers (New_S));
796       Expand_Exception_Handlers (New_S);
797
798       --  Exceptional_Complete_Rendezvous must be called with abort
799       --  still deferred, which is the case for a "when all others" handler.
800
801       return New_S;
802    end Build_Accept_Body;
803
804    -----------------------------------
805    -- Build_Activation_Chain_Entity --
806    -----------------------------------
807
808    procedure Build_Activation_Chain_Entity (N : Node_Id) is
809       P     : Node_Id;
810       Decls : List_Id;
811       Chain : Entity_Id;
812
813    begin
814       --  Loop to find enclosing construct containing activation chain variable
815
816       P := Parent (N);
817
818       while not Nkind_In (P, N_Subprogram_Body,
819                              N_Package_Declaration,
820                              N_Package_Body,
821                              N_Block_Statement,
822                              N_Task_Body,
823                              N_Extended_Return_Statement)
824       loop
825          P := Parent (P);
826       end loop;
827
828       --  If we are in a package body, the activation chain variable is
829       --  declared in the body, but the Activation_Chain_Entity is attached to
830       --  the spec.
831
832       if Nkind (P) = N_Package_Body then
833          Decls := Declarations (P);
834          P := Unit_Declaration_Node (Corresponding_Spec (P));
835
836       elsif Nkind (P) = N_Package_Declaration then
837          Decls := Visible_Declarations (Specification (P));
838
839       elsif Nkind (P) = N_Extended_Return_Statement then
840          Decls := Return_Object_Declarations (P);
841
842       else
843          Decls := Declarations (P);
844       end if;
845
846       --  If activation chain entity not already declared, declare it
847
848       if Nkind (P) = N_Extended_Return_Statement
849         or else No (Activation_Chain_Entity (P))
850       then
851          Chain := Make_Defining_Identifier (Sloc (N), Name_uChain);
852
853          --  Note: An extended return statement is not really a task activator,
854          --  but it does have an activation chain on which to store the tasks
855          --  temporarily. On successful return, the tasks on this chain are
856          --  moved to the chain passed in by the caller. We do not build an
857          --  Activation_Chain_Entity for an N_Extended_Return_Statement,
858          --  because we do not want to build a call to Activate_Tasks. Task
859          --  activation is the responsibility of the caller.
860
861          if Nkind (P) /= N_Extended_Return_Statement then
862             Set_Activation_Chain_Entity (P, Chain);
863          end if;
864
865          Prepend_To (Decls,
866            Make_Object_Declaration (Sloc (P),
867              Defining_Identifier => Chain,
868              Aliased_Present => True,
869              Object_Definition =>
870                New_Reference_To (RTE (RE_Activation_Chain), Sloc (P))));
871
872          Analyze (First (Decls));
873       end if;
874    end Build_Activation_Chain_Entity;
875
876    ----------------------------
877    -- Build_Barrier_Function --
878    ----------------------------
879
880    function Build_Barrier_Function
881      (N   : Node_Id;
882       Ent : Entity_Id;
883       Pid : Node_Id) return Node_Id
884    is
885       Loc         : constant Source_Ptr := Sloc (N);
886       Func_Id     : constant Entity_Id  := Barrier_Function (Ent);
887       Ent_Formals : constant Node_Id    := Entry_Body_Formal_Part (N);
888       Op_Decls    : constant List_Id    := New_List;
889       Func_Body   : Node_Id;
890
891    begin
892       --  Add a declaration for the Protection object, renaming declarations
893       --  for the discriminals and privals and finally a declaration for the
894       --  entry family index (if applicable).
895
896       Install_Private_Data_Declarations
897         (Loc, Func_Id, Pid, N, Op_Decls, True, Ekind (Ent) = E_Entry_Family);
898
899       --  Note: the condition in the barrier function needs to be properly
900       --  processed for the C/Fortran boolean possibility, but this happens
901       --  automatically since the return statement does this normalization.
902
903       Func_Body :=
904         Make_Subprogram_Body (Loc,
905           Specification =>
906             Build_Barrier_Function_Specification (Loc,
907               Make_Defining_Identifier (Loc, Chars (Func_Id))),
908           Declarations => Op_Decls,
909           Handled_Statement_Sequence =>
910             Make_Handled_Sequence_Of_Statements (Loc,
911               Statements => New_List (
912                 Make_Simple_Return_Statement (Loc,
913                   Expression => Condition (Ent_Formals)))));
914       Set_Is_Entry_Barrier_Function (Func_Body);
915
916       return Func_Body;
917    end Build_Barrier_Function;
918
919    ------------------------------------------
920    -- Build_Barrier_Function_Specification --
921    ------------------------------------------
922
923    function Build_Barrier_Function_Specification
924      (Loc    : Source_Ptr;
925       Def_Id : Entity_Id) return Node_Id
926    is
927    begin
928       Set_Debug_Info_Needed (Def_Id);
929
930       return Make_Function_Specification (Loc,
931         Defining_Unit_Name => Def_Id,
932         Parameter_Specifications => New_List (
933           Make_Parameter_Specification (Loc,
934             Defining_Identifier =>
935               Make_Defining_Identifier (Loc, Name_uO),
936             Parameter_Type =>
937               New_Reference_To (RTE (RE_Address), Loc)),
938
939           Make_Parameter_Specification (Loc,
940             Defining_Identifier =>
941               Make_Defining_Identifier (Loc, Name_uE),
942             Parameter_Type =>
943               New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
944
945         Result_Definition =>
946           New_Reference_To (Standard_Boolean, Loc));
947    end Build_Barrier_Function_Specification;
948
949    --------------------------
950    -- Build_Call_With_Task --
951    --------------------------
952
953    function Build_Call_With_Task
954      (N : Node_Id;
955       E : Entity_Id) return Node_Id
956    is
957       Loc : constant Source_Ptr := Sloc (N);
958    begin
959       return
960         Make_Function_Call (Loc,
961           Name => New_Reference_To (E, Loc),
962           Parameter_Associations => New_List (Concurrent_Ref (N)));
963    end Build_Call_With_Task;
964
965    --------------------------------
966    -- Build_Corresponding_Record --
967    --------------------------------
968
969    function Build_Corresponding_Record
970     (N    : Node_Id;
971      Ctyp : Entity_Id;
972      Loc  : Source_Ptr) return Node_Id
973    is
974       Rec_Ent  : constant Entity_Id :=
975                    Make_Defining_Identifier
976                      (Loc, New_External_Name (Chars (Ctyp), 'V'));
977       Disc     : Entity_Id;
978       Dlist    : List_Id;
979       New_Disc : Entity_Id;
980       Cdecls   : List_Id;
981
982    begin
983       Set_Corresponding_Record_Type     (Ctyp, Rec_Ent);
984       Set_Ekind                         (Rec_Ent, E_Record_Type);
985       Set_Has_Delayed_Freeze            (Rec_Ent, Has_Delayed_Freeze (Ctyp));
986       Set_Is_Concurrent_Record_Type     (Rec_Ent, True);
987       Set_Corresponding_Concurrent_Type (Rec_Ent, Ctyp);
988       Set_Stored_Constraint             (Rec_Ent, No_Elist);
989       Cdecls := New_List;
990
991       --  Use discriminals to create list of discriminants for record, and
992       --  create new discriminals for use in default expressions, etc. It is
993       --  worth noting that a task discriminant gives rise to 5 entities;
994
995       --  a) The original discriminant.
996       --  b) The discriminal for use in the task.
997       --  c) The discriminant of the corresponding record.
998       --  d) The discriminal for the init proc of the corresponding record.
999       --  e) The local variable that renames the discriminant in the procedure
1000       --     for the task body.
1001
1002       --  In fact the discriminals b) are used in the renaming declarations
1003       --  for e). See details in  einfo (Handling of Discriminants).
1004
1005       if Present (Discriminant_Specifications (N)) then
1006          Dlist := New_List;
1007          Disc := First_Discriminant (Ctyp);
1008
1009          while Present (Disc) loop
1010             New_Disc := CR_Discriminant (Disc);
1011
1012             Append_To (Dlist,
1013               Make_Discriminant_Specification (Loc,
1014                 Defining_Identifier => New_Disc,
1015                 Discriminant_Type =>
1016                   New_Occurrence_Of (Etype (Disc), Loc),
1017                 Expression =>
1018                   New_Copy (Discriminant_Default_Value (Disc))));
1019
1020             Next_Discriminant (Disc);
1021          end loop;
1022
1023       else
1024          Dlist := No_List;
1025       end if;
1026
1027       --  Now we can construct the record type declaration. Note that this
1028       --  record is "limited tagged". It is "limited" to reflect the underlying
1029       --  limitedness of the task or protected object that it represents, and
1030       --  ensuring for example that it is properly passed by reference. It is
1031       --  "tagged" to give support to dispatching calls through interfaces (Ada
1032       --  2005: AI-345)
1033
1034       return
1035         Make_Full_Type_Declaration (Loc,
1036           Defining_Identifier => Rec_Ent,
1037           Discriminant_Specifications => Dlist,
1038           Type_Definition =>
1039             Make_Record_Definition (Loc,
1040               Component_List =>
1041                 Make_Component_List (Loc,
1042                   Component_Items => Cdecls),
1043               Tagged_Present  =>
1044                  Ada_Version >= Ada_05 and then Is_Tagged_Type (Ctyp),
1045               Limited_Present => True));
1046    end Build_Corresponding_Record;
1047
1048    ----------------------------------
1049    -- Build_Entry_Count_Expression --
1050    ----------------------------------
1051
1052    function Build_Entry_Count_Expression
1053      (Concurrent_Type : Node_Id;
1054       Component_List  : List_Id;
1055       Loc             : Source_Ptr) return Node_Id
1056    is
1057       Eindx  : Nat;
1058       Ent    : Entity_Id;
1059       Ecount : Node_Id;
1060       Comp   : Node_Id;
1061       Lo     : Node_Id;
1062       Hi     : Node_Id;
1063       Typ    : Entity_Id;
1064       Large  : Boolean;
1065
1066    begin
1067       --  Count number of non-family entries
1068
1069       Eindx := 0;
1070       Ent := First_Entity (Concurrent_Type);
1071       while Present (Ent) loop
1072          if Ekind (Ent) = E_Entry then
1073             Eindx := Eindx + 1;
1074          end if;
1075
1076          Next_Entity (Ent);
1077       end loop;
1078
1079       Ecount := Make_Integer_Literal (Loc, Eindx);
1080
1081       --  Loop through entry families building the addition nodes
1082
1083       Ent := First_Entity (Concurrent_Type);
1084       Comp := First (Component_List);
1085       while Present (Ent) loop
1086          if Ekind (Ent) = E_Entry_Family then
1087             while Chars (Ent) /= Chars (Defining_Identifier (Comp)) loop
1088                Next (Comp);
1089             end loop;
1090
1091             Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1092             Hi := Type_High_Bound (Typ);
1093             Lo := Type_Low_Bound  (Typ);
1094             Large := Is_Potentially_Large_Family
1095                        (Base_Type (Typ), Concurrent_Type, Lo, Hi);
1096             Ecount :=
1097               Make_Op_Add (Loc,
1098                 Left_Opnd  => Ecount,
1099                 Right_Opnd => Family_Size
1100                                 (Loc, Hi, Lo, Concurrent_Type, Large));
1101          end if;
1102
1103          Next_Entity (Ent);
1104       end loop;
1105
1106       return Ecount;
1107    end Build_Entry_Count_Expression;
1108
1109    ---------------------------
1110    -- Build_Parameter_Block --
1111    ---------------------------
1112
1113    function Build_Parameter_Block
1114      (Loc     : Source_Ptr;
1115       Actuals : List_Id;
1116       Formals : List_Id;
1117       Decls   : List_Id) return Entity_Id
1118    is
1119       Actual   : Entity_Id;
1120       Comp_Nam : Node_Id;
1121       Comps    : List_Id;
1122       Formal   : Entity_Id;
1123       Has_Comp : Boolean := False;
1124       Rec_Nam  : Node_Id;
1125
1126    begin
1127       Actual := First (Actuals);
1128       Comps  := New_List;
1129       Formal := Defining_Identifier (First (Formals));
1130
1131       while Present (Actual) loop
1132          if not Is_Controlling_Actual (Actual) then
1133
1134             --  Generate:
1135             --    type Ann is access all <actual-type>
1136
1137             Comp_Nam :=
1138               Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
1139
1140             Append_To (Decls,
1141               Make_Full_Type_Declaration (Loc,
1142                 Defining_Identifier =>
1143                   Comp_Nam,
1144                 Type_Definition =>
1145                   Make_Access_To_Object_Definition (Loc,
1146                     All_Present =>
1147                       True,
1148                     Constant_Present =>
1149                       Ekind (Formal) = E_In_Parameter,
1150                     Subtype_Indication =>
1151                       New_Reference_To (Etype (Actual), Loc))));
1152
1153             --  Generate:
1154             --    Param : Ann;
1155
1156             Append_To (Comps,
1157               Make_Component_Declaration (Loc,
1158                 Defining_Identifier =>
1159                   Make_Defining_Identifier (Loc, Chars (Formal)),
1160                 Component_Definition =>
1161                   Make_Component_Definition (Loc,
1162                     Aliased_Present =>
1163                       False,
1164                     Subtype_Indication =>
1165                       New_Reference_To (Comp_Nam, Loc))));
1166
1167             Has_Comp := True;
1168          end if;
1169
1170          Next_Actual (Actual);
1171          Next_Formal_With_Extras (Formal);
1172       end loop;
1173
1174       Rec_Nam :=
1175         Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
1176
1177       if Has_Comp then
1178
1179          --  Generate:
1180          --    type Pnn is record
1181          --       Param1 : Ann1;
1182          --       ...
1183          --       ParamN : AnnN;
1184
1185          --  where Pnn is a parameter wrapping record, Param1 .. ParamN are
1186          --  the original parameter names and Ann1 .. AnnN are the access to
1187          --  actual types.
1188
1189          Append_To (Decls,
1190            Make_Full_Type_Declaration (Loc,
1191              Defining_Identifier =>
1192                Rec_Nam,
1193              Type_Definition =>
1194                Make_Record_Definition (Loc,
1195                  Component_List =>
1196                    Make_Component_List (Loc, Comps))));
1197       else
1198          --  Generate:
1199          --    type Pnn is null record;
1200
1201          Append_To (Decls,
1202            Make_Full_Type_Declaration (Loc,
1203              Defining_Identifier =>
1204                Rec_Nam,
1205              Type_Definition =>
1206                Make_Record_Definition (Loc,
1207                  Null_Present   => True,
1208                  Component_List => Empty)));
1209       end if;
1210
1211       return Rec_Nam;
1212    end Build_Parameter_Block;
1213
1214    ------------------------
1215    -- Build_Wrapper_Body --
1216    ------------------------
1217
1218    function Build_Wrapper_Body
1219      (Loc      : Source_Ptr;
1220       Proc_Nam : Entity_Id;
1221       Obj_Typ  : Entity_Id;
1222       Formals  : List_Id) return Node_Id
1223    is
1224       Actuals      : List_Id := No_List;
1225       Body_Spec    : Node_Id;
1226       Conv_Id      : Node_Id;
1227       First_Formal : Node_Id;
1228       Formal       : Node_Id;
1229
1230    begin
1231       Body_Spec := Build_Wrapper_Spec (Loc, Proc_Nam, Obj_Typ, Formals);
1232
1233       --  If we did not generate the specification do have nothing else to do
1234
1235       if Body_Spec = Empty then
1236          return Empty;
1237       end if;
1238
1239       --  Map formals to actuals. Use the list built for the wrapper spec,
1240       --  skipping the object notation parameter.
1241
1242       First_Formal := First (Parameter_Specifications (Body_Spec));
1243
1244       Formal := First_Formal;
1245       Next (Formal);
1246
1247       if Present (Formal) then
1248          Actuals := New_List;
1249
1250          while Present (Formal) loop
1251             Append_To (Actuals,
1252               Make_Identifier (Loc, Chars =>
1253                 Chars (Defining_Identifier (Formal))));
1254
1255             Next (Formal);
1256          end loop;
1257       end if;
1258
1259       --  An access-to-variable first parameter will require an explicit
1260       --  dereference in the unchecked conversion. This case occurs when
1261       --  a protected entry wrapper must override an interface-level
1262       --  procedure with interface access as first parameter.
1263
1264       --     SubprgName (O.all).Proc_Nam (Formal_1 .. Formal_N)
1265
1266       if Nkind (Parameter_Type (First_Formal)) = N_Access_Definition then
1267          Conv_Id :=
1268            Make_Explicit_Dereference (Loc,
1269              Prefix =>
1270                Make_Identifier (Loc, Chars => Name_uO));
1271       else
1272          Conv_Id :=
1273            Make_Identifier (Loc, Chars => Name_uO);
1274       end if;
1275
1276       if Ekind (Proc_Nam) = E_Function then
1277          return
1278            Make_Subprogram_Body (Loc,
1279              Specification => Body_Spec,
1280              Declarations  => Empty_List,
1281              Handled_Statement_Sequence =>
1282                Make_Handled_Sequence_Of_Statements (Loc,
1283                  Statements =>
1284                    New_List (
1285                      Make_Simple_Return_Statement (Loc,
1286                         Make_Function_Call (Loc,
1287                           Name =>
1288                             Make_Selected_Component (Loc,
1289                               Prefix =>
1290                                 Unchecked_Convert_To (
1291                                   Corresponding_Concurrent_Type (Obj_Typ),
1292                                   Conv_Id),
1293                               Selector_Name =>
1294                                 New_Reference_To (Proc_Nam, Loc)),
1295                           Parameter_Associations => Actuals)))));
1296       else
1297          return
1298            Make_Subprogram_Body (Loc,
1299              Specification => Body_Spec,
1300              Declarations  => Empty_List,
1301              Handled_Statement_Sequence =>
1302                Make_Handled_Sequence_Of_Statements (Loc,
1303                  Statements =>
1304                    New_List (
1305                      Make_Procedure_Call_Statement (Loc,
1306                        Name =>
1307                          Make_Selected_Component (Loc,
1308                            Prefix =>
1309                              Unchecked_Convert_To (
1310                                Corresponding_Concurrent_Type (Obj_Typ),
1311                                Conv_Id),
1312                            Selector_Name =>
1313                              New_Reference_To (Proc_Nam, Loc)),
1314                        Parameter_Associations => Actuals))));
1315       end if;
1316    end Build_Wrapper_Body;
1317
1318    ------------------------
1319    -- Build_Wrapper_Spec --
1320    ------------------------
1321
1322    function Build_Wrapper_Spec
1323      (Loc      : Source_Ptr;
1324       Proc_Nam : Entity_Id;
1325       Obj_Typ  : Entity_Id;
1326       Formals  : List_Id) return Node_Id
1327    is
1328       New_Name_Id : constant Entity_Id :=
1329                       Make_Defining_Identifier (Loc, Chars (Proc_Nam));
1330
1331       First_Param        : Node_Id := Empty;
1332       Iface              : Entity_Id;
1333       Iface_Elmt         : Elmt_Id := No_Elmt;
1334       New_Formals        : List_Id;
1335       Obj_Param          : Node_Id;
1336       Obj_Param_Typ      : Node_Id;
1337       Iface_Prim_Op      : Entity_Id;
1338       Iface_Prim_Op_Elmt : Elmt_Id;
1339
1340       function Overriding_Possible
1341         (Iface_Prim_Op : Entity_Id;
1342          Proc_Nam      : Entity_Id) return Boolean;
1343       --  Determine whether a primitive operation can be overridden by the
1344       --  wrapper. Iface_Prim_Op is the candidate primitive operation of an
1345       --  abstract interface type, Proc_Nam is the generated entry wrapper.
1346
1347       function Replicate_Entry_Formals
1348         (Loc     : Source_Ptr;
1349          Formals : List_Id) return List_Id;
1350       --  An explicit parameter replication is required due to the
1351       --  Is_Entry_Formal flag being set for all the formals. The explicit
1352       --  replication removes the flag that would otherwise cause a different
1353       --  path of analysis.
1354
1355       -------------------------
1356       -- Overriding_Possible --
1357       -------------------------
1358
1359       function Overriding_Possible
1360         (Iface_Prim_Op : Entity_Id;
1361          Proc_Nam      : Entity_Id) return Boolean
1362       is
1363          Prim_Op_Spec  : constant Node_Id := Parent (Iface_Prim_Op);
1364          Proc_Spec     : constant Node_Id := Parent (Proc_Nam);
1365
1366          Is_Access_To_Variable : Boolean;
1367          Is_Out_Present        : Boolean;
1368
1369          function Type_Conformant_Parameters
1370            (Prim_Op_Param_Specs : List_Id;
1371             Proc_Param_Specs    : List_Id) return Boolean;
1372          --  Determine whether the parameters of the generated entry wrapper
1373          --  and those of a primitive operation are type conformant. During
1374          --  this check, the first parameter of the primitive operation is
1375          --  always skipped.
1376
1377          --------------------------------
1378          -- Type_Conformant_Parameters --
1379          --------------------------------
1380
1381          function Type_Conformant_Parameters
1382            (Prim_Op_Param_Specs : List_Id;
1383             Proc_Param_Specs    : List_Id) return Boolean
1384          is
1385             Prim_Op_Param : Node_Id;
1386             Prim_Op_Typ   : Entity_Id;
1387             Proc_Param    : Node_Id;
1388             Proc_Typ      : Entity_Id;
1389
1390          begin
1391             --  Skip the first parameter of the primitive operation
1392
1393             Prim_Op_Param := Next (First (Prim_Op_Param_Specs));
1394             Proc_Param    := First (Proc_Param_Specs);
1395             while Present (Prim_Op_Param)
1396               and then Present (Proc_Param)
1397             loop
1398                Prim_Op_Typ := Find_Parameter_Type (Prim_Op_Param);
1399                Proc_Typ    := Find_Parameter_Type (Proc_Param);
1400
1401                --  The two parameters must be mode conformant
1402
1403                if not Conforming_Types
1404                         (Prim_Op_Typ, Proc_Typ, Mode_Conformant)
1405                then
1406                   return False;
1407                end if;
1408
1409                Next (Prim_Op_Param);
1410                Next (Proc_Param);
1411             end loop;
1412
1413             --  One of the lists is longer than the other
1414
1415             if Present (Prim_Op_Param) or else Present (Proc_Param) then
1416                return False;
1417             end if;
1418
1419             return True;
1420          end Type_Conformant_Parameters;
1421
1422       --  Start of processing for Overriding_Possible
1423
1424       begin
1425          if Chars (Iface_Prim_Op) /= Chars (Proc_Nam) then
1426             return False;
1427          end if;
1428
1429          --  Special check for protected procedures: If an inherited subprogram
1430          --  is implemented by a protected procedure or an entry, then the
1431          --  first parameter of the inherited subprogram shall be of mode OUT
1432          --  or IN OUT, or an access-to-variable parameter.
1433
1434          if Ekind (Iface_Prim_Op) = E_Procedure then
1435
1436             Is_Out_Present :=
1437               Present (Parameter_Specifications (Prim_Op_Spec))
1438                 and then
1439               Out_Present (First (Parameter_Specifications (Prim_Op_Spec)));
1440
1441             Is_Access_To_Variable :=
1442               Present (Parameter_Specifications (Prim_Op_Spec))
1443                 and then
1444               Nkind (Parameter_Type
1445                       (First
1446                         (Parameter_Specifications (Prim_Op_Spec)))) =
1447                                                           N_Access_Definition;
1448
1449             if not Is_Out_Present
1450               and then not Is_Access_To_Variable
1451             then
1452                return False;
1453             end if;
1454          end if;
1455
1456          return Type_Conformant_Parameters (
1457            Parameter_Specifications (Prim_Op_Spec),
1458            Parameter_Specifications (Proc_Spec));
1459       end Overriding_Possible;
1460
1461       -----------------------------
1462       -- Replicate_Entry_Formals --
1463       -----------------------------
1464
1465       function Replicate_Entry_Formals
1466         (Loc     : Source_Ptr;
1467          Formals : List_Id) return List_Id
1468       is
1469          New_Formals : constant List_Id := New_List;
1470          Formal      : Node_Id;
1471          Param_Type  : Node_Id;
1472
1473       begin
1474          Formal := First (Formals);
1475          while Present (Formal) loop
1476
1477             --  Create an explicit copy of the entry parameter
1478
1479             --  When creating the wrapper subprogram for a primitive operation
1480             --  of a protected interface we must construct an equivalent
1481             --  signature to that of the overriding operation. For regular
1482             --  parameters we can just use the type of the formal, but for
1483             --  access to subprogram parameters we need to reanalyze the
1484             --  parameter type to create local entities for the signature of
1485             --  the subprogram type. Using the entities of the overriding
1486             --  subprogram will result in out-of-scope errors in the back-end.
1487
1488             if Nkind (Parameter_Type (Formal)) = N_Access_Definition then
1489                Param_Type := Copy_Separate_Tree (Parameter_Type (Formal));
1490             else
1491                Param_Type :=
1492                  New_Reference_To (Etype (Parameter_Type (Formal)), Loc);
1493             end if;
1494
1495             Append_To (New_Formals,
1496               Make_Parameter_Specification (Loc,
1497                 Defining_Identifier =>
1498                   Make_Defining_Identifier (Loc,
1499                     Chars          => Chars (Defining_Identifier (Formal))),
1500                     In_Present     => In_Present  (Formal),
1501                     Out_Present    => Out_Present (Formal),
1502                     Parameter_Type => Param_Type));
1503
1504             Next (Formal);
1505          end loop;
1506
1507          return New_Formals;
1508       end Replicate_Entry_Formals;
1509
1510    --  Start of processing for Build_Wrapper_Spec
1511
1512    begin
1513       --  The mode is determined by the first parameter of the interface-level
1514       --  procedure that the current entry is trying to override.
1515
1516       pragma Assert (Is_Non_Empty_List (Abstract_Interface_List (Obj_Typ)));
1517
1518       --  We must examine all the protected operations of the implemented
1519       --  interfaces in order to discover a possible overriding candidate.
1520
1521       Iface := Etype (First (Abstract_Interface_List (Obj_Typ)));
1522
1523       Examine_Parents : loop
1524          if Present (Primitive_Operations (Iface)) then
1525             Iface_Prim_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
1526             while Present (Iface_Prim_Op_Elmt) loop
1527                Iface_Prim_Op := Node (Iface_Prim_Op_Elmt);
1528
1529                if not Is_Predefined_Dispatching_Operation (Iface_Prim_Op) then
1530                   while Present (Alias (Iface_Prim_Op)) loop
1531                      Iface_Prim_Op := Alias (Iface_Prim_Op);
1532                   end loop;
1533
1534                   --  The current primitive operation can be overridden by the
1535                   --  generated entry wrapper.
1536
1537                   if Overriding_Possible (Iface_Prim_Op, Proc_Nam) then
1538                      First_Param := First  (Parameter_Specifications
1539                                              (Parent (Iface_Prim_Op)));
1540
1541                      goto Found;
1542                   end if;
1543                end if;
1544
1545                Next_Elmt (Iface_Prim_Op_Elmt);
1546             end loop;
1547          end if;
1548
1549          exit Examine_Parents when Etype (Iface) = Iface;
1550
1551          Iface := Etype (Iface);
1552       end loop Examine_Parents;
1553
1554       if Present (Abstract_Interfaces
1555                    (Corresponding_Record_Type (Scope (Proc_Nam))))
1556       then
1557          Iface_Elmt := First_Elmt
1558                          (Abstract_Interfaces
1559                            (Corresponding_Record_Type (Scope (Proc_Nam))));
1560          Examine_Interfaces : while Present (Iface_Elmt) loop
1561             Iface := Node (Iface_Elmt);
1562
1563             if Present (Primitive_Operations (Iface)) then
1564                Iface_Prim_Op_Elmt := First_Elmt (Primitive_Operations (Iface));
1565                while Present (Iface_Prim_Op_Elmt) loop
1566                   Iface_Prim_Op := Node (Iface_Prim_Op_Elmt);
1567
1568                   if not Is_Predefined_Dispatching_Operation
1569                            (Iface_Prim_Op)
1570                   then
1571                      while Present (Alias (Iface_Prim_Op)) loop
1572                         Iface_Prim_Op := Alias (Iface_Prim_Op);
1573                      end loop;
1574
1575                      --  The current primitive operation can be overridden by
1576                      --  the generated entry wrapper.
1577
1578                      if Overriding_Possible (Iface_Prim_Op, Proc_Nam) then
1579                         First_Param := First (Parameter_Specifications
1580                                                (Parent (Iface_Prim_Op)));
1581
1582                         goto Found;
1583                      end if;
1584                   end if;
1585
1586                   Next_Elmt (Iface_Prim_Op_Elmt);
1587                end loop;
1588             end if;
1589
1590             Next_Elmt (Iface_Elmt);
1591          end loop Examine_Interfaces;
1592       end if;
1593
1594       --  Return if no interface primitive can be overridden
1595
1596       return Empty;
1597
1598       <<Found>>
1599
1600       New_Formals := Replicate_Entry_Formals (Loc, Formals);
1601
1602       --  ??? Certain source packages contain protected or task types that do
1603       --  not implement any interfaces and are compiled with the -gnat05
1604       --  switch.  In this case, a default first parameter is created.
1605
1606       --  If the interface operation has an access parameter, create a copy
1607       --  of it, with the same null exclusion indicator if present.
1608
1609       if Present (First_Param) then
1610          if Nkind (Parameter_Type (First_Param)) = N_Access_Definition then
1611             Obj_Param_Typ :=
1612               Make_Access_Definition (Loc,
1613                 Subtype_Mark =>
1614                   New_Reference_To (Obj_Typ, Loc));
1615             Set_Null_Exclusion_Present (Obj_Param_Typ,
1616                Null_Exclusion_Present (Parameter_Type (First_Param)));
1617
1618          else
1619             Obj_Param_Typ := New_Reference_To (Obj_Typ, Loc);
1620          end if;
1621
1622          Obj_Param :=
1623            Make_Parameter_Specification (Loc,
1624              Defining_Identifier =>
1625                Make_Defining_Identifier (Loc, Name_uO),
1626              In_Present  => In_Present  (First_Param),
1627              Out_Present => Out_Present (First_Param),
1628              Parameter_Type => Obj_Param_Typ);
1629
1630       else
1631          Obj_Param :=
1632            Make_Parameter_Specification (Loc,
1633              Defining_Identifier =>
1634                Make_Defining_Identifier (Loc, Name_uO),
1635              In_Present  => True,
1636              Out_Present => True,
1637                Parameter_Type => New_Reference_To (Obj_Typ, Loc));
1638       end if;
1639
1640       Prepend_To (New_Formals, Obj_Param);
1641
1642       --  Minimum decoration needed to catch the entity in
1643       --  Sem_Ch6.Override_Dispatching_Operation
1644
1645       if Ekind (Proc_Nam) = E_Procedure
1646         or else Ekind (Proc_Nam) = E_Entry
1647       then
1648          Set_Ekind                (New_Name_Id, E_Procedure);
1649          Set_Is_Primitive_Wrapper (New_Name_Id);
1650          Set_Wrapped_Entity       (New_Name_Id, Proc_Nam);
1651
1652          return
1653            Make_Procedure_Specification (Loc,
1654              Defining_Unit_Name => New_Name_Id,
1655              Parameter_Specifications => New_Formals);
1656
1657       else pragma Assert (Ekind (Proc_Nam) = E_Function);
1658          Set_Ekind (New_Name_Id, E_Function);
1659
1660          return
1661            Make_Function_Specification (Loc,
1662              Defining_Unit_Name => New_Name_Id,
1663              Parameter_Specifications => New_Formals,
1664              Result_Definition =>
1665                New_Copy (Result_Definition (Parent (Proc_Nam))));
1666       end if;
1667    end Build_Wrapper_Spec;
1668
1669    ---------------------------
1670    -- Build_Find_Body_Index --
1671    ---------------------------
1672
1673    function Build_Find_Body_Index (Typ : Entity_Id) return Node_Id is
1674       Loc   : constant Source_Ptr := Sloc (Typ);
1675       Ent   : Entity_Id;
1676       E_Typ : Entity_Id;
1677       Has_F : Boolean := False;
1678       Index : Nat;
1679       If_St : Node_Id := Empty;
1680       Lo    : Node_Id;
1681       Hi    : Node_Id;
1682       Decls : List_Id := New_List;
1683       Ret   : Node_Id;
1684       Spec  : Node_Id;
1685       Siz   : Node_Id := Empty;
1686
1687       procedure Add_If_Clause (Expr : Node_Id);
1688       --  Add test for range of current entry
1689
1690       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
1691       --  If a bound of an entry is given by a discriminant, retrieve the
1692       --  actual value of the discriminant from the enclosing object.
1693
1694       -------------------
1695       -- Add_If_Clause --
1696       -------------------
1697
1698       procedure Add_If_Clause (Expr : Node_Id) is
1699          Cond  : Node_Id;
1700          Stats : constant List_Id :=
1701                    New_List (
1702                      Make_Simple_Return_Statement (Loc,
1703                        Expression => Make_Integer_Literal (Loc, Index + 1)));
1704
1705       begin
1706          --  Index for current entry body
1707
1708          Index := Index + 1;
1709
1710          --  Compute total length of entry queues so far
1711
1712          if No (Siz) then
1713             Siz := Expr;
1714          else
1715             Siz :=
1716               Make_Op_Add (Loc,
1717                 Left_Opnd => Siz,
1718                 Right_Opnd => Expr);
1719          end if;
1720
1721          Cond :=
1722            Make_Op_Le (Loc,
1723              Left_Opnd => Make_Identifier (Loc, Name_uE),
1724              Right_Opnd => Siz);
1725
1726          --  Map entry queue indices in the range of the current family
1727          --  into the current index, that designates the entry body.
1728
1729          if No (If_St) then
1730             If_St :=
1731               Make_Implicit_If_Statement (Typ,
1732                 Condition => Cond,
1733                 Then_Statements => Stats,
1734                 Elsif_Parts   => New_List);
1735
1736             Ret := If_St;
1737
1738          else
1739             Append (
1740               Make_Elsif_Part (Loc,
1741                 Condition => Cond,
1742                 Then_Statements => Stats),
1743               Elsif_Parts (If_St));
1744          end if;
1745       end Add_If_Clause;
1746
1747       ------------------------------
1748       -- Convert_Discriminant_Ref --
1749       ------------------------------
1750
1751       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
1752          B   : Node_Id;
1753
1754       begin
1755          if Is_Entity_Name (Bound)
1756            and then Ekind (Entity (Bound)) = E_Discriminant
1757          then
1758             B :=
1759               Make_Selected_Component (Loc,
1760                Prefix =>
1761                  Unchecked_Convert_To (Corresponding_Record_Type (Typ),
1762                    Make_Explicit_Dereference (Loc,
1763                      Make_Identifier (Loc, Name_uObject))),
1764                Selector_Name => Make_Identifier (Loc, Chars (Bound)));
1765             Set_Etype (B, Etype (Entity (Bound)));
1766          else
1767             B := New_Copy_Tree (Bound);
1768          end if;
1769
1770          return B;
1771       end Convert_Discriminant_Ref;
1772
1773    --  Start of processing for Build_Find_Body_Index
1774
1775    begin
1776       Spec := Build_Find_Body_Index_Spec (Typ);
1777
1778       Ent := First_Entity (Typ);
1779       while Present (Ent) loop
1780          if Ekind (Ent) = E_Entry_Family then
1781             Has_F := True;
1782             exit;
1783          end if;
1784
1785          Next_Entity (Ent);
1786       end loop;
1787
1788       if not Has_F then
1789
1790          --  If the protected type has no entry families, there is a one-one
1791          --  correspondence between entry queue and entry body.
1792
1793          Ret :=
1794            Make_Simple_Return_Statement (Loc,
1795              Expression => Make_Identifier (Loc, Name_uE));
1796
1797       else
1798          --  Suppose entries e1, e2, ... have size l1, l2, ... we generate
1799          --  the following:
1800          --
1801          --  if E <= l1 then return 1;
1802          --  elsif E <= l1 + l2 then return 2;
1803          --  ...
1804
1805          Index := 0;
1806          Siz   := Empty;
1807          Ent   := First_Entity (Typ);
1808
1809          Add_Object_Pointer (Loc, Typ, Decls);
1810
1811          while Present (Ent) loop
1812
1813             if Ekind (Ent) = E_Entry then
1814                Add_If_Clause (Make_Integer_Literal (Loc, 1));
1815
1816             elsif Ekind (Ent) = E_Entry_Family then
1817
1818                E_Typ := Etype (Discrete_Subtype_Definition (Parent (Ent)));
1819                Hi := Convert_Discriminant_Ref (Type_High_Bound (E_Typ));
1820                Lo := Convert_Discriminant_Ref (Type_Low_Bound  (E_Typ));
1821                Add_If_Clause (Family_Size (Loc, Hi, Lo, Typ, False));
1822             end if;
1823
1824             Next_Entity (Ent);
1825          end loop;
1826
1827          if Index = 1 then
1828             Decls := New_List;
1829             Ret :=
1830               Make_Simple_Return_Statement (Loc,
1831                 Expression => Make_Integer_Literal (Loc, 1));
1832
1833          elsif Nkind (Ret) = N_If_Statement then
1834
1835             --  Ranges are in increasing order, so last one doesn't need guard
1836
1837             declare
1838                Nod : constant Node_Id := Last (Elsif_Parts (Ret));
1839             begin
1840                Remove (Nod);
1841                Set_Else_Statements (Ret, Then_Statements (Nod));
1842             end;
1843          end if;
1844       end if;
1845
1846       return
1847         Make_Subprogram_Body (Loc,
1848           Specification => Spec,
1849           Declarations  => Decls,
1850           Handled_Statement_Sequence =>
1851             Make_Handled_Sequence_Of_Statements (Loc,
1852               Statements => New_List (Ret)));
1853    end Build_Find_Body_Index;
1854
1855    --------------------------------
1856    -- Build_Find_Body_Index_Spec --
1857    --------------------------------
1858
1859    function Build_Find_Body_Index_Spec (Typ : Entity_Id) return Node_Id is
1860       Loc   : constant Source_Ptr := Sloc (Typ);
1861       Id    : constant Entity_Id :=
1862                Make_Defining_Identifier (Loc,
1863                  Chars => New_External_Name (Chars (Typ), 'F'));
1864       Parm1 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uO);
1865       Parm2 : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uE);
1866
1867    begin
1868       return
1869         Make_Function_Specification (Loc,
1870           Defining_Unit_Name => Id,
1871           Parameter_Specifications => New_List (
1872             Make_Parameter_Specification (Loc,
1873               Defining_Identifier => Parm1,
1874               Parameter_Type =>
1875                 New_Reference_To (RTE (RE_Address), Loc)),
1876
1877             Make_Parameter_Specification (Loc,
1878               Defining_Identifier => Parm2,
1879               Parameter_Type =>
1880                 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))),
1881           Result_Definition => New_Occurrence_Of (
1882             RTE (RE_Protected_Entry_Index), Loc));
1883    end Build_Find_Body_Index_Spec;
1884
1885    -------------------------
1886    -- Build_Master_Entity --
1887    -------------------------
1888
1889    procedure Build_Master_Entity (E : Entity_Id) is
1890       Loc  : constant Source_Ptr := Sloc (E);
1891       P    : Node_Id;
1892       Decl : Node_Id;
1893       S    : Entity_Id;
1894
1895    begin
1896       S := Scope (E);
1897
1898       --  Ada 2005 (AI-287): Do not set/get the has_master_entity reminder
1899       --  in internal scopes, unless present already.. Required for nested
1900       --  limited aggregates, where the expansion of task components may
1901       --  generate inner blocks. If the block is the rewriting of a call
1902       --  this is valid master.
1903
1904       if Ada_Version >= Ada_05 then
1905          while Is_Internal (S) loop
1906             if Nkind (Parent (S)) = N_Block_Statement
1907               and then
1908                 Nkind (Original_Node (Parent (S))) = N_Procedure_Call_Statement
1909             then
1910                exit;
1911             else
1912                S := Scope (S);
1913             end if;
1914          end loop;
1915       end if;
1916
1917       --  Nothing to do if we already built a master entity for this scope
1918       --  or if there is no task hierarchy.
1919
1920       if Has_Master_Entity (S)
1921         or else Restriction_Active (No_Task_Hierarchy)
1922       then
1923          return;
1924       end if;
1925
1926       --  Otherwise first build the master entity
1927       --    _Master : constant Master_Id := Current_Master.all;
1928       --  and insert it just before the current declaration
1929
1930       Decl :=
1931         Make_Object_Declaration (Loc,
1932           Defining_Identifier =>
1933             Make_Defining_Identifier (Loc, Name_uMaster),
1934           Constant_Present => True,
1935           Object_Definition => New_Reference_To (RTE (RE_Master_Id), Loc),
1936           Expression =>
1937             Make_Explicit_Dereference (Loc,
1938               New_Reference_To (RTE (RE_Current_Master), Loc)));
1939
1940       P := Parent (E);
1941       Insert_Before (P, Decl);
1942       Analyze (Decl);
1943
1944       --  Ada 2005 (AI-287): Set the has_master_entity reminder in the
1945       --  non-internal scope selected above.
1946
1947       if Ada_Version >= Ada_05 then
1948          Set_Has_Master_Entity (S);
1949       else
1950          Set_Has_Master_Entity (Scope (E));
1951       end if;
1952
1953       --  Now mark the containing scope as a task master
1954
1955       while Nkind (P) /= N_Compilation_Unit loop
1956          P := Parent (P);
1957
1958          --  If we fall off the top, we are at the outer level, and the
1959          --  environment task is our effective master, so nothing to mark.
1960
1961          if Nkind_In
1962               (P, N_Task_Body, N_Block_Statement, N_Subprogram_Body)
1963          then
1964             Set_Is_Task_Master (P, True);
1965             return;
1966
1967          elsif Nkind (Parent (P)) = N_Subunit then
1968             P := Corresponding_Stub (Parent (P));
1969          end if;
1970       end loop;
1971    end Build_Master_Entity;
1972
1973    ---------------------------
1974    -- Build_Protected_Entry --
1975    ---------------------------
1976
1977    function Build_Protected_Entry
1978      (N   : Node_Id;
1979       Ent : Entity_Id;
1980       Pid : Node_Id) return Node_Id
1981    is
1982       Loc : constant Source_Ptr := Sloc (N);
1983
1984       Decls   : constant List_Id := Declarations (N);
1985       End_Lab : constant Node_Id :=
1986                   End_Label (Handled_Statement_Sequence (N));
1987       End_Loc : constant Source_Ptr :=
1988                   Sloc (Last (Statements (Handled_Statement_Sequence (N))));
1989       --  Used for the generated call to Complete_Entry_Body
1990
1991       Han_Loc : Source_Ptr;
1992       --  Used for the exception handler, inserted at end of the body
1993
1994       Op_Decls : constant List_Id := New_List;
1995       Complete : Node_Id;
1996       Edef     : Entity_Id;
1997       Espec    : Node_Id;
1998       Ohandle  : Node_Id;
1999       Op_Stats : List_Id;
2000
2001    begin
2002       --  Set the source location on the exception handler only when debugging
2003       --  the expanded code (see Make_Implicit_Exception_Handler).
2004
2005       if Debug_Generated_Code then
2006          Han_Loc := End_Loc;
2007
2008       --  Otherwise the inserted code should not be visible to the debugger
2009
2010       else
2011          Han_Loc := No_Location;
2012       end if;
2013
2014       Edef :=
2015         Make_Defining_Identifier (Loc,
2016           Chars => Chars (Protected_Body_Subprogram (Ent)));
2017       Espec :=
2018         Build_Protected_Entry_Specification (Loc, Edef, Empty);
2019
2020       --  Add the following declarations:
2021       --    type poVP is access poV;
2022       --    _object : poVP := poVP (_O);
2023       --
2024       --  where _O is the formal parameter associated with the concurrent
2025       --  object. These declarations are needed for Complete_Entry_Body.
2026
2027       Add_Object_Pointer (Loc, Pid, Op_Decls);
2028
2029       --  Add renamings for all formals, the Protection object, discriminals,
2030       --  privals and the entry indix constant for use by debugger.
2031
2032       Add_Formal_Renamings (Espec, Op_Decls, Ent, Loc);
2033       Debug_Private_Data_Declarations (Decls);
2034
2035       case Corresponding_Runtime_Package (Pid) is
2036          when System_Tasking_Protected_Objects_Entries =>
2037             Complete :=
2038               New_Reference_To (RTE (RE_Complete_Entry_Body), Loc);
2039
2040          when System_Tasking_Protected_Objects_Single_Entry =>
2041             Complete :=
2042               New_Reference_To (RTE (RE_Complete_Single_Entry_Body), Loc);
2043
2044          when others =>
2045             raise Program_Error;
2046       end case;
2047
2048       Op_Stats := New_List (
2049         Make_Block_Statement (Loc,
2050           Declarations => Decls,
2051           Handled_Statement_Sequence =>
2052             Handled_Statement_Sequence (N)),
2053
2054         Make_Procedure_Call_Statement (End_Loc,
2055           Name => Complete,
2056           Parameter_Associations => New_List (
2057             Make_Attribute_Reference (End_Loc,
2058               Prefix =>
2059                 Make_Selected_Component (End_Loc,
2060                   Prefix =>
2061                     Make_Identifier (End_Loc, Name_uObject),
2062                   Selector_Name =>
2063                     Make_Identifier (End_Loc, Name_uObject)),
2064               Attribute_Name => Name_Unchecked_Access))));
2065
2066       --  When exceptions can not be propagated, we never need to call
2067       --  Exception_Complete_Entry_Body
2068
2069       if No_Exception_Handlers_Set then
2070          return
2071            Make_Subprogram_Body (Loc,
2072              Specification => Espec,
2073              Declarations => Op_Decls,
2074              Handled_Statement_Sequence =>
2075                Make_Handled_Sequence_Of_Statements (Loc,
2076                  Statements => Op_Stats,
2077                  End_Label  => End_Lab));
2078
2079       else
2080          Ohandle := Make_Others_Choice (Loc);
2081          Set_All_Others (Ohandle);
2082
2083          case Corresponding_Runtime_Package (Pid) is
2084             when System_Tasking_Protected_Objects_Entries =>
2085                Complete :=
2086                  New_Reference_To
2087                    (RTE (RE_Exceptional_Complete_Entry_Body), Loc);
2088
2089             when System_Tasking_Protected_Objects_Single_Entry =>
2090                Complete :=
2091                  New_Reference_To
2092                    (RTE (RE_Exceptional_Complete_Single_Entry_Body), Loc);
2093
2094             when others =>
2095                raise Program_Error;
2096          end case;
2097
2098          --  Create body of entry procedure. The renaming declarations are
2099          --  placed ahead of the block that contains the actual entry body.
2100
2101          return
2102            Make_Subprogram_Body (Loc,
2103              Specification => Espec,
2104              Declarations => Op_Decls,
2105              Handled_Statement_Sequence =>
2106                Make_Handled_Sequence_Of_Statements (Loc,
2107                  Statements => Op_Stats,
2108                  End_Label  => End_Lab,
2109                  Exception_Handlers => New_List (
2110                    Make_Implicit_Exception_Handler (Han_Loc,
2111                      Exception_Choices => New_List (Ohandle),
2112
2113                      Statements =>  New_List (
2114                        Make_Procedure_Call_Statement (Han_Loc,
2115                          Name => Complete,
2116                          Parameter_Associations => New_List (
2117                            Make_Attribute_Reference (Han_Loc,
2118                              Prefix =>
2119                                Make_Selected_Component (Han_Loc,
2120                                  Prefix =>
2121                                    Make_Identifier (Han_Loc, Name_uObject),
2122                                  Selector_Name =>
2123                                    Make_Identifier (Han_Loc, Name_uObject)),
2124                                Attribute_Name => Name_Unchecked_Access),
2125
2126                            Make_Function_Call (Han_Loc,
2127                              Name => New_Reference_To (
2128                                RTE (RE_Get_GNAT_Exception), Loc)))))))));
2129       end if;
2130    end Build_Protected_Entry;
2131
2132    -----------------------------------------
2133    -- Build_Protected_Entry_Specification --
2134    -----------------------------------------
2135
2136    function Build_Protected_Entry_Specification
2137      (Loc    : Source_Ptr;
2138       Def_Id : Entity_Id;
2139       Ent_Id : Entity_Id) return Node_Id
2140    is
2141       P : constant Entity_Id := Make_Defining_Identifier (Loc, Name_uP);
2142
2143    begin
2144       Set_Debug_Info_Needed (Def_Id);
2145
2146       if Present (Ent_Id) then
2147          Append_Elmt (P, Accept_Address (Ent_Id));
2148       end if;
2149
2150       return
2151         Make_Procedure_Specification (Loc,
2152           Defining_Unit_Name => Def_Id,
2153           Parameter_Specifications => New_List (
2154             Make_Parameter_Specification (Loc,
2155               Defining_Identifier =>
2156                 Make_Defining_Identifier (Loc, Name_uO),
2157               Parameter_Type =>
2158                 New_Reference_To (RTE (RE_Address), Loc)),
2159
2160             Make_Parameter_Specification (Loc,
2161               Defining_Identifier => P,
2162               Parameter_Type =>
2163                 New_Reference_To (RTE (RE_Address), Loc)),
2164
2165             Make_Parameter_Specification (Loc,
2166               Defining_Identifier =>
2167                 Make_Defining_Identifier (Loc, Name_uE),
2168               Parameter_Type =>
2169                 New_Reference_To (RTE (RE_Protected_Entry_Index), Loc))));
2170    end Build_Protected_Entry_Specification;
2171
2172    --------------------------
2173    -- Build_Protected_Spec --
2174    --------------------------
2175
2176    function Build_Protected_Spec
2177      (N           : Node_Id;
2178       Obj_Type    : Entity_Id;
2179       Ident       : Entity_Id;
2180       Unprotected : Boolean := False) return List_Id
2181    is
2182       Loc       : constant Source_Ptr := Sloc (N);
2183       Decl      : Node_Id;
2184       Formal    : Entity_Id;
2185       New_Plist : List_Id;
2186       New_Param : Node_Id;
2187
2188    begin
2189       New_Plist := New_List;
2190
2191       Formal := First_Formal (Ident);
2192       while Present (Formal) loop
2193          New_Param :=
2194            Make_Parameter_Specification (Loc,
2195              Defining_Identifier =>
2196                Make_Defining_Identifier (Sloc (Formal), Chars (Formal)),
2197              In_Present          => In_Present (Parent (Formal)),
2198              Out_Present         => Out_Present (Parent (Formal)),
2199              Parameter_Type      => New_Reference_To (Etype (Formal), Loc));
2200
2201          if Unprotected then
2202             Set_Protected_Formal (Formal, Defining_Identifier (New_Param));
2203          end if;
2204
2205          Append (New_Param, New_Plist);
2206          Next_Formal (Formal);
2207       end loop;
2208
2209       --  If the subprogram is a procedure and the context is not an access
2210       --  to protected subprogram, the parameter is in-out. Otherwise it is
2211       --  an in parameter.
2212
2213       Decl :=
2214         Make_Parameter_Specification (Loc,
2215           Defining_Identifier =>
2216             Make_Defining_Identifier (Loc, Name_uObject),
2217           In_Present => True,
2218           Out_Present =>
2219             (Etype (Ident) = Standard_Void_Type
2220                and then not Is_RTE (Obj_Type, RE_Address)),
2221           Parameter_Type =>
2222             New_Reference_To (Obj_Type, Loc));
2223       Set_Debug_Info_Needed (Defining_Identifier (Decl));
2224       Prepend_To (New_Plist, Decl);
2225
2226       return New_Plist;
2227    end Build_Protected_Spec;
2228
2229    ---------------------------------------
2230    -- Build_Protected_Sub_Specification --
2231    ---------------------------------------
2232
2233    function Build_Protected_Sub_Specification
2234      (N        : Node_Id;
2235       Prot_Typ : Entity_Id;
2236       Mode     : Subprogram_Protection_Mode) return Node_Id
2237    is
2238       Loc       : constant Source_Ptr := Sloc (N);
2239       Decl      : Node_Id;
2240       Def_Id    : Entity_Id;
2241       New_Id    : Entity_Id;
2242       New_Plist : List_Id;
2243       New_Spec  : Node_Id;
2244
2245       Append_Chr : constant array (Subprogram_Protection_Mode) of Character :=
2246                      (Dispatching_Mode => ' ',
2247                       Protected_Mode   => 'P',
2248                       Unprotected_Mode => 'N');
2249
2250    begin
2251       if Ekind (Defining_Unit_Name (Specification (N))) =
2252            E_Subprogram_Body
2253       then
2254          Decl := Unit_Declaration_Node (Corresponding_Spec (N));
2255       else
2256          Decl := N;
2257       end if;
2258
2259       Def_Id := Defining_Unit_Name (Specification (Decl));
2260
2261       New_Plist :=
2262         Build_Protected_Spec
2263           (Decl, Corresponding_Record_Type (Prot_Typ), Def_Id,
2264            Mode = Unprotected_Mode);
2265       New_Id :=
2266         Make_Defining_Identifier (Loc,
2267           Chars => Build_Selected_Name (Prot_Typ, Def_Id, Append_Chr (Mode)));
2268
2269       --  The unprotected operation carries the user code, and debugging
2270       --  information must be generated for it, even though this spec does
2271       --  not come from source. It is also convenient to allow gdb to step
2272       --  into the protected operation, even though it only contains lock/
2273       --  unlock calls.
2274
2275       Set_Debug_Info_Needed (New_Id);
2276
2277       if Nkind (Specification (Decl)) = N_Procedure_Specification then
2278          New_Spec :=
2279            Make_Procedure_Specification (Loc,
2280              Defining_Unit_Name => New_Id,
2281              Parameter_Specifications => New_Plist);
2282
2283       --  Create a new specification for the anonymous subprogram type
2284
2285       else
2286          New_Spec :=
2287            Make_Function_Specification (Loc,
2288              Defining_Unit_Name => New_Id,
2289              Parameter_Specifications => New_Plist,
2290              Result_Definition =>
2291                Copy_Result_Type (Result_Definition (Specification (Decl))));
2292
2293          Set_Return_Present (Defining_Unit_Name (New_Spec));
2294       end if;
2295
2296       return New_Spec;
2297    end Build_Protected_Sub_Specification;
2298
2299    -------------------------------------
2300    -- Build_Protected_Subprogram_Body --
2301    -------------------------------------
2302
2303    function Build_Protected_Subprogram_Body
2304      (N         : Node_Id;
2305       Pid       : Node_Id;
2306       N_Op_Spec : Node_Id) return Node_Id
2307    is
2308       Loc          : constant Source_Ptr := Sloc (N);
2309       Op_Spec      : Node_Id;
2310       P_Op_Spec    : Node_Id;
2311       Uactuals     : List_Id;
2312       Pformal      : Node_Id;
2313       Unprot_Call  : Node_Id;
2314       Sub_Body     : Node_Id;
2315       Lock_Name    : Node_Id;
2316       Lock_Stmt    : Node_Id;
2317       Service_Name : Node_Id;
2318       R            : Node_Id;
2319       Return_Stmt  : Node_Id := Empty;    -- init to avoid gcc 3 warning
2320       Pre_Stmts    : List_Id := No_List;  -- init to avoid gcc 3 warning
2321       Stmts        : List_Id;
2322       Object_Parm  : Node_Id;
2323       Exc_Safe     : Boolean;
2324
2325       function Is_Exception_Safe (Subprogram : Node_Id) return Boolean;
2326       --  Tell whether a given subprogram cannot raise an exception
2327
2328       -----------------------
2329       -- Is_Exception_Safe --
2330       -----------------------
2331
2332       function Is_Exception_Safe (Subprogram : Node_Id) return Boolean is
2333
2334          function Has_Side_Effect (N : Node_Id) return Boolean;
2335          --  Return True whenever encountering a subprogram call or raise
2336          --  statement of any kind in the sequence of statements
2337
2338          ---------------------
2339          -- Has_Side_Effect --
2340          ---------------------
2341
2342          --  What is this doing buried two levels down in exp_ch9. It seems
2343          --  like a generally useful function, and indeed there may be code
2344          --  duplication going on here ???
2345
2346          function Has_Side_Effect (N : Node_Id) return Boolean is
2347             Stmt : Node_Id;
2348             Expr : Node_Id;
2349
2350             function Is_Call_Or_Raise (N : Node_Id) return Boolean;
2351             --  Indicate whether N is a subprogram call or a raise statement
2352
2353             ----------------------
2354             -- Is_Call_Or_Raise --
2355             ----------------------
2356
2357             function Is_Call_Or_Raise (N : Node_Id) return Boolean is
2358             begin
2359                return Nkind_In (N, N_Procedure_Call_Statement,
2360                                    N_Function_Call,
2361                                    N_Raise_Statement,
2362                                    N_Raise_Constraint_Error,
2363                                    N_Raise_Program_Error,
2364                                    N_Raise_Storage_Error);
2365             end Is_Call_Or_Raise;
2366
2367          --  Start of processing for Has_Side_Effect
2368
2369          begin
2370             Stmt := N;
2371             while Present (Stmt) loop
2372                if Is_Call_Or_Raise (Stmt) then
2373                   return True;
2374                end if;
2375
2376                --  An object declaration can also contain a function call
2377                --  or a raise statement
2378
2379                if Nkind (Stmt) = N_Object_Declaration then
2380                   Expr := Expression (Stmt);
2381
2382                   if Present (Expr) and then Is_Call_Or_Raise (Expr) then
2383                      return True;
2384                   end if;
2385                end if;
2386
2387                Next (Stmt);
2388             end loop;
2389
2390             return False;
2391          end Has_Side_Effect;
2392
2393       --  Start of processing for Is_Exception_Safe
2394
2395       begin
2396          --  If the checks handled by the back end are not disabled, we cannot
2397          --  ensure that no exception will be raised.
2398
2399          if not Access_Checks_Suppressed (Empty)
2400            or else not Discriminant_Checks_Suppressed (Empty)
2401            or else not Range_Checks_Suppressed (Empty)
2402            or else not Index_Checks_Suppressed (Empty)
2403            or else Opt.Stack_Checking_Enabled
2404          then
2405             return False;
2406          end if;
2407
2408          if Has_Side_Effect (First (Declarations (Subprogram)))
2409            or else
2410               Has_Side_Effect (
2411                 First (Statements (Handled_Statement_Sequence (Subprogram))))
2412          then
2413             return False;
2414          else
2415             return True;
2416          end if;
2417       end Is_Exception_Safe;
2418
2419    --  Start of processing for Build_Protected_Subprogram_Body
2420
2421    begin
2422       Op_Spec := Specification (N);
2423       Exc_Safe := Is_Exception_Safe (N);
2424
2425       P_Op_Spec :=
2426         Build_Protected_Sub_Specification (N, Pid, Protected_Mode);
2427
2428       --  Build a list of the formal parameters of the protected version of
2429       --  the subprogram to use as the actual parameters of the unprotected
2430       --  version.
2431
2432       Uactuals := New_List;
2433       Pformal := First (Parameter_Specifications (P_Op_Spec));
2434       while Present (Pformal) loop
2435          Append (
2436            Make_Identifier (Loc, Chars (Defining_Identifier (Pformal))),
2437            Uactuals);
2438          Next (Pformal);
2439       end loop;
2440
2441       --  Make a call to the unprotected version of the subprogram built above
2442       --  for use by the protected version built below.
2443
2444       if Nkind (Op_Spec) = N_Function_Specification then
2445          if Exc_Safe then
2446             R := Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
2447             Unprot_Call :=
2448               Make_Object_Declaration (Loc,
2449                 Defining_Identifier => R,
2450                 Constant_Present => True,
2451                 Object_Definition => New_Copy (Result_Definition (N_Op_Spec)),
2452                 Expression =>
2453                   Make_Function_Call (Loc,
2454                     Name => Make_Identifier (Loc,
2455                       Chars (Defining_Unit_Name (N_Op_Spec))),
2456                     Parameter_Associations => Uactuals));
2457             Return_Stmt := Make_Simple_Return_Statement (Loc,
2458               Expression => New_Reference_To (R, Loc));
2459
2460          else
2461             Unprot_Call := Make_Simple_Return_Statement (Loc,
2462               Expression => Make_Function_Call (Loc,
2463                 Name =>
2464                   Make_Identifier (Loc,
2465                     Chars (Defining_Unit_Name (N_Op_Spec))),
2466                 Parameter_Associations => Uactuals));
2467          end if;
2468
2469       else
2470          Unprot_Call :=
2471            Make_Procedure_Call_Statement (Loc,
2472              Name =>
2473                Make_Identifier (Loc,
2474                  Chars (Defining_Unit_Name (N_Op_Spec))),
2475              Parameter_Associations => Uactuals);
2476       end if;
2477
2478       --  Wrap call in block that will be covered by an at_end handler
2479
2480       if not Exc_Safe then
2481          Unprot_Call := Make_Block_Statement (Loc,
2482            Handled_Statement_Sequence =>
2483              Make_Handled_Sequence_Of_Statements (Loc,
2484                Statements => New_List (Unprot_Call)));
2485       end if;
2486
2487       --  Make the protected subprogram body. This locks the protected
2488       --  object and calls the unprotected version of the subprogram.
2489
2490       case Corresponding_Runtime_Package (Pid) is
2491          when System_Tasking_Protected_Objects_Entries =>
2492             Lock_Name := New_Reference_To (RTE (RE_Lock_Entries), Loc);
2493             Service_Name := New_Reference_To (RTE (RE_Service_Entries), Loc);
2494
2495          when System_Tasking_Protected_Objects_Single_Entry =>
2496             Lock_Name := New_Reference_To (RTE (RE_Lock_Entry), Loc);
2497             Service_Name := New_Reference_To (RTE (RE_Service_Entry), Loc);
2498
2499          when System_Tasking_Protected_Objects =>
2500             Lock_Name := New_Reference_To (RTE (RE_Lock), Loc);
2501             Service_Name := New_Reference_To (RTE (RE_Unlock), Loc);
2502
2503          when others =>
2504             raise Program_Error;
2505       end case;
2506
2507       Object_Parm :=
2508         Make_Attribute_Reference (Loc,
2509            Prefix =>
2510              Make_Selected_Component (Loc,
2511                Prefix =>
2512                  Make_Identifier (Loc, Name_uObject),
2513              Selector_Name =>
2514                  Make_Identifier (Loc, Name_uObject)),
2515            Attribute_Name => Name_Unchecked_Access);
2516
2517       Lock_Stmt := Make_Procedure_Call_Statement (Loc,
2518         Name => Lock_Name,
2519         Parameter_Associations => New_List (Object_Parm));
2520
2521       if Abort_Allowed then
2522          Stmts := New_List (
2523            Make_Procedure_Call_Statement (Loc,
2524              Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
2525              Parameter_Associations => Empty_List),
2526            Lock_Stmt);
2527
2528       else
2529          Stmts := New_List (Lock_Stmt);
2530       end if;
2531
2532       if not Exc_Safe then
2533          Append (Unprot_Call, Stmts);
2534       else
2535          if Nkind (Op_Spec) = N_Function_Specification then
2536             Pre_Stmts := Stmts;
2537             Stmts     := Empty_List;
2538          else
2539             Append (Unprot_Call, Stmts);
2540          end if;
2541
2542          Append (
2543            Make_Procedure_Call_Statement (Loc,
2544              Name => Service_Name,
2545              Parameter_Associations =>
2546                New_List (New_Copy_Tree (Object_Parm))),
2547            Stmts);
2548
2549          if Abort_Allowed then
2550             Append (
2551               Make_Procedure_Call_Statement (Loc,
2552                 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc),
2553                 Parameter_Associations => Empty_List),
2554               Stmts);
2555          end if;
2556
2557          if Nkind (Op_Spec) = N_Function_Specification then
2558             Append (Return_Stmt, Stmts);
2559             Append (Make_Block_Statement (Loc,
2560               Declarations => New_List (Unprot_Call),
2561               Handled_Statement_Sequence =>
2562                 Make_Handled_Sequence_Of_Statements (Loc,
2563                   Statements => Stmts)), Pre_Stmts);
2564             Stmts := Pre_Stmts;
2565          end if;
2566       end if;
2567
2568       Sub_Body :=
2569         Make_Subprogram_Body (Loc,
2570           Declarations => Empty_List,
2571           Specification => P_Op_Spec,
2572           Handled_Statement_Sequence =>
2573             Make_Handled_Sequence_Of_Statements (Loc, Statements => Stmts));
2574
2575       if not Exc_Safe then
2576          Set_Is_Protected_Subprogram_Body (Sub_Body);
2577       end if;
2578
2579       return Sub_Body;
2580    end Build_Protected_Subprogram_Body;
2581
2582    -------------------------------------
2583    -- Build_Protected_Subprogram_Call --
2584    -------------------------------------
2585
2586    procedure Build_Protected_Subprogram_Call
2587      (N        : Node_Id;
2588       Name     : Node_Id;
2589       Rec      : Node_Id;
2590       External : Boolean := True)
2591    is
2592       Loc     : constant Source_Ptr := Sloc (N);
2593       Sub     : constant Entity_Id  := Entity (Name);
2594       New_Sub : Node_Id;
2595       Params  : List_Id;
2596
2597    begin
2598       if External then
2599          New_Sub := New_Occurrence_Of (External_Subprogram (Sub), Loc);
2600       else
2601          New_Sub :=
2602            New_Occurrence_Of (Protected_Body_Subprogram (Sub), Loc);
2603       end if;
2604
2605       if Present (Parameter_Associations (N)) then
2606          Params := New_Copy_List_Tree (Parameter_Associations (N));
2607       else
2608          Params := New_List;
2609       end if;
2610
2611       Prepend (Rec, Params);
2612
2613       if Ekind (Sub) = E_Procedure then
2614          Rewrite (N,
2615            Make_Procedure_Call_Statement (Loc,
2616              Name => New_Sub,
2617              Parameter_Associations => Params));
2618
2619       else
2620          pragma Assert (Ekind (Sub) = E_Function);
2621          Rewrite (N,
2622            Make_Function_Call (Loc,
2623              Name => New_Sub,
2624              Parameter_Associations => Params));
2625       end if;
2626
2627       if External
2628         and then Nkind (Rec) = N_Unchecked_Type_Conversion
2629         and then Is_Entity_Name (Expression (Rec))
2630         and then Is_Shared_Passive (Entity (Expression (Rec)))
2631       then
2632          Add_Shared_Var_Lock_Procs (N);
2633       end if;
2634    end Build_Protected_Subprogram_Call;
2635
2636    -------------------------
2637    -- Build_Selected_Name --
2638    -------------------------
2639
2640    function Build_Selected_Name
2641      (Prefix      : Entity_Id;
2642       Selector    : Entity_Id;
2643       Append_Char : Character := ' ') return Name_Id
2644    is
2645       Select_Buffer : String (1 .. Hostparm.Max_Name_Length);
2646       Select_Len    : Natural;
2647
2648    begin
2649       Get_Name_String (Chars (Selector));
2650       Select_Len := Name_Len;
2651       Select_Buffer (1 .. Select_Len) := Name_Buffer (1 .. Name_Len);
2652       Get_Name_String (Chars (Prefix));
2653
2654       --  If scope is anonymous type, discard suffix to recover name of
2655       --  single protected object. Otherwise use protected type name.
2656
2657       if Name_Buffer (Name_Len) = 'T' then
2658          Name_Len := Name_Len - 1;
2659       end if;
2660
2661       Name_Buffer (Name_Len + 1) := '_';
2662       Name_Buffer (Name_Len + 2) := '_';
2663
2664       Name_Len := Name_Len + 2;
2665       for J in 1 .. Select_Len loop
2666          Name_Len := Name_Len + 1;
2667          Name_Buffer (Name_Len) := Select_Buffer (J);
2668       end loop;
2669
2670       --  Now add the Append_Char if specified. The encoding to follow
2671       --  depends on the type of entity. If Append_Char is either 'N' or 'P',
2672       --  then the entity is associated to a protected type subprogram.
2673       --  Otherwise, it is a protected type entry. For each case, the
2674       --  encoding to follow for the suffix is documented in exp_dbug.ads.
2675
2676       --  It would be better to encapsulate this as a routine in Exp_Dbug ???
2677
2678       if Append_Char /= ' ' then
2679          if Append_Char = 'P' or Append_Char = 'N' then
2680             Name_Len := Name_Len + 1;
2681             Name_Buffer (Name_Len) := Append_Char;
2682             return Name_Find;
2683          else
2684             Name_Buffer (Name_Len + 1) := '_';
2685             Name_Buffer (Name_Len + 2) := Append_Char;
2686             Name_Len := Name_Len + 2;
2687             return New_External_Name (Name_Find, ' ', -1);
2688          end if;
2689       else
2690          return Name_Find;
2691       end if;
2692    end Build_Selected_Name;
2693
2694    -----------------------------
2695    -- Build_Simple_Entry_Call --
2696    -----------------------------
2697
2698    --  A task entry call is converted to a call to Call_Simple
2699
2700    --    declare
2701    --       P : parms := (parm, parm, parm);
2702    --    begin
2703    --       Call_Simple (acceptor-task, entry-index, P'Address);
2704    --       parm := P.param;
2705    --       parm := P.param;
2706    --       ...
2707    --    end;
2708
2709    --  Here Pnn is an aggregate of the type constructed for the entry to hold
2710    --  the parameters, and the constructed aggregate value contains either the
2711    --  parameters or, in the case of non-elementary types, references to these
2712    --  parameters. Then the address of this aggregate is passed to the runtime
2713    --  routine, along with the task id value and the task entry index value.
2714    --  Pnn is only required if parameters are present.
2715
2716    --  The assignments after the call are present only in the case of in-out
2717    --  or out parameters for elementary types, and are used to assign back the
2718    --  resulting values of such parameters.
2719
2720    --  Note: the reason that we insert a block here is that in the context
2721    --  of selects, conditional entry calls etc. the entry call statement
2722    --  appears on its own, not as an element of a list.
2723
2724    --  A protected entry call is converted to a Protected_Entry_Call:
2725
2726    --  declare
2727    --     P   : E1_Params := (param, param, param);
2728    --     Pnn : Boolean;
2729    --     Bnn : Communications_Block;
2730
2731    --  declare
2732    --     P   : E1_Params := (param, param, param);
2733    --     Bnn : Communications_Block;
2734
2735    --  begin
2736    --     Protected_Entry_Call (
2737    --       Object => po._object'Access,
2738    --       E => <entry index>;
2739    --       Uninterpreted_Data => P'Address;
2740    --       Mode => Simple_Call;
2741    --       Block => Bnn);
2742    --     parm := P.param;
2743    --     parm := P.param;
2744    --       ...
2745    --  end;
2746
2747    procedure Build_Simple_Entry_Call
2748      (N       : Node_Id;
2749       Concval : Node_Id;
2750       Ename   : Node_Id;
2751       Index   : Node_Id)
2752    is
2753    begin
2754       Expand_Call (N);
2755
2756       --  If call has been inlined, nothing left to do
2757
2758       if Nkind (N) = N_Block_Statement then
2759          return;
2760       end if;
2761
2762       --  Convert entry call to Call_Simple call
2763
2764       declare
2765          Loc       : constant Source_Ptr := Sloc (N);
2766          Parms     : constant List_Id    := Parameter_Associations (N);
2767          Stats     : constant List_Id    := New_List;
2768          Actual    : Node_Id;
2769          Call      : Node_Id;
2770          Comm_Name : Entity_Id;
2771          Conctyp   : Node_Id;
2772          Decls     : List_Id;
2773          Ent       : Entity_Id;
2774          Ent_Acc   : Entity_Id;
2775          Formal    : Node_Id;
2776          Iface_Tag : Entity_Id;
2777          Iface_Typ : Entity_Id;
2778          N_Node    : Node_Id;
2779          N_Var     : Node_Id;
2780          P         : Entity_Id;
2781          Parm1     : Node_Id;
2782          Parm2     : Node_Id;
2783          Parm3     : Node_Id;
2784          Pdecl     : Node_Id;
2785          Plist     : List_Id;
2786          X         : Entity_Id;
2787          Xdecl     : Node_Id;
2788
2789       begin
2790          --  Simple entry and entry family cases merge here
2791
2792          Ent     := Entity (Ename);
2793          Ent_Acc := Entry_Parameters_Type (Ent);
2794          Conctyp := Etype (Concval);
2795
2796          --  If prefix is an access type, dereference to obtain the task type
2797
2798          if Is_Access_Type (Conctyp) then
2799             Conctyp := Designated_Type (Conctyp);
2800          end if;
2801
2802          --  Special case for protected subprogram calls
2803
2804          if Is_Protected_Type (Conctyp)
2805            and then Is_Subprogram (Entity (Ename))
2806          then
2807             if not Is_Eliminated (Entity (Ename)) then
2808                Build_Protected_Subprogram_Call
2809                  (N, Ename, Convert_Concurrent (Concval, Conctyp));
2810                Analyze (N);
2811             end if;
2812
2813             return;
2814          end if;
2815
2816          --  First parameter is the Task_Id value from the task value or the
2817          --  Object from the protected object value, obtained by selecting
2818          --  the _Task_Id or _Object from the result of doing an unchecked
2819          --  conversion to convert the value to the corresponding record type.
2820
2821          if Nkind (Concval) = N_Function_Call
2822            and then Is_Task_Type (Conctyp)
2823            and then Ada_Version >= Ada_05
2824          then
2825             declare
2826                Obj : constant Entity_Id :=
2827                   Make_Defining_Identifier (Loc, New_Internal_Name ('F'));
2828                Decl : Node_Id;
2829
2830             begin
2831                Decl :=
2832                  Make_Object_Declaration (Loc,
2833                    Defining_Identifier => Obj,
2834                    Object_Definition   => New_Occurrence_Of (Conctyp, Loc),
2835                    Expression          => Relocate_Node (Concval));
2836                Set_Etype (Obj, Conctyp);
2837                Decls := New_List (Decl);
2838                Rewrite (Concval, New_Occurrence_Of (Obj, Loc));
2839             end;
2840
2841          else
2842             Decls := New_List;
2843          end if;
2844
2845          Parm1 := Concurrent_Ref (Concval);
2846
2847          --  Second parameter is the entry index, computed by the routine
2848          --  provided for this purpose. The value of this expression is
2849          --  assigned to an intermediate variable to assure that any entry
2850          --  family index expressions are evaluated before the entry
2851          --  parameters.
2852
2853          if Abort_Allowed
2854            or else Restriction_Active (No_Entry_Queue) = False
2855            or else not Is_Protected_Type (Conctyp)
2856            or else Number_Entries (Conctyp) > 1
2857            or else (Has_Attach_Handler (Conctyp)
2858                      and then not Restricted_Profile)
2859          then
2860             X := Make_Defining_Identifier (Loc, Name_uX);
2861
2862             Xdecl :=
2863               Make_Object_Declaration (Loc,
2864                 Defining_Identifier => X,
2865                 Object_Definition =>
2866                   New_Reference_To (RTE (RE_Task_Entry_Index), Loc),
2867                 Expression => Actual_Index_Expression (
2868                   Loc, Entity (Ename), Index, Concval));
2869
2870             Append_To (Decls, Xdecl);
2871             Parm2 := New_Reference_To (X, Loc);
2872
2873          else
2874             Xdecl := Empty;
2875             Parm2 := Empty;
2876          end if;
2877
2878          --  The third parameter is the packaged parameters. If there are
2879          --  none, then it is just the null address, since nothing is passed.
2880
2881          if No (Parms) then
2882             Parm3 := New_Reference_To (RTE (RE_Null_Address), Loc);
2883             P := Empty;
2884
2885          --  Case of parameters present, where third argument is the address
2886          --  of a packaged record containing the required parameter values.
2887
2888          else
2889             --  First build a list of parameter values, which are references to
2890             --  objects of the parameter types.
2891
2892             Plist := New_List;
2893
2894             Actual := First_Actual (N);
2895             Formal := First_Formal (Ent);
2896
2897             while Present (Actual) loop
2898
2899                --  If it is a by_copy_type, copy it to a new variable. The
2900                --  packaged record has a field that points to this variable.
2901
2902                if Is_By_Copy_Type (Etype (Actual)) then
2903                   N_Node :=
2904                     Make_Object_Declaration (Loc,
2905                       Defining_Identifier =>
2906                         Make_Defining_Identifier (Loc,
2907                           Chars => New_Internal_Name ('J')),
2908                       Aliased_Present => True,
2909                       Object_Definition =>
2910                         New_Reference_To (Etype (Formal), Loc));
2911
2912                   --  Mark the object as not needing initialization since the
2913                   --  initialization is performed separately, avoiding errors
2914                   --  on cases such as formals of null-excluding access types.
2915
2916                   Set_No_Initialization (N_Node);
2917
2918                   --  We must make an assignment statement separate for the
2919                   --  case of limited type. We cannot assign it unless the
2920                   --  Assignment_OK flag is set first. An out formal of an
2921                   --  access type must also be initialized from the actual,
2922                   --  as stated in RM 6.4.1 (13).
2923
2924                   if Ekind (Formal) /= E_Out_Parameter
2925                     or else Is_Access_Type (Etype (Formal))
2926                   then
2927                      N_Var :=
2928                        New_Reference_To (Defining_Identifier (N_Node), Loc);
2929                      Set_Assignment_OK (N_Var);
2930                      Append_To (Stats,
2931                        Make_Assignment_Statement (Loc,
2932                          Name => N_Var,
2933                          Expression => Relocate_Node (Actual)));
2934                   end if;
2935
2936                   Append (N_Node, Decls);
2937
2938                   Append_To (Plist,
2939                     Make_Attribute_Reference (Loc,
2940                       Attribute_Name => Name_Unchecked_Access,
2941                     Prefix =>
2942                       New_Reference_To (Defining_Identifier (N_Node), Loc)));
2943                else
2944                   --  Interface class-wide formal
2945
2946                   if Ada_Version >= Ada_05
2947                     and then Ekind (Etype (Formal)) = E_Class_Wide_Type
2948                     and then Is_Interface (Etype (Formal))
2949                   then
2950                      Iface_Typ := Etype (Etype (Formal));
2951
2952                      --  Generate:
2953                      --    formal_iface_type! (actual.iface_tag)'reference
2954
2955                      Iface_Tag :=
2956                        Find_Interface_Tag (Etype (Actual), Iface_Typ);
2957                      pragma Assert (Present (Iface_Tag));
2958
2959                      Append_To (Plist,
2960                        Make_Reference (Loc,
2961                          Unchecked_Convert_To (Iface_Typ,
2962                            Make_Selected_Component (Loc,
2963                              Prefix =>
2964                                Relocate_Node (Actual),
2965                              Selector_Name =>
2966                                New_Reference_To (Iface_Tag, Loc)))));
2967                   else
2968                      --  Generate:
2969                      --    actual'reference
2970
2971                      Append_To (Plist,
2972                        Make_Reference (Loc, Relocate_Node (Actual)));
2973                   end if;
2974                end if;
2975
2976                Next_Actual (Actual);
2977                Next_Formal_With_Extras (Formal);
2978             end loop;
2979
2980             --  Now build the declaration of parameters initialized with the
2981             --  aggregate containing this constructed parameter list.
2982
2983             P := Make_Defining_Identifier (Loc, Name_uP);
2984
2985             Pdecl :=
2986               Make_Object_Declaration (Loc,
2987                 Defining_Identifier => P,
2988                 Object_Definition =>
2989                   New_Reference_To (Designated_Type (Ent_Acc), Loc),
2990                 Expression =>
2991                   Make_Aggregate (Loc, Expressions => Plist));
2992
2993             Parm3 :=
2994               Make_Attribute_Reference (Loc,
2995                 Prefix => New_Reference_To (P, Loc),
2996                 Attribute_Name => Name_Address);
2997
2998             Append (Pdecl, Decls);
2999          end if;
3000
3001          --  Now we can create the call, case of protected type
3002
3003          if Is_Protected_Type (Conctyp) then
3004             case Corresponding_Runtime_Package (Conctyp) is
3005                when System_Tasking_Protected_Objects_Entries =>
3006
3007                   --  Change the type of the index declaration
3008
3009                   Set_Object_Definition (Xdecl,
3010                     New_Reference_To (RTE (RE_Protected_Entry_Index), Loc));
3011
3012                   --  Some additional declarations for protected entry calls
3013
3014                   if No (Decls) then
3015                      Decls := New_List;
3016                   end if;
3017
3018                   --  Bnn : Communications_Block;
3019
3020                   Comm_Name :=
3021                     Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
3022
3023                   Append_To (Decls,
3024                     Make_Object_Declaration (Loc,
3025                       Defining_Identifier => Comm_Name,
3026                       Object_Definition =>
3027                         New_Reference_To (RTE (RE_Communication_Block), Loc)));
3028
3029                   --  Some additional statements for protected entry calls
3030
3031                   --     Protected_Entry_Call (
3032                   --       Object => po._object'Access,
3033                   --       E => <entry index>;
3034                   --       Uninterpreted_Data => P'Address;
3035                   --       Mode => Simple_Call;
3036                   --       Block => Bnn);
3037
3038                   Call :=
3039                     Make_Procedure_Call_Statement (Loc,
3040                       Name =>
3041                         New_Reference_To (RTE (RE_Protected_Entry_Call), Loc),
3042
3043                       Parameter_Associations => New_List (
3044                         Make_Attribute_Reference (Loc,
3045                           Attribute_Name => Name_Unchecked_Access,
3046                           Prefix         => Parm1),
3047                         Parm2,
3048                         Parm3,
3049                         New_Reference_To (RTE (RE_Simple_Call), Loc),
3050                         New_Occurrence_Of (Comm_Name, Loc)));
3051
3052                when System_Tasking_Protected_Objects_Single_Entry =>
3053                   --     Protected_Single_Entry_Call (
3054                   --       Object => po._object'Access,
3055                   --       Uninterpreted_Data => P'Address;
3056                   --       Mode => Simple_Call);
3057
3058                   Call :=
3059                     Make_Procedure_Call_Statement (Loc,
3060                       Name => New_Reference_To (
3061                         RTE (RE_Protected_Single_Entry_Call), Loc),
3062
3063                       Parameter_Associations => New_List (
3064                         Make_Attribute_Reference (Loc,
3065                           Attribute_Name => Name_Unchecked_Access,
3066                           Prefix         => Parm1),
3067                         Parm3,
3068                         New_Reference_To (RTE (RE_Simple_Call), Loc)));
3069
3070                when others =>
3071                   raise Program_Error;
3072             end case;
3073
3074          --  Case of task type
3075
3076          else
3077             Call :=
3078               Make_Procedure_Call_Statement (Loc,
3079                 Name => New_Reference_To (RTE (RE_Call_Simple), Loc),
3080                 Parameter_Associations => New_List (Parm1, Parm2, Parm3));
3081
3082          end if;
3083
3084          Append_To (Stats, Call);
3085
3086          --  If there are out or in/out parameters by copy add assignment
3087          --  statements for the result values.
3088
3089          if Present (Parms) then
3090             Actual := First_Actual (N);
3091             Formal := First_Formal (Ent);
3092
3093             Set_Assignment_OK (Actual);
3094             while Present (Actual) loop
3095                if Is_By_Copy_Type (Etype (Actual))
3096                  and then Ekind (Formal) /= E_In_Parameter
3097                then
3098                   N_Node :=
3099                     Make_Assignment_Statement (Loc,
3100                       Name => New_Copy (Actual),
3101                       Expression =>
3102                         Make_Explicit_Dereference (Loc,
3103                           Make_Selected_Component (Loc,
3104                             Prefix => New_Reference_To (P, Loc),
3105                             Selector_Name =>
3106                               Make_Identifier (Loc, Chars (Formal)))));
3107
3108                   --  In all cases (including limited private types) we want
3109                   --  the assignment to be valid.
3110
3111                   Set_Assignment_OK (Name (N_Node));
3112
3113                   --  If the call is the triggering alternative in an
3114                   --  asynchronous select, or the entry_call alternative of a
3115                   --  conditional entry call, the assignments for in-out
3116                   --  parameters are incorporated into the statement list that
3117                   --  follows, so that there are executed only if the entry
3118                   --  call succeeds.
3119
3120                   if (Nkind (Parent (N)) = N_Triggering_Alternative
3121                        and then N = Triggering_Statement (Parent (N)))
3122                     or else
3123                      (Nkind (Parent (N)) = N_Entry_Call_Alternative
3124                        and then N = Entry_Call_Statement (Parent (N)))
3125                   then
3126                      if No (Statements (Parent (N))) then
3127                         Set_Statements (Parent (N), New_List);
3128                      end if;
3129
3130                      Prepend (N_Node, Statements (Parent (N)));
3131
3132                   else
3133                      Insert_After (Call, N_Node);
3134                   end if;
3135                end if;
3136
3137                Next_Actual (Actual);
3138                Next_Formal_With_Extras (Formal);
3139             end loop;
3140          end if;
3141
3142          --  Finally, create block and analyze it
3143
3144          Rewrite (N,
3145            Make_Block_Statement (Loc,
3146              Declarations => Decls,
3147              Handled_Statement_Sequence =>
3148                Make_Handled_Sequence_Of_Statements (Loc,
3149                  Statements => Stats)));
3150
3151          Analyze (N);
3152       end;
3153    end Build_Simple_Entry_Call;
3154
3155    --------------------------------
3156    -- Build_Task_Activation_Call --
3157    --------------------------------
3158
3159    procedure Build_Task_Activation_Call (N : Node_Id) is
3160       Loc   : constant Source_Ptr := Sloc (N);
3161       Chain : Entity_Id;
3162       Call  : Node_Id;
3163       Name  : Node_Id;
3164       P     : Node_Id;
3165
3166    begin
3167       --  Get the activation chain entity. Except in the case of a package
3168       --  body, this is in the node that was passed. For a package body, we
3169       --  have to find the corresponding package declaration node.
3170
3171       if Nkind (N) = N_Package_Body then
3172          P := Corresponding_Spec (N);
3173          loop
3174             P := Parent (P);
3175             exit when Nkind (P) = N_Package_Declaration;
3176          end loop;
3177
3178          Chain := Activation_Chain_Entity (P);
3179
3180       else
3181          Chain := Activation_Chain_Entity (N);
3182       end if;
3183
3184       if Present (Chain) then
3185          if Restricted_Profile then
3186             Name := New_Reference_To (RTE (RE_Activate_Restricted_Tasks), Loc);
3187          else
3188             Name := New_Reference_To (RTE (RE_Activate_Tasks), Loc);
3189          end if;
3190
3191          Call :=
3192            Make_Procedure_Call_Statement (Loc,
3193              Name => Name,
3194              Parameter_Associations =>
3195                New_List (Make_Attribute_Reference (Loc,
3196                  Prefix => New_Occurrence_Of (Chain, Loc),
3197                  Attribute_Name => Name_Unchecked_Access)));
3198
3199          if Nkind (N) = N_Package_Declaration then
3200             if Present (Corresponding_Body (N)) then
3201                null;
3202
3203             elsif Present (Private_Declarations (Specification (N))) then
3204                Append (Call, Private_Declarations (Specification (N)));
3205
3206             else
3207                Append (Call, Visible_Declarations (Specification (N)));
3208             end if;
3209
3210          else
3211             if Present (Handled_Statement_Sequence (N)) then
3212
3213                --  The call goes at the start of the statement sequence
3214                --  after the start of exception range label if one is present.
3215
3216                declare
3217                   Stm : Node_Id;
3218
3219                begin
3220                   Stm := First (Statements (Handled_Statement_Sequence (N)));
3221
3222                   --  A special case, skip exception range label if one is
3223                   --  present (from front end zcx processing).
3224
3225                   if Nkind (Stm) = N_Label and then Exception_Junk (Stm) then
3226                      Next (Stm);
3227                   end if;
3228
3229                   --  Another special case, if the first statement is a block
3230                   --  from optimization of a local raise to a goto, then the
3231                   --  call goes inside this block.
3232
3233                   if Nkind (Stm) = N_Block_Statement
3234                     and then Exception_Junk (Stm)
3235                   then
3236                      Stm :=
3237                        First (Statements (Handled_Statement_Sequence (Stm)));
3238                   end if;
3239
3240                   --  Insertion point is after any exception label pushes,
3241                   --  since we want it covered by any local handlers.
3242
3243                   while Nkind (Stm) in N_Push_xxx_Label loop
3244                      Next (Stm);
3245                   end loop;
3246
3247                   --  Now we have the proper insertion point
3248
3249                   Insert_Before (Stm, Call);
3250                end;
3251
3252             else
3253                Set_Handled_Statement_Sequence (N,
3254                   Make_Handled_Sequence_Of_Statements (Loc,
3255                      Statements => New_List (Call)));
3256             end if;
3257          end if;
3258
3259          Analyze (Call);
3260          Check_Task_Activation (N);
3261       end if;
3262    end Build_Task_Activation_Call;
3263
3264    -------------------------------
3265    -- Build_Task_Allocate_Block --
3266    -------------------------------
3267
3268    procedure Build_Task_Allocate_Block
3269      (Actions : List_Id;
3270       N       : Node_Id;
3271       Args    : List_Id)
3272    is
3273       T      : constant Entity_Id  := Entity (Expression (N));
3274       Init   : constant Entity_Id  := Base_Init_Proc (T);
3275       Loc    : constant Source_Ptr := Sloc (N);
3276       Chain  : constant Entity_Id  :=
3277                  Make_Defining_Identifier (Loc, Name_uChain);
3278
3279       Blkent : Entity_Id;
3280       Block  : Node_Id;
3281
3282    begin
3283       Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3284
3285       Block :=
3286         Make_Block_Statement (Loc,
3287           Identifier => New_Reference_To (Blkent, Loc),
3288           Declarations => New_List (
3289
3290             --  _Chain  : Activation_Chain;
3291
3292             Make_Object_Declaration (Loc,
3293               Defining_Identifier => Chain,
3294               Aliased_Present => True,
3295               Object_Definition   =>
3296                 New_Reference_To (RTE (RE_Activation_Chain), Loc))),
3297
3298           Handled_Statement_Sequence =>
3299             Make_Handled_Sequence_Of_Statements (Loc,
3300
3301               Statements => New_List (
3302
3303                --  Init (Args);
3304
3305                 Make_Procedure_Call_Statement (Loc,
3306                   Name => New_Reference_To (Init, Loc),
3307                   Parameter_Associations => Args),
3308
3309                --  Activate_Tasks (_Chain);
3310
3311                 Make_Procedure_Call_Statement (Loc,
3312                   Name => New_Reference_To (RTE (RE_Activate_Tasks), Loc),
3313                   Parameter_Associations => New_List (
3314                     Make_Attribute_Reference (Loc,
3315                       Prefix => New_Reference_To (Chain, Loc),
3316                       Attribute_Name => Name_Unchecked_Access))))),
3317
3318           Has_Created_Identifier => True,
3319           Is_Task_Allocation_Block => True);
3320
3321       Append_To (Actions,
3322         Make_Implicit_Label_Declaration (Loc,
3323           Defining_Identifier => Blkent,
3324           Label_Construct     => Block));
3325
3326       Append_To (Actions, Block);
3327
3328       Set_Activation_Chain_Entity (Block, Chain);
3329    end Build_Task_Allocate_Block;
3330
3331    -----------------------------------------------
3332    -- Build_Task_Allocate_Block_With_Init_Stmts --
3333    -----------------------------------------------
3334
3335    procedure Build_Task_Allocate_Block_With_Init_Stmts
3336      (Actions    : List_Id;
3337       N          : Node_Id;
3338       Init_Stmts : List_Id)
3339    is
3340       Loc    : constant Source_Ptr := Sloc (N);
3341       Chain  : constant Entity_Id  :=
3342                  Make_Defining_Identifier (Loc, Name_uChain);
3343       Blkent : Entity_Id;
3344       Block  : Node_Id;
3345
3346    begin
3347       Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
3348
3349       Append_To (Init_Stmts,
3350         Make_Procedure_Call_Statement (Loc,
3351           Name => New_Reference_To (RTE (RE_Activate_Tasks), Loc),
3352           Parameter_Associations => New_List (
3353             Make_Attribute_Reference (Loc,
3354               Prefix => New_Reference_To (Chain, Loc),
3355               Attribute_Name => Name_Unchecked_Access))));
3356
3357       Block :=
3358         Make_Block_Statement (Loc,
3359           Identifier => New_Reference_To (Blkent, Loc),
3360           Declarations => New_List (
3361
3362             --  _Chain  : Activation_Chain;
3363
3364             Make_Object_Declaration (Loc,
3365               Defining_Identifier => Chain,
3366               Aliased_Present => True,
3367               Object_Definition   =>
3368                 New_Reference_To (RTE (RE_Activation_Chain), Loc))),
3369
3370           Handled_Statement_Sequence =>
3371             Make_Handled_Sequence_Of_Statements (Loc, Init_Stmts),
3372
3373           Has_Created_Identifier => True,
3374           Is_Task_Allocation_Block => True);
3375
3376       Append_To (Actions,
3377         Make_Implicit_Label_Declaration (Loc,
3378           Defining_Identifier => Blkent,
3379           Label_Construct     => Block));
3380
3381       Append_To (Actions, Block);
3382
3383       Set_Activation_Chain_Entity (Block, Chain);
3384    end Build_Task_Allocate_Block_With_Init_Stmts;
3385
3386    -----------------------------------
3387    -- Build_Task_Proc_Specification --
3388    -----------------------------------
3389
3390    function Build_Task_Proc_Specification (T : Entity_Id) return Node_Id is
3391       Loc     : constant Source_Ptr := Sloc (T);
3392       Spec_Id : Entity_Id;
3393
3394    begin
3395       Spec_Id :=
3396         Make_Defining_Identifier (Loc,
3397           Chars => New_External_Name (Chars (T), 'B'));
3398       Set_Is_Internal (Spec_Id);
3399
3400       --  Associate the procedure with the task, if this is the declaration
3401       --  (and not the body) of the procedure.
3402
3403       if No (Task_Body_Procedure (T)) then
3404          Set_Task_Body_Procedure (T, Spec_Id);
3405       end if;
3406
3407       return
3408         Make_Procedure_Specification (Loc,
3409           Defining_Unit_Name       => Spec_Id,
3410           Parameter_Specifications => New_List (
3411             Make_Parameter_Specification (Loc,
3412               Defining_Identifier =>
3413                 Make_Defining_Identifier (Loc, Name_uTask),
3414               Parameter_Type      =>
3415                 Make_Access_Definition (Loc,
3416                   Subtype_Mark =>
3417                     New_Reference_To (Corresponding_Record_Type (T), Loc)))));
3418    end Build_Task_Proc_Specification;
3419
3420    ---------------------------------------
3421    -- Build_Unprotected_Subprogram_Body --
3422    ---------------------------------------
3423
3424    function Build_Unprotected_Subprogram_Body
3425      (N   : Node_Id;
3426       Pid : Node_Id) return Node_Id
3427    is
3428       Decls : constant List_Id := Declarations (N);
3429
3430    begin
3431       --  Add renamings for the Protection object, discriminals, privals and
3432       --  the entry indix constant for use by debugger.
3433
3434       Debug_Private_Data_Declarations (Decls);
3435
3436       --  Make an unprotected version of the subprogram for use within the same
3437       --  object, with a new name and an additional parameter representing the
3438       --  object.
3439
3440       return
3441         Make_Subprogram_Body (Sloc (N),
3442           Specification              =>
3443             Build_Protected_Sub_Specification (N, Pid, Unprotected_Mode),
3444           Declarations               => Decls,
3445           Handled_Statement_Sequence => Handled_Statement_Sequence (N));
3446    end Build_Unprotected_Subprogram_Body;
3447
3448    ----------------------------
3449    -- Collect_Entry_Families --
3450    ----------------------------
3451
3452    procedure Collect_Entry_Families
3453      (Loc          : Source_Ptr;
3454       Cdecls       : List_Id;
3455       Current_Node : in out Node_Id;
3456       Conctyp      : Entity_Id)
3457    is
3458       Efam      : Entity_Id;
3459       Efam_Decl : Node_Id;
3460       Efam_Type : Entity_Id;
3461
3462    begin
3463       Efam := First_Entity (Conctyp);
3464       while Present (Efam) loop
3465          if Ekind (Efam) = E_Entry_Family then
3466             Efam_Type :=
3467               Make_Defining_Identifier (Loc,
3468                 Chars => New_Internal_Name ('F'));
3469
3470             declare
3471                Bas : Entity_Id :=
3472                        Base_Type
3473                         (Etype (Discrete_Subtype_Definition (Parent (Efam))));
3474
3475                Bas_Decl : Node_Id := Empty;
3476                Lo, Hi   : Node_Id;
3477
3478             begin
3479                Get_Index_Bounds
3480                  (Discrete_Subtype_Definition (Parent (Efam)), Lo, Hi);
3481
3482                if Is_Potentially_Large_Family (Bas, Conctyp, Lo, Hi) then
3483                   Bas :=
3484                     Make_Defining_Identifier (Loc,
3485                       Chars => New_Internal_Name ('B'));
3486
3487                   Bas_Decl :=
3488                     Make_Subtype_Declaration (Loc,
3489                        Defining_Identifier => Bas,
3490                        Subtype_Indication  =>
3491                          Make_Subtype_Indication (Loc,
3492                            Subtype_Mark =>
3493                              New_Occurrence_Of (Standard_Integer, Loc),
3494                            Constraint   =>
3495                              Make_Range_Constraint (Loc,
3496                                Range_Expression => Make_Range (Loc,
3497                                  Make_Integer_Literal
3498                                    (Loc, -Entry_Family_Bound),
3499                                  Make_Integer_Literal
3500                                    (Loc, Entry_Family_Bound - 1)))));
3501
3502                   Insert_After (Current_Node, Bas_Decl);
3503                   Current_Node := Bas_Decl;
3504                   Analyze (Bas_Decl);
3505                end if;
3506
3507                Efam_Decl :=
3508                  Make_Full_Type_Declaration (Loc,
3509                    Defining_Identifier => Efam_Type,
3510                    Type_Definition =>
3511                      Make_Unconstrained_Array_Definition (Loc,
3512                        Subtype_Marks =>
3513                          (New_List (New_Occurrence_Of (Bas, Loc))),
3514
3515                     Component_Definition =>
3516                       Make_Component_Definition (Loc,
3517                         Aliased_Present    => False,
3518                         Subtype_Indication =>
3519                           New_Reference_To (Standard_Character, Loc))));
3520             end;
3521
3522             Insert_After (Current_Node, Efam_Decl);
3523             Current_Node := Efam_Decl;
3524             Analyze (Efam_Decl);
3525
3526             Append_To (Cdecls,
3527               Make_Component_Declaration (Loc,
3528                 Defining_Identifier =>
3529                   Make_Defining_Identifier (Loc, Chars (Efam)),
3530
3531                 Component_Definition =>
3532                   Make_Component_Definition (Loc,
3533                     Aliased_Present    => False,
3534                     Subtype_Indication =>
3535                       Make_Subtype_Indication (Loc,
3536                         Subtype_Mark =>
3537                           New_Occurrence_Of (Efam_Type, Loc),
3538
3539                         Constraint  =>
3540                           Make_Index_Or_Discriminant_Constraint (Loc,
3541                             Constraints => New_List (
3542                               New_Occurrence_Of
3543                                 (Etype (Discrete_Subtype_Definition
3544                                   (Parent (Efam))), Loc)))))));
3545
3546          end if;
3547
3548          Next_Entity (Efam);
3549       end loop;
3550    end Collect_Entry_Families;
3551
3552    -----------------------
3553    -- Concurrent_Object --
3554    -----------------------
3555
3556    function Concurrent_Object
3557      (Spec_Id  : Entity_Id;
3558       Conc_Typ : Entity_Id) return Entity_Id
3559    is
3560    begin
3561       --  Parameter _O or _object
3562
3563       if Is_Protected_Type (Conc_Typ) then
3564          return First_Formal (Protected_Body_Subprogram (Spec_Id));
3565
3566       --  Parameter _task
3567
3568       else
3569          pragma Assert (Is_Task_Type (Conc_Typ));
3570          return First_Formal (Task_Body_Procedure (Conc_Typ));
3571       end if;
3572    end Concurrent_Object;
3573
3574    ----------------------
3575    -- Copy_Result_Type --
3576    ----------------------
3577
3578    function Copy_Result_Type (Res : Node_Id) return Node_Id is
3579       New_Res  : constant Node_Id := New_Copy_Tree (Res);
3580       Par_Spec : Node_Id;
3581       Formal   : Entity_Id;
3582
3583    begin
3584       --  If the result type is an access_to_subprogram, we must create
3585       --  new entities for its spec.
3586
3587       if Nkind (New_Res) = N_Access_Definition
3588         and then Present (Access_To_Subprogram_Definition (New_Res))
3589       then
3590          --  Provide new entities for the formals
3591
3592          Par_Spec := First (Parameter_Specifications
3593                               (Access_To_Subprogram_Definition (New_Res)));
3594          while Present (Par_Spec) loop
3595             Formal := Defining_Identifier (Par_Spec);
3596             Set_Defining_Identifier (Par_Spec,
3597               Make_Defining_Identifier (Sloc (Formal), Chars (Formal)));
3598             Next (Par_Spec);
3599          end loop;
3600       end if;
3601
3602       return New_Res;
3603    end Copy_Result_Type;
3604
3605    --------------------
3606    -- Concurrent_Ref --
3607    --------------------
3608
3609    --  The expression returned for a reference to a concurrent object has the
3610    --  form:
3611
3612    --    taskV!(name)._Task_Id
3613
3614    --  for a task, and
3615
3616    --    objectV!(name)._Object
3617
3618    --  for a protected object. For the case of an access to a concurrent
3619    --  object, there is an extra explicit dereference:
3620
3621    --    taskV!(name.all)._Task_Id
3622    --    objectV!(name.all)._Object
3623
3624    --  here taskV and objectV are the types for the associated records, which
3625    --  contain the required _Task_Id and _Object fields for tasks and protected
3626    --  objects, respectively.
3627
3628    --  For the case of a task type name, the expression is
3629
3630    --    Self;
3631
3632    --  i.e. a call to the Self function which returns precisely this Task_Id
3633
3634    --  For the case of a protected type name, the expression is
3635
3636    --    objectR
3637
3638    --  which is a renaming of the _object field of the current object object
3639    --  record, passed into protected operations as a parameter.
3640
3641    function Concurrent_Ref (N : Node_Id) return Node_Id is
3642       Loc  : constant Source_Ptr := Sloc (N);
3643       Ntyp : constant Entity_Id  := Etype (N);
3644       Dtyp : Entity_Id;
3645       Sel  : Name_Id;
3646
3647       function Is_Current_Task (T : Entity_Id) return Boolean;
3648       --  Check whether the reference is to the immediately enclosing task
3649       --  type, or to an outer one (rare but legal).
3650
3651       ---------------------
3652       -- Is_Current_Task --
3653       ---------------------
3654
3655       function Is_Current_Task (T : Entity_Id) return Boolean is
3656          Scop : Entity_Id;
3657
3658       begin
3659          Scop := Current_Scope;
3660          while Present (Scop)
3661            and then Scop /= Standard_Standard
3662          loop
3663
3664             if Scop = T then
3665                return True;
3666
3667             elsif Is_Task_Type (Scop) then
3668                return False;
3669
3670             --  If this is a procedure nested within the task type, we must
3671             --  assume that it can be called from an inner task, and therefore
3672             --  cannot treat it as a local reference.
3673
3674             elsif Is_Overloadable (Scop)
3675               and then In_Open_Scopes (T)
3676             then
3677                return False;
3678
3679             else
3680                Scop := Scope (Scop);
3681             end if;
3682          end loop;
3683
3684          --  We know that we are within the task body, so should have found it
3685          --  in scope.
3686
3687          raise Program_Error;
3688       end Is_Current_Task;
3689
3690    --  Start of processing for Concurrent_Ref
3691
3692    begin
3693       if Is_Access_Type (Ntyp) then
3694          Dtyp := Designated_Type (Ntyp);
3695
3696          if Is_Protected_Type (Dtyp) then
3697             Sel := Name_uObject;
3698          else
3699             Sel := Name_uTask_Id;
3700          end if;
3701
3702          return
3703            Make_Selected_Component (Loc,
3704              Prefix =>
3705                Unchecked_Convert_To (Corresponding_Record_Type (Dtyp),
3706                  Make_Explicit_Dereference (Loc, N)),
3707              Selector_Name => Make_Identifier (Loc, Sel));
3708
3709       elsif Is_Entity_Name (N)
3710         and then Is_Concurrent_Type (Entity (N))
3711       then
3712          if Is_Task_Type (Entity (N)) then
3713
3714             if Is_Current_Task (Entity (N)) then
3715                return
3716                  Make_Function_Call (Loc,
3717                    Name => New_Reference_To (RTE (RE_Self), Loc));
3718
3719             else
3720                declare
3721                   Decl   : Node_Id;
3722                   T_Self : constant Entity_Id :=
3723                              Make_Defining_Identifier (Loc,
3724                                Chars => New_Internal_Name ('T'));
3725                   T_Body : constant Node_Id :=
3726                              Parent (Corresponding_Body (Parent (Entity (N))));
3727
3728                begin
3729                   Decl := Make_Object_Declaration (Loc,
3730                      Defining_Identifier => T_Self,
3731                      Object_Definition =>
3732                        New_Occurrence_Of (RTE (RO_ST_Task_Id), Loc),
3733                      Expression =>
3734                        Make_Function_Call (Loc,
3735                          Name => New_Reference_To (RTE (RE_Self), Loc)));
3736                   Prepend (Decl, Declarations (T_Body));
3737                   Analyze (Decl);
3738                   Set_Scope (T_Self, Entity (N));
3739                   return New_Occurrence_Of (T_Self,  Loc);
3740                end;
3741             end if;
3742
3743          else
3744             pragma Assert (Is_Protected_Type (Entity (N)));
3745
3746             return
3747               New_Reference_To (Find_Protection_Object (Current_Scope), Loc);
3748          end if;
3749
3750       else
3751          if Is_Protected_Type (Ntyp) then
3752             Sel := Name_uObject;
3753
3754          elsif Is_Task_Type (Ntyp) then
3755             Sel := Name_uTask_Id;
3756
3757          else
3758             raise Program_Error;
3759          end if;
3760
3761          return
3762            Make_Selected_Component (Loc,
3763              Prefix =>
3764                Unchecked_Convert_To (Corresponding_Record_Type (Ntyp),
3765                  New_Copy_Tree (N)),
3766              Selector_Name => Make_Identifier (Loc, Sel));
3767       end if;
3768    end Concurrent_Ref;
3769
3770    ------------------------
3771    -- Convert_Concurrent --
3772    ------------------------
3773
3774    function Convert_Concurrent
3775      (N   : Node_Id;
3776       Typ : Entity_Id) return Node_Id
3777    is
3778    begin
3779       if not Is_Concurrent_Type (Typ) then
3780          return N;
3781       else
3782          return
3783            Unchecked_Convert_To (Corresponding_Record_Type (Typ),
3784              New_Copy_Tree (N));
3785       end if;
3786    end Convert_Concurrent;
3787
3788    -------------------------------------
3789    -- Debug_Private_Data_Declarations --
3790    -------------------------------------
3791
3792    procedure Debug_Private_Data_Declarations (Decls : List_Id) is
3793       Debug_Nod : Node_Id;
3794       Decl      : Node_Id;
3795
3796    begin
3797       Decl := First (Decls);
3798       while Present (Decl)
3799         and then not Comes_From_Source (Decl)
3800       loop
3801          --  Declaration for concurrent entity _object and its access type,
3802          --  along with the entry index subtype:
3803          --    type prot_typVP is access prot_typV;
3804          --    _object : prot_typVP := prot_typV (_O);
3805          --    subtype Jnn is <Type of Index> range Low .. High;
3806
3807          if Nkind_In (Decl, N_Full_Type_Declaration, N_Object_Declaration) then
3808             Set_Debug_Info_Needed (Defining_Identifier (Decl));
3809
3810          --  Declaration for the Protection object, discriminals, privals and
3811          --  entry index constant:
3812          --    conc_typR   : protection_typ renames _object._object;
3813          --    discr_nameD : discr_typ renames _object.discr_name;
3814          --    discr_nameD : discr_typ renames _task.discr_name;
3815          --    prival_name : comp_typ  renames _object.comp_name;
3816          --    J : constant Jnn :=
3817          --          Jnn'Val (_E - <Index expression> + Jnn'Pos (Jnn'First));
3818
3819          elsif Nkind (Decl) = N_Object_Renaming_Declaration then
3820             Set_Debug_Info_Needed (Defining_Identifier (Decl));
3821             Debug_Nod := Debug_Renaming_Declaration (Decl);
3822
3823             if Present (Debug_Nod) then
3824                Insert_After (Decl, Debug_Nod);
3825             end if;
3826          end if;
3827
3828          Next (Decl);
3829       end loop;
3830    end Debug_Private_Data_Declarations;
3831
3832    ----------------------------
3833    -- Entry_Index_Expression --
3834    ----------------------------
3835
3836    function Entry_Index_Expression
3837      (Sloc  : Source_Ptr;
3838       Ent   : Entity_Id;
3839       Index : Node_Id;
3840       Ttyp  : Entity_Id) return Node_Id
3841    is
3842       Expr : Node_Id;
3843       Num  : Node_Id;
3844       Lo   : Node_Id;
3845       Hi   : Node_Id;
3846       Prev : Entity_Id;
3847       S    : Node_Id;
3848
3849    begin
3850       --  The queues of entries and entry families appear in textual order in
3851       --  the associated record. The entry index is computed as the sum of the
3852       --  number of queues for all entries that precede the designated one, to
3853       --  which is added the index expression, if this expression denotes a
3854       --  member of a family.
3855
3856       --  The following is a place holder for the count of simple entries
3857
3858       Num := Make_Integer_Literal (Sloc, 1);
3859
3860       --  We construct an expression which is a series of addition operations.
3861       --  The first operand is the number of single entries that precede this
3862       --  one, the second operand is the index value relative to the start of
3863       --  the referenced family, and the remaining operands are the lengths of
3864       --  the entry families that precede this entry, i.e. the constructed
3865       --  expression is:
3866
3867       --    number_simple_entries +
3868       --      (s'pos (index-value) - s'pos (family'first)) + 1 +
3869       --      family'length + ...
3870
3871       --  where index-value is the given index value, and s is the index
3872       --  subtype (we have to use pos because the subtype might be an
3873       --  enumeration type preventing direct subtraction). Note that the task
3874       --  entry array is one-indexed.
3875
3876       --  The upper bound of the entry family may be a discriminant, so we
3877       --  retrieve the lower bound explicitly to compute offset, rather than
3878       --  using the index subtype which may mention a discriminant.
3879
3880       if Present (Index) then
3881          S := Etype (Discrete_Subtype_Definition (Declaration_Node (Ent)));
3882
3883          Expr :=
3884            Make_Op_Add (Sloc,
3885              Left_Opnd  => Num,
3886
3887              Right_Opnd =>
3888                Family_Offset (
3889                  Sloc,
3890                  Make_Attribute_Reference (Sloc,
3891                    Attribute_Name => Name_Pos,
3892                    Prefix => New_Reference_To (Base_Type (S), Sloc),
3893                    Expressions => New_List (Relocate_Node (Index))),
3894                  Type_Low_Bound (S),
3895                  Ttyp,
3896                  False));
3897       else
3898          Expr := Num;
3899       end if;
3900
3901       --  Now add lengths of preceding entries and entry families
3902
3903       Prev := First_Entity (Ttyp);
3904
3905       while Chars (Prev) /= Chars (Ent)
3906         or else (Ekind (Prev) /= Ekind (Ent))
3907         or else not Sem_Ch6.Type_Conformant (Ent, Prev)
3908       loop
3909          if Ekind (Prev) = E_Entry then
3910             Set_Intval (Num, Intval (Num) + 1);
3911
3912          elsif Ekind (Prev) = E_Entry_Family then
3913             S :=
3914               Etype (Discrete_Subtype_Definition (Declaration_Node (Prev)));
3915             Lo := Type_Low_Bound  (S);
3916             Hi := Type_High_Bound (S);
3917
3918             Expr :=
3919               Make_Op_Add (Sloc,
3920               Left_Opnd  => Expr,
3921               Right_Opnd => Family_Size (Sloc, Hi, Lo, Ttyp, False));
3922
3923          --  Other components are anonymous types to be ignored
3924
3925          else
3926             null;
3927          end if;
3928
3929          Next_Entity (Prev);
3930       end loop;
3931
3932       return Expr;
3933    end Entry_Index_Expression;
3934
3935    ---------------------------
3936    -- Establish_Task_Master --
3937    ---------------------------
3938
3939    procedure Establish_Task_Master (N : Node_Id) is
3940       Call : Node_Id;
3941    begin
3942       if Restriction_Active (No_Task_Hierarchy) = False then
3943          Call := Build_Runtime_Call (Sloc (N), RE_Enter_Master);
3944          Prepend_To (Declarations (N), Call);
3945          Analyze (Call);
3946       end if;
3947    end Establish_Task_Master;
3948
3949    --------------------------------
3950    -- Expand_Accept_Declarations --
3951    --------------------------------
3952
3953    --  Part of the expansion of an accept statement involves the creation of
3954    --  a declaration that can be referenced from the statement sequence of
3955    --  the accept:
3956
3957    --    Ann : Address;
3958
3959    --  This declaration is inserted immediately before the accept statement
3960    --  and it is important that it be inserted before the statements of the
3961    --  statement sequence are analyzed. Thus it would be too late to create
3962    --  this declaration in the Expand_N_Accept_Statement routine, which is
3963    --  why there is a separate procedure to be called directly from Sem_Ch9.
3964
3965    --  Ann is used to hold the address of the record containing the parameters
3966    --  (see Expand_N_Entry_Call for more details on how this record is built).
3967    --  References to the parameters do an unchecked conversion of this address
3968    --  to a pointer to the required record type, and then access the field that
3969    --  holds the value of the required parameter. The entity for the address
3970    --  variable is held as the top stack element (i.e. the last element) of the
3971    --  Accept_Address stack in the corresponding entry entity, and this element
3972    --  must be set in place  before the statements are processed.
3973
3974    --  The above description applies to the case of a stand alone accept
3975    --  statement, i.e. one not appearing as part of a select alternative.
3976
3977    --  For the case of an accept that appears as part of a select alternative
3978    --  of a selective accept, we must still create the declaration right away,
3979    --  since Ann is needed immediately, but there is an important difference:
3980
3981    --    The declaration is inserted before the selective accept, not before
3982    --    the accept statement (which is not part of a list anyway, and so would
3983    --    not accommodate inserted declarations)
3984
3985    --    We only need one address variable for the entire selective accept. So
3986    --    the Ann declaration is created only for the first accept alternative,
3987    --    and subsequent accept alternatives reference the same Ann variable.
3988
3989    --  We can distinguish the two cases by seeing whether the accept statement
3990    --  is part of a list. If not, then it must be in an accept alternative.
3991
3992    --  To expand the requeue statement, a label is provided at the end of the
3993    --  accept statement or alternative of which it is a part, so that the
3994    --  statement can be skipped after the requeue is complete. This label is
3995    --  created here rather than during the expansion of the accept statement,
3996    --  because it will be needed by any requeue statements within the accept,
3997    --  which are expanded before the accept.
3998
3999    procedure Expand_Accept_Declarations (N : Node_Id; Ent : Entity_Id) is
4000       Loc    : constant Source_Ptr := Sloc (N);
4001       Stats  : constant Node_Id    := Handled_Statement_Sequence (N);
4002       Ann    : Entity_Id           := Empty;
4003       Adecl  : Node_Id;
4004       Lab_Id : Node_Id;
4005       Lab    : Node_Id;
4006       Ldecl  : Node_Id;
4007       Ldecl2 : Node_Id;
4008
4009    begin
4010       if Expander_Active then
4011
4012          --  If we have no handled statement sequence, we may need to build
4013          --  a dummy sequence consisting of a null statement. This can be
4014          --  skipped if the trivial accept optimization is permitted.
4015
4016          if not Trivial_Accept_OK
4017            and then
4018              (No (Stats) or else Null_Statements (Statements (Stats)))
4019          then
4020             Set_Handled_Statement_Sequence (N,
4021               Make_Handled_Sequence_Of_Statements (Loc,
4022                 New_List (Make_Null_Statement (Loc))));
4023          end if;
4024
4025          --  Create and declare two labels to be placed at the end of the
4026          --  accept statement. The first label is used to allow requeues to
4027          --  skip the remainder of entry processing. The second label is used
4028          --  to skip the remainder of entry processing if the rendezvous
4029          --  completes in the middle of the accept body.
4030
4031          if Present (Handled_Statement_Sequence (N)) then
4032             Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
4033             Set_Entity (Lab_Id,
4034               Make_Defining_Identifier (Loc, Chars (Lab_Id)));
4035             Lab := Make_Label (Loc, Lab_Id);
4036             Ldecl :=
4037               Make_Implicit_Label_Declaration (Loc,
4038                 Defining_Identifier  => Entity (Lab_Id),
4039                 Label_Construct      => Lab);
4040             Append (Lab, Statements (Handled_Statement_Sequence (N)));
4041
4042             Lab_Id := Make_Identifier (Loc, New_Internal_Name ('L'));
4043             Set_Entity (Lab_Id,
4044               Make_Defining_Identifier (Loc, Chars (Lab_Id)));
4045             Lab := Make_Label (Loc, Lab_Id);
4046             Ldecl2 :=
4047               Make_Implicit_Label_Declaration (Loc,
4048                 Defining_Identifier  => Entity (Lab_Id),
4049                 Label_Construct      => Lab);
4050             Append (Lab, Statements (Handled_Statement_Sequence (N)));
4051
4052          else
4053             Ldecl := Empty;
4054             Ldecl2 := Empty;
4055          end if;
4056
4057          --  Case of stand alone accept statement
4058
4059          if Is_List_Member (N) then
4060
4061             if Present (Handled_Statement_Sequence (N)) then
4062                Ann :=
4063                  Make_Defining_Identifier (Loc,
4064                    Chars => New_Internal_Name ('A'));
4065
4066                Adecl :=
4067                  Make_Object_Declaration (Loc,
4068                    Defining_Identifier => Ann,
4069                    Object_Definition =>
4070                      New_Reference_To (RTE (RE_Address), Loc));
4071
4072                Insert_Before (N, Adecl);
4073                Analyze (Adecl);
4074
4075                Insert_Before (N, Ldecl);
4076                Analyze (Ldecl);
4077
4078                Insert_Before (N, Ldecl2);
4079                Analyze (Ldecl2);
4080             end if;
4081
4082          --  Case of accept statement which is in an accept alternative
4083
4084          else
4085             declare
4086                Acc_Alt : constant Node_Id := Parent (N);
4087                Sel_Acc : constant Node_Id := Parent (Acc_Alt);
4088                Alt     : Node_Id;
4089
4090             begin
4091                pragma Assert (Nkind (Acc_Alt) = N_Accept_Alternative);
4092                pragma Assert (Nkind (Sel_Acc) = N_Selective_Accept);
4093
4094                --  ??? Consider a single label for select statements
4095
4096                if Present (Handled_Statement_Sequence (N)) then
4097                   Prepend (Ldecl2,
4098                      Statements (Handled_Statement_Sequence (N)));
4099                   Analyze (Ldecl2);
4100
4101                   Prepend (Ldecl,
4102                      Statements (Handled_Statement_Sequence (N)));
4103                   Analyze (Ldecl);
4104                end if;
4105
4106                --  Find first accept alternative of the selective accept. A
4107                --  valid selective accept must have at least one accept in it.
4108
4109                Alt := First (Select_Alternatives (Sel_Acc));
4110
4111                while Nkind (Alt) /= N_Accept_Alternative loop
4112                   Next (Alt);
4113                end loop;
4114
4115                --  If we are the first accept statement, then we have to create
4116                --  the Ann variable, as for the stand alone case, except that
4117                --  it is inserted before the selective accept. Similarly, a
4118                --  label for requeue expansion must be declared.
4119
4120                if N = Accept_Statement (Alt) then
4121                   Ann :=
4122                     Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4123
4124                   Adecl :=
4125                     Make_Object_Declaration (Loc,
4126                       Defining_Identifier => Ann,
4127                       Object_Definition =>
4128                         New_Reference_To (RTE (RE_Address), Loc));
4129
4130                   Insert_Before (Sel_Acc, Adecl);
4131                   Analyze (Adecl);
4132
4133                --  If we are not the first accept statement, then find the Ann
4134                --  variable allocated by the first accept and use it.
4135
4136                else
4137                   Ann :=
4138                     Node (Last_Elmt (Accept_Address
4139                       (Entity (Entry_Direct_Name (Accept_Statement (Alt))))));
4140                end if;
4141             end;
4142          end if;
4143
4144          --  Merge here with Ann either created or referenced, and Adecl
4145          --  pointing to the corresponding declaration. Remaining processing
4146          --  is the same for the two cases.
4147
4148          if Present (Ann) then
4149             Append_Elmt (Ann, Accept_Address (Ent));
4150             Set_Debug_Info_Needed (Ann);
4151          end if;
4152
4153          --  Create renaming declarations for the entry formals. Each reference
4154          --  to a formal becomes a dereference of a component of the parameter
4155          --  block, whose address is held in Ann. These declarations are
4156          --  eventually inserted into the accept block, and analyzed there so
4157          --  that they have the proper scope for gdb and do not conflict with
4158          --  other declarations.
4159
4160          if Present (Parameter_Specifications (N))
4161            and then Present (Handled_Statement_Sequence (N))
4162          then
4163             declare
4164                Comp   : Entity_Id;
4165                Decl   : Node_Id;
4166                Formal : Entity_Id;
4167                New_F  : Entity_Id;
4168
4169             begin
4170                Push_Scope (Ent);
4171                Formal := First_Formal (Ent);
4172
4173                while Present (Formal) loop
4174                   Comp  := Entry_Component (Formal);
4175                   New_F :=
4176                     Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
4177
4178                   Set_Etype (New_F, Etype (Formal));
4179                   Set_Scope (New_F, Ent);
4180
4181                --  Now we set debug info needed on New_F even though it does
4182                --  not come from source, so that the debugger will get the
4183                --  right information for these generated names.
4184
4185                   Set_Debug_Info_Needed (New_F);
4186
4187                   if Ekind (Formal) = E_In_Parameter then
4188                      Set_Ekind (New_F, E_Constant);
4189                   else
4190                      Set_Ekind (New_F, E_Variable);
4191                      Set_Extra_Constrained (New_F, Extra_Constrained (Formal));
4192                   end if;
4193
4194                   Set_Actual_Subtype (New_F, Actual_Subtype (Formal));
4195
4196                   Decl :=
4197                     Make_Object_Renaming_Declaration (Loc,
4198                       Defining_Identifier =>
4199                         New_F,
4200                       Subtype_Mark =>
4201                         New_Reference_To (Etype (Formal), Loc),
4202                       Name =>
4203                         Make_Explicit_Dereference (Loc,
4204                           Make_Selected_Component (Loc,
4205                             Prefix =>
4206                               Unchecked_Convert_To (
4207                                 Entry_Parameters_Type (Ent),
4208                                 New_Reference_To (Ann, Loc)),
4209                             Selector_Name =>
4210                               New_Reference_To (Comp, Loc))));
4211
4212                   if No (Declarations (N)) then
4213                      Set_Declarations (N, New_List);
4214                   end if;
4215
4216                   Append (Decl, Declarations (N));
4217                   Set_Renamed_Object (Formal, New_F);
4218                   Next_Formal (Formal);
4219                end loop;
4220
4221                End_Scope;
4222             end;
4223          end if;
4224       end if;
4225    end Expand_Accept_Declarations;
4226
4227    ---------------------------------------------
4228    -- Expand_Access_Protected_Subprogram_Type --
4229    ---------------------------------------------
4230
4231    procedure Expand_Access_Protected_Subprogram_Type (N : Node_Id) is
4232       Loc    : constant Source_Ptr := Sloc (N);
4233       Comps  : List_Id;
4234       T      : constant Entity_Id  := Defining_Identifier (N);
4235       D_T    : constant Entity_Id  := Designated_Type (T);
4236       D_T2   : constant Entity_Id  := Make_Defining_Identifier (Loc,
4237                                         Chars => New_Internal_Name ('D'));
4238       E_T    : constant Entity_Id  := Make_Defining_Identifier (Loc,
4239                                         Chars => New_Internal_Name ('E'));
4240       P_List : constant List_Id    := Build_Protected_Spec
4241                                         (N, RTE (RE_Address), D_T, False);
4242       Decl1  : Node_Id;
4243       Decl2  : Node_Id;
4244       Def1   : Node_Id;
4245
4246    begin
4247       --  Create access to protected subprogram with full signature
4248
4249       if Nkind (Type_Definition (N)) = N_Access_Function_Definition then
4250          Def1 :=
4251            Make_Access_Function_Definition (Loc,
4252              Parameter_Specifications => P_List,
4253              Result_Definition =>
4254                Copy_Result_Type (Result_Definition (Type_Definition (N))));
4255
4256       else
4257          Def1 :=
4258            Make_Access_Procedure_Definition (Loc,
4259              Parameter_Specifications => P_List);
4260       end if;
4261
4262       Decl1 :=
4263         Make_Full_Type_Declaration (Loc,
4264           Defining_Identifier => D_T2,
4265           Type_Definition => Def1);
4266
4267       Analyze (Decl1);
4268       Insert_After (N, Decl1);
4269
4270       --  Create Equivalent_Type, a record with two components for an access to
4271       --  object and an access to subprogram.
4272
4273       Comps := New_List (
4274         Make_Component_Declaration (Loc,
4275           Defining_Identifier =>
4276             Make_Defining_Identifier (Loc, New_Internal_Name ('P')),
4277           Component_Definition =>
4278             Make_Component_Definition (Loc,
4279               Aliased_Present => False,
4280               Subtype_Indication =>
4281                 New_Occurrence_Of (RTE (RE_Address), Loc))),
4282
4283         Make_Component_Declaration (Loc,
4284           Defining_Identifier =>
4285             Make_Defining_Identifier (Loc, New_Internal_Name ('S')),
4286           Component_Definition =>
4287             Make_Component_Definition (Loc,
4288               Aliased_Present => False,
4289               Subtype_Indication => New_Occurrence_Of (D_T2, Loc))));
4290
4291       Decl2 :=
4292         Make_Full_Type_Declaration (Loc,
4293           Defining_Identifier => E_T,
4294           Type_Definition =>
4295             Make_Record_Definition (Loc,
4296               Component_List =>
4297                 Make_Component_List (Loc,
4298                   Component_Items => Comps)));
4299
4300       Analyze (Decl2);
4301       Insert_After (Decl1, Decl2);
4302       Set_Equivalent_Type (T, E_T);
4303    end Expand_Access_Protected_Subprogram_Type;
4304
4305    --------------------------
4306    -- Expand_Entry_Barrier --
4307    --------------------------
4308
4309    procedure Expand_Entry_Barrier (N : Node_Id; Ent : Entity_Id) is
4310       Cond      : constant Node_Id   :=
4311                     Condition (Entry_Body_Formal_Part (N));
4312       Prot      : constant Entity_Id := Scope (Ent);
4313       Spec_Decl : constant Node_Id   := Parent (Prot);
4314       Func      : Node_Id;
4315       B_F       : Node_Id;
4316       Body_Decl : Node_Id;
4317
4318    begin
4319       if No_Run_Time_Mode then
4320          Error_Msg_CRT ("entry barrier", N);
4321          return;
4322       end if;
4323
4324       --  The body of the entry barrier must be analyzed in the context of the
4325       --  protected object, but its scope is external to it, just as any other
4326       --  unprotected version of a protected operation. The specification has
4327       --  been produced when the protected type declaration was elaborated. We
4328       --  build the body, insert it in the enclosing scope, but analyze it in
4329       --  the current context. A more uniform approach would be to treat the
4330       --  barrier just as a protected function, and discard the protected
4331       --  version of it because it is never called.
4332
4333       if Expander_Active then
4334          B_F := Build_Barrier_Function (N, Ent, Prot);
4335          Func := Barrier_Function (Ent);
4336          Set_Corresponding_Spec (B_F, Func);
4337
4338          Body_Decl := Parent (Corresponding_Body (Spec_Decl));
4339
4340          if Nkind (Parent (Body_Decl)) = N_Subunit then
4341             Body_Decl := Corresponding_Stub (Parent (Body_Decl));
4342          end if;
4343
4344          Insert_Before_And_Analyze (Body_Decl, B_F);
4345
4346          Set_Discriminals (Spec_Decl);
4347          Set_Scope (Func, Scope (Prot));
4348
4349       else
4350          Analyze_And_Resolve (Cond, Any_Boolean);
4351       end if;
4352
4353       --  The Ravenscar profile restricts barriers to simple variables declared
4354       --  within the protected object. We also allow Boolean constants, since
4355       --  these appear in several published examples and are also allowed by
4356       --  the Aonix compiler.
4357
4358       --  Note that after analysis variables in this context will be replaced
4359       --  by the corresponding prival, that is to say a renaming of a selected
4360       --  component of the form _Object.Var. If expansion is disabled, as
4361       --  within a generic, we check that the entity appears in the current
4362       --  scope.
4363
4364       if Is_Entity_Name (Cond) then
4365
4366          --  A small optimization of useless renamings. If the scope of the
4367          --  entity of the condition is not the barrier function, then the
4368          --  condition does not reference any of the generated renamings
4369          --  within the function.
4370
4371          if Expander_Active
4372            and then Scope (Entity (Cond)) /= Func
4373          then
4374             Set_Declarations (B_F, Empty_List);
4375          end if;
4376
4377          if Entity (Cond) = Standard_False
4378               or else
4379             Entity (Cond) = Standard_True
4380          then
4381             return;
4382
4383          elsif not Expander_Active
4384            and then Scope (Entity (Cond)) = Current_Scope
4385          then
4386             return;
4387
4388          --  Check for case of _object.all.field (note that the explicit
4389          --  dereference gets inserted by analyze/expand of _object.field)
4390
4391          elsif Present (Renamed_Object (Entity (Cond)))
4392            and then
4393              Nkind (Renamed_Object (Entity (Cond))) = N_Selected_Component
4394            and then
4395              Chars
4396                (Prefix
4397                  (Prefix (Renamed_Object (Entity (Cond))))) = Name_uObject
4398          then
4399             return;
4400          end if;
4401       end if;
4402
4403       --  It is not a boolean variable or literal, so check the restriction
4404
4405       Check_Restriction (Simple_Barriers, Cond);
4406    end Expand_Entry_Barrier;
4407
4408    ------------------------------
4409    -- Expand_N_Abort_Statement --
4410    ------------------------------
4411
4412    --  Expand abort T1, T2, .. Tn; into:
4413    --    Abort_Tasks (Task_List'(1 => T1.Task_Id, 2 => T2.Task_Id ...))
4414
4415    procedure Expand_N_Abort_Statement (N : Node_Id) is
4416       Loc    : constant Source_Ptr := Sloc (N);
4417       Tlist  : constant List_Id    := Names (N);
4418       Count  : Nat;
4419       Aggr   : Node_Id;
4420       Tasknm : Node_Id;
4421
4422    begin
4423       Aggr := Make_Aggregate (Loc, Component_Associations => New_List);
4424       Count := 0;
4425
4426       Tasknm := First (Tlist);
4427
4428       while Present (Tasknm) loop
4429          Count := Count + 1;
4430
4431          --  A task interface class-wide type object is being aborted.
4432          --  Retrieve its _task_id by calling a dispatching routine.
4433
4434          if Ada_Version >= Ada_05
4435            and then Ekind (Etype (Tasknm)) = E_Class_Wide_Type
4436            and then Is_Interface (Etype (Tasknm))
4437            and then Is_Task_Interface (Etype (Tasknm))
4438          then
4439             Append_To (Component_Associations (Aggr),
4440               Make_Component_Association (Loc,
4441                 Choices => New_List (
4442                   Make_Integer_Literal (Loc, Count)),
4443                 Expression =>
4444
4445                   --  Task_Id (Tasknm._disp_get_task_id)
4446
4447                   Make_Unchecked_Type_Conversion (Loc,
4448                     Subtype_Mark =>
4449                       New_Reference_To (RTE (RO_ST_Task_Id), Loc),
4450                     Expression =>
4451                       Make_Selected_Component (Loc,
4452                         Prefix =>
4453                           New_Copy_Tree (Tasknm),
4454                         Selector_Name =>
4455                           Make_Identifier (Loc, Name_uDisp_Get_Task_Id)))));
4456
4457          else
4458             Append_To (Component_Associations (Aggr),
4459               Make_Component_Association (Loc,
4460                 Choices => New_List (
4461                   Make_Integer_Literal (Loc, Count)),
4462                 Expression => Concurrent_Ref (Tasknm)));
4463          end if;
4464
4465          Next (Tasknm);
4466       end loop;
4467
4468       Rewrite (N,
4469         Make_Procedure_Call_Statement (Loc,
4470           Name => New_Reference_To (RTE (RE_Abort_Tasks), Loc),
4471           Parameter_Associations => New_List (
4472             Make_Qualified_Expression (Loc,
4473               Subtype_Mark => New_Reference_To (RTE (RE_Task_List), Loc),
4474               Expression => Aggr))));
4475
4476       Analyze (N);
4477    end Expand_N_Abort_Statement;
4478
4479    -------------------------------
4480    -- Expand_N_Accept_Statement --
4481    -------------------------------
4482
4483    --  This procedure handles expansion of accept statements that stand
4484    --  alone, i.e. they are not part of an accept alternative. The expansion
4485    --  of accept statement in accept alternatives is handled by the routines
4486    --  Expand_N_Accept_Alternative and Expand_N_Selective_Accept. The
4487    --  following description applies only to stand alone accept statements.
4488
4489    --  If there is no handled statement sequence, or only null statements,
4490    --  then this is called a trivial accept, and the expansion is:
4491
4492    --    Accept_Trivial (entry-index)
4493
4494    --  If there is a handled statement sequence, then the expansion is:
4495
4496    --    Ann : Address;
4497    --    {Lnn : Label}
4498
4499    --    begin
4500    --       begin
4501    --          Accept_Call (entry-index, Ann);
4502    --          Renaming_Declarations for formals
4503    --          <statement sequence from N_Accept_Statement node>
4504    --          Complete_Rendezvous;
4505    --          <<Lnn>>
4506    --
4507    --       exception
4508    --          when ... =>
4509    --             <exception handler from N_Accept_Statement node>
4510    --             Complete_Rendezvous;
4511    --          when ... =>
4512    --             <exception handler from N_Accept_Statement node>
4513    --             Complete_Rendezvous;
4514    --          ...
4515    --       end;
4516
4517    --    exception
4518    --       when all others =>
4519    --          Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
4520    --    end;
4521
4522    --  The first three declarations were already inserted ahead of the accept
4523    --  statement by the Expand_Accept_Declarations procedure, which was called
4524    --  directly from the semantics during analysis of the accept statement,
4525    --  before analyzing its contained statements.
4526
4527    --  The declarations from the N_Accept_Statement, as noted in Sinfo, come
4528    --  from possible expansion activity (the original source of course does
4529    --  not have any declarations associated with the accept statement, since
4530    --  an accept statement has no declarative part). In particular, if the
4531    --  expander is active, the first such declaration is the declaration of
4532    --  the Accept_Params_Ptr entity (see Sem_Ch9.Analyze_Accept_Statement).
4533    --
4534    --  The two blocks are merged into a single block if the inner block has
4535    --  no exception handlers, but otherwise two blocks are required, since
4536    --  exceptions might be raised in the exception handlers of the inner
4537    --  block, and Exceptional_Complete_Rendezvous must be called.
4538
4539    procedure Expand_N_Accept_Statement (N : Node_Id) is
4540       Loc     : constant Source_Ptr := Sloc (N);
4541       Stats   : constant Node_Id    := Handled_Statement_Sequence (N);
4542       Ename   : constant Node_Id    := Entry_Direct_Name (N);
4543       Eindx   : constant Node_Id    := Entry_Index (N);
4544       Eent    : constant Entity_Id  := Entity (Ename);
4545       Acstack : constant Elist_Id   := Accept_Address (Eent);
4546       Ann     : constant Entity_Id  := Node (Last_Elmt (Acstack));
4547       Ttyp    : constant Entity_Id  := Etype (Scope (Eent));
4548       Blkent  : Entity_Id;
4549       Call    : Node_Id;
4550       Block   : Node_Id;
4551
4552    --  Start of processing for Expand_N_Accept_Statement
4553
4554    begin
4555       --  If accept statement is not part of a list, then its parent must be
4556       --  an accept alternative, and, as described above, we do not do any
4557       --  expansion for such accept statements at this level.
4558
4559       if not Is_List_Member (N) then
4560          pragma Assert (Nkind (Parent (N)) = N_Accept_Alternative);
4561          return;
4562
4563       --  Trivial accept case (no statement sequence, or null statements).
4564       --  If the accept statement has declarations, then just insert them
4565       --  before the procedure call.
4566
4567       elsif Trivial_Accept_OK
4568         and then (No (Stats) or else Null_Statements (Statements (Stats)))
4569       then
4570          --  Remove declarations for renamings, because the parameter block
4571          --  will not be assigned.
4572
4573          declare
4574             D      : Node_Id;
4575             Next_D : Node_Id;
4576
4577          begin
4578             D := First (Declarations (N));
4579
4580             while Present (D) loop
4581                Next_D := Next (D);
4582                if Nkind (D) = N_Object_Renaming_Declaration then
4583                   Remove (D);
4584                end if;
4585
4586                D := Next_D;
4587             end loop;
4588          end;
4589
4590          if Present (Declarations (N)) then
4591             Insert_Actions (N, Declarations (N));
4592          end if;
4593
4594          Rewrite (N,
4595            Make_Procedure_Call_Statement (Loc,
4596              Name => New_Reference_To (RTE (RE_Accept_Trivial), Loc),
4597              Parameter_Associations => New_List (
4598                Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp))));
4599
4600          Analyze (N);
4601
4602          --  Discard Entry_Address that was created for it, so it will not be
4603          --  emitted if this accept statement is in the statement part of a
4604          --  delay alternative.
4605
4606          if Present (Stats) then
4607             Remove_Last_Elmt (Acstack);
4608          end if;
4609
4610       --  Case of statement sequence present
4611
4612       else
4613          --  Construct the block, using the declarations from the accept
4614          --  statement if any to initialize the declarations of the block.
4615
4616          Blkent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
4617          Set_Ekind (Blkent, E_Block);
4618          Set_Etype (Blkent, Standard_Void_Type);
4619          Set_Scope (Blkent, Current_Scope);
4620
4621          Block :=
4622            Make_Block_Statement (Loc,
4623              Identifier                 => New_Reference_To (Blkent, Loc),
4624              Declarations               => Declarations (N),
4625              Handled_Statement_Sequence => Build_Accept_Body (N));
4626
4627          --  Prepend call to Accept_Call to main statement sequence If the
4628          --  accept has exception handlers, the statement sequence is wrapped
4629          --  in a block. Insert call and renaming declarations in the
4630          --  declarations of the block, so they are elaborated before the
4631          --  handlers.
4632
4633          Call :=
4634            Make_Procedure_Call_Statement (Loc,
4635              Name => New_Reference_To (RTE (RE_Accept_Call), Loc),
4636              Parameter_Associations => New_List (
4637                Entry_Index_Expression (Loc, Entity (Ename), Eindx, Ttyp),
4638                New_Reference_To (Ann, Loc)));
4639
4640          if Parent (Stats) = N then
4641             Prepend (Call, Statements (Stats));
4642          else
4643             Set_Declarations
4644               (Parent (Stats),
4645                 New_List (Call));
4646          end if;
4647
4648          Analyze (Call);
4649
4650          Push_Scope (Blkent);
4651
4652          declare
4653             D      : Node_Id;
4654             Next_D : Node_Id;
4655             Typ    : Entity_Id;
4656
4657          begin
4658             D := First (Declarations (N));
4659             while Present (D) loop
4660                Next_D := Next (D);
4661
4662                if Nkind (D) = N_Object_Renaming_Declaration then
4663
4664                   --  The renaming declarations for the formals were created
4665                   --  during analysis of the accept statement, and attached to
4666                   --  the list of declarations. Place them now in the context
4667                   --  of the accept block or subprogram.
4668
4669                   Remove (D);
4670                   Typ := Entity (Subtype_Mark (D));
4671                   Insert_After (Call, D);
4672                   Analyze (D);
4673
4674                   --  If the formal is class_wide, it does not have an actual
4675                   --  subtype. The analysis of the renaming declaration creates
4676                   --  one, but we need to retain the class-wide nature of the
4677                   --  entity.
4678
4679                   if Is_Class_Wide_Type (Typ) then
4680                      Set_Etype (Defining_Identifier (D), Typ);
4681                   end if;
4682
4683                end if;
4684
4685                D := Next_D;
4686             end loop;
4687          end;
4688
4689          End_Scope;
4690
4691          --  Replace the accept statement by the new block
4692
4693          Rewrite (N, Block);
4694          Analyze (N);
4695
4696          --  Last step is to unstack the Accept_Address value
4697
4698          Remove_Last_Elmt (Acstack);
4699       end if;
4700    end Expand_N_Accept_Statement;
4701
4702    ----------------------------------
4703    -- Expand_N_Asynchronous_Select --
4704    ----------------------------------
4705
4706    --  This procedure assumes that the trigger statement is an entry call or
4707    --  a dispatching procedure call. A delay alternative should already have
4708    --  been expanded into an entry call to the appropriate delay object Wait
4709    --  entry.
4710
4711    --  If the trigger is a task entry call, the select is implemented with
4712    --  a Task_Entry_Call:
4713
4714    --    declare
4715    --       B : Boolean;
4716    --       C : Boolean;
4717    --       P : parms := (parm, parm, parm);
4718
4719    --        --  Clean is added by Exp_Ch7.Expand_Cleanup_Actions
4720
4721    --       procedure _clean is
4722    --       begin
4723    --          ...
4724    --          Cancel_Task_Entry_Call (C);
4725    --          ...
4726    --       end _clean;
4727
4728    --    begin
4729    --       Abort_Defer;
4730    --       Task_Entry_Call
4731    --         (<acceptor-task>,    --  Acceptor
4732    --          <entry-index>,      --  E
4733    --          P'Address,          --  Uninterpreted_Data
4734    --          Asynchronous_Call,  --  Mode
4735    --          B);                 --  Rendezvous_Successful
4736
4737    --       begin
4738    --          begin
4739    --             Abort_Undefer;
4740    --             <abortable-part>
4741    --          at end
4742    --             _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
4743    --          end;
4744    --       exception
4745    --          when Abort_Signal => Abort_Undefer;
4746    --       end;
4747
4748    --       parm := P.param;
4749    --       parm := P.param;
4750    --       ...
4751    --       if not C then
4752    --          <triggered-statements>
4753    --       end if;
4754    --    end;
4755
4756    --  Note that Build_Simple_Entry_Call is used to expand the entry of the
4757    --  asynchronous entry call (by Expand_N_Entry_Call_Statement procedure)
4758    --  as follows:
4759
4760    --    declare
4761    --       P : parms := (parm, parm, parm);
4762    --    begin
4763    --       Call_Simple (acceptor-task, entry-index, P'Address);
4764    --       parm := P.param;
4765    --       parm := P.param;
4766    --       ...
4767    --    end;
4768
4769    --  so the task at hand is to convert the latter expansion into the former
4770
4771    --  If the trigger is a protected entry call, the select is implemented
4772    --  with Protected_Entry_Call:
4773
4774    --  declare
4775    --     P   : E1_Params := (param, param, param);
4776    --     Bnn : Communications_Block;
4777
4778    --  begin
4779    --     declare
4780
4781    --        --  Clean is added by Exp_Ch7.Expand_Cleanup_Actions
4782
4783    --        procedure _clean is
4784    --        begin
4785    --           ...
4786    --           if Enqueued (Bnn) then
4787    --              Cancel_Protected_Entry_Call (Bnn);
4788    --           end if;
4789    --           ...
4790    --        end _clean;
4791
4792    --     begin
4793    --        begin
4794    --           Protected_Entry_Call
4795    --             (po._object'Access,  --  Object
4796    --              <entry index>,      --  E
4797    --              P'Address,          --  Uninterpreted_Data
4798    --              Asynchronous_Call,  --  Mode
4799    --              Bnn);               --  Block
4800
4801    --           if Enqueued (Bnn) then
4802    --              <abortable-part>
4803    --           end if;
4804    --        at end
4805    --           _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
4806    --        end;
4807    --     exception
4808    --        when Abort_Signal => Abort_Undefer;
4809    --     end;
4810
4811    --     if not Cancelled (Bnn) then
4812    --        <triggered-statements>
4813    --     end if;
4814    --  end;
4815
4816    --  Build_Simple_Entry_Call is used to expand the all to a simple protected
4817    --  entry call:
4818
4819    --  declare
4820    --     P   : E1_Params := (param, param, param);
4821    --     Bnn : Communications_Block;
4822
4823    --  begin
4824    --     Protected_Entry_Call
4825    --       (po._object'Access,  --  Object
4826    --        <entry index>,      --  E
4827    --        P'Address,          --  Uninterpreted_Data
4828    --        Simple_Call,        --  Mode
4829    --        Bnn);               --  Block
4830    --     parm := P.param;
4831    --     parm := P.param;
4832    --       ...
4833    --  end;
4834
4835    --  Ada 2005 (AI-345): If the trigger is a dispatching call, the select is
4836    --  expanded into:
4837
4838    --    declare
4839    --       B   : Boolean := False;
4840    --       Bnn : Communication_Block;
4841    --       C   : Ada.Tags.Prim_Op_Kind;
4842    --       D   : System.Storage_Elements.Dummy_Communication_Block;
4843    --       K   : Ada.Tags.Tagged_Kind :=
4844    --               Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
4845    --       P   : Parameters := (Param1 .. ParamN);
4846    --       S   : Integer;
4847    --       U   : Boolean;
4848
4849    --    begin
4850    --       if K = Ada.Tags.TK_Limited_Tagged then
4851    --          <dispatching-call>;
4852    --          <triggering-statements>;
4853
4854    --       else
4855    --          S :=
4856    --            Ada.Tags.Get_Offset_Index
4857    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
4858
4859    --          _Disp_Get_Prim_Op_Kind (<object>, S, C);
4860
4861    --          if C = POK_Protected_Entry then
4862    --             declare
4863    --                procedure _clean is
4864    --                begin
4865    --                   if Enqueued (Bnn) then
4866    --                      Cancel_Protected_Entry_Call (Bnn);
4867    --                   end if;
4868    --                end _clean;
4869
4870    --             begin
4871    --                begin
4872    --                   _Disp_Asynchronous_Select
4873    --                     (<object>, S, P'Address, D, B);
4874    --                   Bnn := Communication_Block (D);
4875
4876    --                   Param1 := P.Param1;
4877    --                   ...
4878    --                   ParamN := P.ParamN;
4879
4880    --                   if Enqueued (Bnn) then
4881    --                      <abortable-statements>
4882    --                   end if;
4883    --                at end
4884    --                   _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
4885    --                end;
4886    --             exception
4887    --                when Abort_Signal => Abort_Undefer;
4888    --             end;
4889
4890    --             if not Cancelled (Bnn) then
4891    --                <triggering-statements>
4892    --             end if;
4893
4894    --          elsif C = POK_Task_Entry then
4895    --             declare
4896    --                procedure _clean is
4897    --                begin
4898    --                   Cancel_Task_Entry_Call (U);
4899    --                end _clean;
4900
4901    --             begin
4902    --                Abort_Defer;
4903
4904    --                _Disp_Asynchronous_Select
4905    --                  (<object>, S, P'Address, D, B);
4906    --                Bnn := Communication_Bloc (D);
4907
4908    --                Param1 := P.Param1;
4909    --                ...
4910    --                ParamN := P.ParamN;
4911
4912    --                begin
4913    --                   begin
4914    --                      Abort_Undefer;
4915    --                      <abortable-statements>
4916    --                   at end
4917    --                      _clean;  --  Added by Exp_Ch7.Expand_Cleanup_Actions
4918    --                   end;
4919    --                exception
4920    --                   when Abort_Signal => Abort_Undefer;
4921    --                end;
4922
4923    --                if not U then
4924    --                   <triggering-statements>
4925    --                end if;
4926    --             end;
4927
4928    --          else
4929    --             <dispatching-call>;
4930    --             <triggering-statements>
4931    --          end if;
4932    --       end if;
4933    --    end;
4934
4935    --  The job is to convert this to the asynchronous form
4936
4937    --  If the trigger is a delay statement, it will have been expanded into a
4938    --  call to one of the GNARL delay procedures. This routine will convert
4939    --  this into a protected entry call on a delay object and then continue
4940    --  processing as for a protected entry call trigger. This requires
4941    --  declaring a Delay_Block object and adding a pointer to this object to
4942    --  the parameter list of the delay procedure to form the parameter list of
4943    --  the entry call. This object is used by the runtime to queue the delay
4944    --  request.
4945
4946    --  For a description of the use of P and the assignments after the call,
4947    --  see Expand_N_Entry_Call_Statement.
4948
4949    procedure Expand_N_Asynchronous_Select (N : Node_Id) is
4950       Loc    : constant Source_Ptr := Sloc (N);
4951       Abrt   : constant Node_Id    := Abortable_Part (N);
4952       Astats : constant List_Id    := Statements (Abrt);
4953       Trig   : constant Node_Id    := Triggering_Alternative (N);
4954       Tstats : constant List_Id    := Statements (Trig);
4955
4956       Abort_Block_Ent   : Entity_Id;
4957       Abortable_Block   : Node_Id;
4958       Actuals           : List_Id;
4959       Blk_Ent           : Entity_Id;
4960       Blk_Typ           : Entity_Id;
4961       Call              : Node_Id;
4962       Call_Ent          : Entity_Id;
4963       Cancel_Param      : Entity_Id;
4964       Cleanup_Block     : Node_Id;
4965       Cleanup_Block_Ent : Entity_Id;
4966       Cleanup_Stmts     : List_Id;
4967       Conc_Typ_Stmts    : List_Id;
4968       Concval           : Node_Id;
4969       Dblock_Ent        : Entity_Id;
4970       Decl              : Node_Id;
4971       Decls             : List_Id;
4972       Ecall             : Node_Id;
4973       Ename             : Node_Id;
4974       Enqueue_Call      : Node_Id;
4975       Formals           : List_Id;
4976       Hdle              : List_Id;
4977       Index             : Node_Id;
4978       Lim_Typ_Stmts     : List_Id;
4979       N_Orig            : Node_Id;
4980       Obj               : Entity_Id;
4981       Param             : Node_Id;
4982       Params            : List_Id;
4983       Pdef              : Entity_Id;
4984       ProtE_Stmts       : List_Id;
4985       ProtP_Stmts       : List_Id;
4986       Stmt              : Node_Id;
4987       Stmts             : List_Id;
4988       Target_Undefer    : RE_Id;
4989       TaskE_Stmts       : List_Id;
4990       Undefer_Args      : List_Id := No_List;
4991
4992       B   : Entity_Id;  --  Call status flag
4993       Bnn : Entity_Id;  --  Communication block
4994       C   : Entity_Id;  --  Call kind
4995       K   : Entity_Id;  --  Tagged kind
4996       P   : Entity_Id;  --  Parameter block
4997       S   : Entity_Id;  --  Primitive operation slot
4998       T   : Entity_Id;  --  Additional status flag
4999
5000    begin
5001       Blk_Ent := Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5002       Ecall   := Triggering_Statement (Trig);
5003
5004       --  The arguments in the call may require dynamic allocation, and the
5005       --  call statement may have been transformed into a block. The block
5006       --  may contain additional declarations for internal entities, and the
5007       --  original call is found by sequential search.
5008
5009       if Nkind (Ecall) = N_Block_Statement then
5010          Ecall := First (Statements (Handled_Statement_Sequence (Ecall)));
5011          while not Nkind_In (Ecall, N_Procedure_Call_Statement,
5012                                     N_Entry_Call_Statement)
5013          loop
5014             Next (Ecall);
5015          end loop;
5016       end if;
5017
5018       --  This is either a dispatching call or a delay statement used as a
5019       --  trigger which was expanded into a procedure call.
5020
5021       if Nkind (Ecall) = N_Procedure_Call_Statement then
5022          if Ada_Version >= Ada_05
5023            and then
5024              (No (Original_Node (Ecall))
5025                 or else not Nkind_In (Original_Node (Ecall),
5026                                         N_Delay_Relative_Statement,
5027                                         N_Delay_Until_Statement))
5028          then
5029             Extract_Dispatching_Call (Ecall, Call_Ent, Obj, Actuals, Formals);
5030
5031             Decls := New_List;
5032             Stmts := New_List;
5033
5034             --  Call status flag processing, generate:
5035             --    B : Boolean := False;
5036
5037             B := Build_B (Loc, Decls);
5038
5039             --  Communication block processing, generate:
5040             --    Bnn : Communication_Block;
5041
5042             Bnn := Make_Defining_Identifier (Loc, New_Internal_Name ('B'));
5043
5044             Append_To (Decls,
5045               Make_Object_Declaration (Loc,
5046                 Defining_Identifier =>
5047                   Bnn,
5048                 Object_Definition =>
5049                   New_Reference_To (RTE (RE_Communication_Block), Loc)));
5050
5051             --  Call kind processing, generate:
5052             --    C : Ada.Tags.Prim_Op_Kind;
5053
5054             C := Build_C (Loc, Decls);
5055
5056             --  Tagged kind processing, generate:
5057             --    K : Ada.Tags.Tagged_Kind :=
5058             --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
5059
5060             --  Dummy communication block, generate:
5061             --    D : Dummy_Communication_Block;
5062
5063             Append_To (Decls,
5064               Make_Object_Declaration (Loc,
5065                 Defining_Identifier =>
5066                   Make_Defining_Identifier (Loc, Name_uD),
5067                 Object_Definition =>
5068                   New_Reference_To (
5069                     RTE (RE_Dummy_Communication_Block), Loc)));
5070
5071             K := Build_K (Loc, Decls, Obj);
5072
5073             --  Parameter block processing
5074
5075             Blk_Typ := Build_Parameter_Block
5076                          (Loc, Actuals, Formals, Decls);
5077             P       := Parameter_Block_Pack
5078                          (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
5079
5080             --  Dispatch table slot processing, generate:
5081             --    S : Integer;
5082
5083             S := Build_S (Loc, Decls);
5084
5085             --  Additional status flag processing, generate:
5086
5087             T := Make_Defining_Identifier (Loc, New_Internal_Name ('T'));
5088
5089             Append_To (Decls,
5090               Make_Object_Declaration (Loc,
5091                 Defining_Identifier =>
5092                   T,
5093                 Object_Definition =>
5094                   New_Reference_To (Standard_Boolean, Loc)));
5095
5096             ------------------------------
5097             -- Protected entry handling --
5098             ------------------------------
5099
5100             --  Generate:
5101             --    Param1 := P.Param1;
5102             --    ...
5103             --    ParamN := P.ParamN;
5104
5105             Cleanup_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
5106
5107             --  Generate:
5108             --    Bnn := Communication_Block (D);
5109
5110             Prepend_To (Cleanup_Stmts,
5111               Make_Assignment_Statement (Loc,
5112                 Name =>
5113                   New_Reference_To (Bnn, Loc),
5114                 Expression =>
5115                   Make_Unchecked_Type_Conversion (Loc,
5116                     Subtype_Mark =>
5117                       New_Reference_To (RTE (RE_Communication_Block), Loc),
5118                     Expression =>
5119                       Make_Identifier (Loc, Name_uD))));
5120
5121             --  Generate:
5122             --    _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
5123
5124             Prepend_To (Cleanup_Stmts,
5125               Make_Procedure_Call_Statement (Loc,
5126                 Name =>
5127                   New_Reference_To (
5128                     Find_Prim_Op (Etype (Etype (Obj)),
5129                       Name_uDisp_Asynchronous_Select),
5130                     Loc),
5131                 Parameter_Associations =>
5132                   New_List (
5133                     New_Copy_Tree (Obj),             --  <object>
5134                     New_Reference_To (S, Loc),       --  S
5135                     Make_Attribute_Reference (Loc,   --  P'Address
5136                       Prefix =>
5137                         New_Reference_To (P, Loc),
5138                       Attribute_Name =>
5139                         Name_Address),
5140                     Make_Identifier (Loc, Name_uD),  --  D
5141                     New_Reference_To (B, Loc))));    --  B
5142
5143             --  Generate:
5144             --    if Enqueued (Bnn) then
5145             --       <abortable-statements>
5146             --    end if;
5147
5148             Append_To (Cleanup_Stmts,
5149               Make_If_Statement (Loc,
5150                 Condition =>
5151                   Make_Function_Call (Loc,
5152                     Name =>
5153                       New_Reference_To (RTE (RE_Enqueued), Loc),
5154                     Parameter_Associations =>
5155                       New_List (
5156                         New_Reference_To (Bnn, Loc))),
5157
5158                 Then_Statements =>
5159                   New_Copy_List_Tree (Astats)));
5160
5161             --  Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
5162             --  will then generate a _clean for the communication block Bnn.
5163
5164             --  Generate:
5165             --    declare
5166             --       procedure _clean is
5167             --       begin
5168             --          if Enqueued (Bnn) then
5169             --             Cancel_Protected_Entry_Call (Bnn);
5170             --          end if;
5171             --       end _clean;
5172             --    begin
5173             --       Cleanup_Stmts
5174             --    at end
5175             --       _clean;
5176             --    end;
5177
5178             Cleanup_Block_Ent :=
5179               Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
5180
5181             Cleanup_Block :=
5182               Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, Bnn);
5183
5184             --  Wrap the cleanup block in an exception handling block
5185
5186             --  Generate:
5187             --    begin
5188             --       Cleanup_Block
5189             --    exception
5190             --       when Abort_Signal => Abort_Undefer;
5191             --    end;
5192
5193             Abort_Block_Ent :=
5194               Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5195
5196             ProtE_Stmts :=
5197               New_List (
5198                 Make_Implicit_Label_Declaration (Loc,
5199                   Defining_Identifier =>
5200                     Abort_Block_Ent),
5201
5202                 Build_Abort_Block
5203                   (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
5204
5205             --  Generate:
5206             --    if not Cancelled (Bnn) then
5207             --       <triggering-statements>
5208             --    end if;
5209
5210             Append_To (ProtE_Stmts,
5211               Make_If_Statement (Loc,
5212                 Condition =>
5213                   Make_Op_Not (Loc,
5214                     Right_Opnd =>
5215                       Make_Function_Call (Loc,
5216                         Name =>
5217                           New_Reference_To (RTE (RE_Cancelled), Loc),
5218                         Parameter_Associations =>
5219                           New_List (
5220                             New_Reference_To (Bnn, Loc)))),
5221
5222                 Then_Statements =>
5223                   New_Copy_List_Tree (Tstats)));
5224
5225             -------------------------
5226             -- Task entry handling --
5227             -------------------------
5228
5229             --  Generate:
5230             --    Param1 := P.Param1;
5231             --    ...
5232             --    ParamN := P.ParamN;
5233
5234             TaskE_Stmts := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
5235
5236             --  Generate:
5237             --    Bnn := Communication_Block (D);
5238
5239             Append_To (TaskE_Stmts,
5240               Make_Assignment_Statement (Loc,
5241                 Name =>
5242                   New_Reference_To (Bnn, Loc),
5243                 Expression =>
5244                   Make_Unchecked_Type_Conversion (Loc,
5245                     Subtype_Mark =>
5246                       New_Reference_To (RTE (RE_Communication_Block), Loc),
5247                     Expression =>
5248                       Make_Identifier (Loc, Name_uD))));
5249
5250             --  Generate:
5251             --    _Disp_Asynchronous_Select (<object>, S, P'Address, D, B);
5252
5253             Prepend_To (TaskE_Stmts,
5254               Make_Procedure_Call_Statement (Loc,
5255                 Name =>
5256                   New_Reference_To (
5257                     Find_Prim_Op (Etype (Etype (Obj)),
5258                       Name_uDisp_Asynchronous_Select),
5259                     Loc),
5260                 Parameter_Associations =>
5261                   New_List (
5262                     New_Copy_Tree (Obj),             --  <object>
5263                     New_Reference_To (S, Loc),       --  S
5264                     Make_Attribute_Reference (Loc,   --  P'Address
5265                       Prefix =>
5266                         New_Reference_To (P, Loc),
5267                       Attribute_Name =>
5268                         Name_Address),
5269                     Make_Identifier (Loc, Name_uD),  --  D
5270                     New_Reference_To (B, Loc))));    --  B
5271
5272             --  Generate:
5273             --    Abort_Defer;
5274
5275             Prepend_To (TaskE_Stmts,
5276               Make_Procedure_Call_Statement (Loc,
5277                 Name =>
5278                   New_Reference_To (RTE (RE_Abort_Defer), Loc),
5279                 Parameter_Associations =>
5280                   No_List));
5281
5282             --  Generate:
5283             --    Abort_Undefer;
5284             --    <abortable-statements>
5285
5286             Cleanup_Stmts := New_Copy_List_Tree (Astats);
5287
5288             Prepend_To (Cleanup_Stmts,
5289               Make_Procedure_Call_Statement (Loc,
5290                 Name =>
5291                   New_Reference_To (RTE (RE_Abort_Undefer), Loc),
5292                 Parameter_Associations =>
5293                   No_List));
5294
5295             --  Wrap the statements in a block. Exp_Ch7.Expand_Cleanup_Actions
5296             --  will generate a _clean for the additional status flag.
5297
5298             --  Generate:
5299             --    declare
5300             --       procedure _clean is
5301             --       begin
5302             --          Cancel_Task_Entry_Call (U);
5303             --       end _clean;
5304             --    begin
5305             --       Cleanup_Stmts
5306             --    at end
5307             --       _clean;
5308             --    end;
5309
5310             Cleanup_Block_Ent :=
5311               Make_Defining_Identifier (Loc, New_Internal_Name ('C'));
5312
5313             Cleanup_Block :=
5314               Build_Cleanup_Block (Loc, Cleanup_Block_Ent, Cleanup_Stmts, T);
5315
5316             --  Wrap the cleanup block in an exception handling block
5317
5318             --  Generate:
5319             --    begin
5320             --       Cleanup_Block
5321             --    exception
5322             --       when Abort_Signal => Abort_Undefer;
5323             --    end;
5324
5325             Abort_Block_Ent :=
5326               Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
5327
5328             Append_To (TaskE_Stmts,
5329               Make_Implicit_Label_Declaration (Loc,
5330                 Defining_Identifier =>
5331                   Abort_Block_Ent));
5332
5333             Append_To (TaskE_Stmts,
5334               Build_Abort_Block
5335                 (Loc, Abort_Block_Ent, Cleanup_Block_Ent, Cleanup_Block));
5336
5337             --  Generate:
5338             --    if not T then
5339             --       <triggering-statements>
5340             --    end if;
5341
5342             Append_To (TaskE_Stmts,
5343               Make_If_Statement (Loc,
5344                 Condition =>
5345                   Make_Op_Not (Loc,
5346                     Right_Opnd =>
5347                       New_Reference_To (T, Loc)),
5348
5349                 Then_Statements =>
5350                   New_Copy_List_Tree (Tstats)));
5351
5352             ----------------------------------
5353             -- Protected procedure handling --
5354             ----------------------------------
5355
5356             --  Generate:
5357             --    <dispatching-call>;
5358             --    <triggering-statements>
5359
5360             ProtP_Stmts := New_Copy_List_Tree (Tstats);
5361             Prepend_To (ProtP_Stmts, New_Copy_Tree (Ecall));
5362
5363             --  Generate:
5364             --    S := Ada.Tags.Get_Offset_Index
5365             --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
5366
5367             Conc_Typ_Stmts :=
5368               New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
5369
5370             --  Generate:
5371             --    _Disp_Get_Prim_Op_Kind (<object>, S, C);
5372
5373             Append_To (Conc_Typ_Stmts,
5374               Make_Procedure_Call_Statement (Loc,
5375                 Name =>
5376                   New_Reference_To (
5377                     Find_Prim_Op (Etype (Etype (Obj)),
5378                       Name_uDisp_Get_Prim_Op_Kind),
5379                     Loc),
5380                 Parameter_Associations =>
5381                   New_List (
5382                     New_Copy_Tree (Obj),
5383                     New_Reference_To (S, Loc),
5384                     New_Reference_To (C, Loc))));
5385
5386             --  Generate:
5387             --    if C = POK_Procedure_Entry then
5388             --       ProtE_Stmts
5389             --    elsif C = POK_Task_Entry then
5390             --       TaskE_Stmts
5391             --    else
5392             --       ProtP_Stmts
5393             --    end if;
5394
5395             Append_To (Conc_Typ_Stmts,
5396               Make_If_Statement (Loc,
5397                 Condition =>
5398                   Make_Op_Eq (Loc,
5399                     Left_Opnd =>
5400                       New_Reference_To (C, Loc),
5401                     Right_Opnd =>
5402                       New_Reference_To (RTE (RE_POK_Protected_Entry), Loc)),
5403
5404                 Then_Statements =>
5405                   ProtE_Stmts,
5406
5407                 Elsif_Parts =>
5408                   New_List (
5409                     Make_Elsif_Part (Loc,
5410                       Condition =>
5411                         Make_Op_Eq (Loc,
5412                           Left_Opnd =>
5413                             New_Reference_To (C, Loc),
5414                           Right_Opnd =>
5415                             New_Reference_To (RTE (RE_POK_Task_Entry), Loc)),
5416
5417                       Then_Statements =>
5418                         TaskE_Stmts)),
5419
5420                 Else_Statements =>
5421                   ProtP_Stmts));
5422
5423             --  Generate:
5424             --    <dispatching-call>;
5425             --    <triggering-statements>
5426
5427             Lim_Typ_Stmts := New_Copy_List_Tree (Tstats);
5428             Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Ecall));
5429
5430             --  Generate:
5431             --    if K = Ada.Tags.TK_Limited_Tagged then
5432             --       Lim_Typ_Stmts
5433             --    else
5434             --       Conc_Typ_Stmts
5435             --    end if;
5436
5437             Append_To (Stmts,
5438               Make_If_Statement (Loc,
5439                 Condition =>
5440                    Make_Op_Eq (Loc,
5441                      Left_Opnd =>
5442                        New_Reference_To (K, Loc),
5443                      Right_Opnd =>
5444                        New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc)),
5445
5446                 Then_Statements =>
5447                   Lim_Typ_Stmts,
5448
5449                 Else_Statements =>
5450                   Conc_Typ_Stmts));
5451
5452             Rewrite (N,
5453               Make_Block_Statement (Loc,
5454                 Declarations =>
5455                   Decls,
5456                 Handled_Statement_Sequence =>
5457                   Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5458
5459             Analyze (N);
5460             return;
5461
5462          --  Delay triggering statement processing
5463
5464          else
5465             --  Add a Delay_Block object to the parameter list of the delay
5466             --  procedure to form the parameter list of the Wait entry call.
5467
5468             Dblock_Ent :=
5469               Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
5470
5471             Pdef := Entity (Name (Ecall));
5472
5473             if Is_RTE (Pdef, RO_CA_Delay_For) then
5474                Enqueue_Call :=
5475                  New_Reference_To (RTE (RE_Enqueue_Duration), Loc);
5476
5477             elsif Is_RTE (Pdef, RO_CA_Delay_Until) then
5478                Enqueue_Call :=
5479                  New_Reference_To (RTE (RE_Enqueue_Calendar), Loc);
5480
5481             else pragma Assert (Is_RTE (Pdef, RO_RT_Delay_Until));
5482                Enqueue_Call := New_Reference_To (RTE (RE_Enqueue_RT), Loc);
5483             end if;
5484
5485             Append_To (Parameter_Associations (Ecall),
5486               Make_Attribute_Reference (Loc,
5487                 Prefix => New_Reference_To (Dblock_Ent, Loc),
5488                 Attribute_Name => Name_Unchecked_Access));
5489
5490             --  Create the inner block to protect the abortable part
5491
5492             Hdle := New_List (
5493               Make_Implicit_Exception_Handler (Loc,
5494                 Exception_Choices =>
5495                   New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5496                 Statements => New_List (
5497                   Make_Procedure_Call_Statement (Loc,
5498                     Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
5499
5500             Prepend_To (Astats,
5501               Make_Procedure_Call_Statement (Loc,
5502                 Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
5503
5504             Abortable_Block :=
5505               Make_Block_Statement (Loc,
5506                 Identifier => New_Reference_To (Blk_Ent, Loc),
5507                 Handled_Statement_Sequence =>
5508                   Make_Handled_Sequence_Of_Statements (Loc,
5509                     Statements => Astats),
5510                 Has_Created_Identifier => True,
5511                 Is_Asynchronous_Call_Block => True);
5512
5513             --  Append call to if Enqueue (When, DB'Unchecked_Access) then
5514
5515             Rewrite (Ecall,
5516               Make_Implicit_If_Statement (N,
5517                 Condition => Make_Function_Call (Loc,
5518                   Name => Enqueue_Call,
5519                   Parameter_Associations => Parameter_Associations (Ecall)),
5520                 Then_Statements =>
5521                   New_List (Make_Block_Statement (Loc,
5522                     Handled_Statement_Sequence =>
5523                       Make_Handled_Sequence_Of_Statements (Loc,
5524                         Statements => New_List (
5525                           Make_Implicit_Label_Declaration (Loc,
5526                             Defining_Identifier => Blk_Ent,
5527                             Label_Construct     => Abortable_Block),
5528                           Abortable_Block),
5529                         Exception_Handlers => Hdle)))));
5530
5531             Stmts := New_List (Ecall);
5532
5533             --  Construct statement sequence for new block
5534
5535             Append_To (Stmts,
5536               Make_Implicit_If_Statement (N,
5537                 Condition => Make_Function_Call (Loc,
5538                   Name => New_Reference_To (
5539                     RTE (RE_Timed_Out), Loc),
5540                   Parameter_Associations => New_List (
5541                     Make_Attribute_Reference (Loc,
5542                       Prefix => New_Reference_To (Dblock_Ent, Loc),
5543                       Attribute_Name => Name_Unchecked_Access))),
5544                 Then_Statements => Tstats));
5545
5546             --  The result is the new block
5547
5548             Set_Entry_Cancel_Parameter (Blk_Ent, Dblock_Ent);
5549
5550             Rewrite (N,
5551               Make_Block_Statement (Loc,
5552                 Declarations => New_List (
5553                   Make_Object_Declaration (Loc,
5554                     Defining_Identifier => Dblock_Ent,
5555                     Aliased_Present => True,
5556                     Object_Definition => New_Reference_To (
5557                       RTE (RE_Delay_Block), Loc))),
5558
5559                 Handled_Statement_Sequence =>
5560                   Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5561
5562             Analyze (N);
5563             return;
5564          end if;
5565
5566       else
5567          N_Orig := N;
5568       end if;
5569
5570       Extract_Entry (Ecall, Concval, Ename, Index);
5571       Build_Simple_Entry_Call (Ecall, Concval, Ename, Index);
5572
5573       Stmts := Statements (Handled_Statement_Sequence (Ecall));
5574       Decls := Declarations (Ecall);
5575
5576       if Is_Protected_Type (Etype (Concval)) then
5577
5578          --  Get the declarations of the block expanded from the entry call
5579
5580          Decl := First (Decls);
5581          while Present (Decl)
5582            and then
5583              (Nkind (Decl) /= N_Object_Declaration
5584                or else not Is_RTE (Etype (Object_Definition (Decl)),
5585                                    RE_Communication_Block))
5586          loop
5587             Next (Decl);
5588          end loop;
5589
5590          pragma Assert (Present (Decl));
5591          Cancel_Param := Defining_Identifier (Decl);
5592
5593          --  Change the mode of the Protected_Entry_Call call
5594
5595          --  Protected_Entry_Call (
5596          --    Object => po._object'Access,
5597          --    E => <entry index>;
5598          --    Uninterpreted_Data => P'Address;
5599          --    Mode => Asynchronous_Call;
5600          --    Block => Bnn);
5601
5602          Stmt := First (Stmts);
5603
5604          --  Skip assignments to temporaries created for in-out parameters
5605
5606          --  This makes unwarranted assumptions about the shape of the expanded
5607          --  tree for the call, and should be cleaned up ???
5608
5609          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
5610             Next (Stmt);
5611          end loop;
5612
5613          Call := Stmt;
5614
5615          Param := First (Parameter_Associations (Call));
5616          while Present (Param)
5617            and then not Is_RTE (Etype (Param), RE_Call_Modes)
5618          loop
5619             Next (Param);
5620          end loop;
5621
5622          pragma Assert (Present (Param));
5623          Rewrite (Param, New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
5624          Analyze (Param);
5625
5626          --  Append an if statement to execute the abortable part
5627
5628          --  Generate:
5629          --    if Enqueued (Bnn) then
5630
5631          Append_To (Stmts,
5632            Make_Implicit_If_Statement (N,
5633              Condition => Make_Function_Call (Loc,
5634                Name => New_Reference_To (
5635                  RTE (RE_Enqueued), Loc),
5636                Parameter_Associations => New_List (
5637                  New_Reference_To (Cancel_Param, Loc))),
5638              Then_Statements => Astats));
5639
5640          Abortable_Block :=
5641            Make_Block_Statement (Loc,
5642              Identifier => New_Reference_To (Blk_Ent, Loc),
5643              Handled_Statement_Sequence =>
5644                Make_Handled_Sequence_Of_Statements (Loc,
5645                  Statements => Stmts),
5646              Has_Created_Identifier => True,
5647              Is_Asynchronous_Call_Block => True);
5648
5649          --  For the VM call Update_Exception instead of Abort_Undefer.
5650          --  See 4jexcept.ads for an explanation.
5651
5652          if VM_Target = No_VM then
5653             Target_Undefer := RE_Abort_Undefer;
5654          else
5655             Target_Undefer := RE_Update_Exception;
5656             Undefer_Args :=
5657               New_List (Make_Function_Call (Loc,
5658                           Name => New_Occurrence_Of
5659                                     (RTE (RE_Current_Target_Exception), Loc)));
5660          end if;
5661
5662          Stmts := New_List (
5663            Make_Block_Statement (Loc,
5664              Handled_Statement_Sequence =>
5665                Make_Handled_Sequence_Of_Statements (Loc,
5666                  Statements => New_List (
5667                    Make_Implicit_Label_Declaration (Loc,
5668                      Defining_Identifier => Blk_Ent,
5669                      Label_Construct     => Abortable_Block),
5670                    Abortable_Block),
5671
5672                --  exception
5673
5674                  Exception_Handlers => New_List (
5675                    Make_Implicit_Exception_Handler (Loc,
5676
5677                --  when Abort_Signal =>
5678                --     Abort_Undefer.all;
5679
5680                      Exception_Choices =>
5681                        New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5682                      Statements => New_List (
5683                        Make_Procedure_Call_Statement (Loc,
5684                          Name => New_Reference_To (
5685                            RTE (Target_Undefer), Loc),
5686                          Parameter_Associations => Undefer_Args)))))),
5687
5688          --  if not Cancelled (Bnn) then
5689          --     triggered statements
5690          --  end if;
5691
5692            Make_Implicit_If_Statement (N,
5693              Condition => Make_Op_Not (Loc,
5694                Right_Opnd =>
5695                  Make_Function_Call (Loc,
5696                    Name => New_Occurrence_Of (RTE (RE_Cancelled), Loc),
5697                    Parameter_Associations => New_List (
5698                      New_Occurrence_Of (Cancel_Param, Loc)))),
5699              Then_Statements => Tstats));
5700
5701       --  Asynchronous task entry call
5702
5703       else
5704          if No (Decls) then
5705             Decls := New_List;
5706          end if;
5707
5708          B := Make_Defining_Identifier (Loc, Name_uB);
5709
5710          --  Insert declaration of B in declarations of existing block
5711
5712          Prepend_To (Decls,
5713            Make_Object_Declaration (Loc,
5714              Defining_Identifier => B,
5715              Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
5716
5717          Cancel_Param := Make_Defining_Identifier (Loc, Name_uC);
5718
5719          --  Insert declaration of C in declarations of existing block
5720
5721          Prepend_To (Decls,
5722            Make_Object_Declaration (Loc,
5723              Defining_Identifier => Cancel_Param,
5724              Object_Definition => New_Reference_To (Standard_Boolean, Loc)));
5725
5726          --  Remove and save the call to Call_Simple
5727
5728          Stmt := First (Stmts);
5729
5730          --  Skip assignments to temporaries created for in-out parameters.
5731          --  This makes unwarranted assumptions about the shape of the expanded
5732          --  tree for the call, and should be cleaned up ???
5733
5734          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
5735             Next (Stmt);
5736          end loop;
5737
5738          Call := Stmt;
5739
5740          --  Create the inner block to protect the abortable part
5741
5742          Hdle :=  New_List (
5743            Make_Implicit_Exception_Handler (Loc,
5744              Exception_Choices =>
5745                New_List (New_Reference_To (Stand.Abort_Signal, Loc)),
5746              Statements =>
5747                New_List (
5748                  Make_Procedure_Call_Statement (Loc,
5749                    Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)))));
5750
5751          Prepend_To (Astats,
5752            Make_Procedure_Call_Statement (Loc,
5753              Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc)));
5754
5755          Abortable_Block :=
5756            Make_Block_Statement (Loc,
5757              Identifier => New_Reference_To (Blk_Ent, Loc),
5758              Handled_Statement_Sequence =>
5759                Make_Handled_Sequence_Of_Statements (Loc,
5760                  Statements => Astats),
5761              Has_Created_Identifier => True,
5762              Is_Asynchronous_Call_Block => True);
5763
5764          Insert_After (Call,
5765            Make_Block_Statement (Loc,
5766              Handled_Statement_Sequence =>
5767                Make_Handled_Sequence_Of_Statements (Loc,
5768                  Statements => New_List (
5769                    Make_Implicit_Label_Declaration (Loc,
5770                      Defining_Identifier =>
5771                        Blk_Ent,
5772                      Label_Construct =>
5773                        Abortable_Block),
5774                    Abortable_Block),
5775                  Exception_Handlers => Hdle)));
5776
5777          --  Create new call statement
5778
5779          Params := Parameter_Associations (Call);
5780
5781          Append_To (Params,
5782            New_Reference_To (RTE (RE_Asynchronous_Call), Loc));
5783          Append_To (Params,
5784            New_Reference_To (B, Loc));
5785
5786          Rewrite (Call,
5787            Make_Procedure_Call_Statement (Loc,
5788              Name =>
5789                New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
5790              Parameter_Associations => Params));
5791
5792          --  Construct statement sequence for new block
5793
5794          Append_To (Stmts,
5795            Make_Implicit_If_Statement (N,
5796              Condition =>
5797                Make_Op_Not (Loc,
5798                  New_Reference_To (Cancel_Param, Loc)),
5799              Then_Statements => Tstats));
5800
5801          --  Protected the call against abort
5802
5803          Prepend_To (Stmts,
5804            Make_Procedure_Call_Statement (Loc,
5805              Name => New_Reference_To (RTE (RE_Abort_Defer), Loc),
5806              Parameter_Associations => Empty_List));
5807       end if;
5808
5809       Set_Entry_Cancel_Parameter (Blk_Ent, Cancel_Param);
5810
5811       --  The result is the new block
5812
5813       Rewrite (N_Orig,
5814         Make_Block_Statement (Loc,
5815           Declarations => Decls,
5816           Handled_Statement_Sequence =>
5817             Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
5818
5819       Analyze (N_Orig);
5820    end Expand_N_Asynchronous_Select;
5821
5822    -------------------------------------
5823    -- Expand_N_Conditional_Entry_Call --
5824    -------------------------------------
5825
5826    --  The conditional task entry call is converted to a call to
5827    --  Task_Entry_Call:
5828
5829    --    declare
5830    --       B : Boolean;
5831    --       P : parms := (parm, parm, parm);
5832
5833    --    begin
5834    --       Task_Entry_Call
5835    --         (<acceptor-task>,   --  Acceptor
5836    --          <entry-index>,     --  E
5837    --          P'Address,         --  Uninterpreted_Data
5838    --          Conditional_Call,  --  Mode
5839    --          B);                --  Rendezvous_Successful
5840    --       parm := P.param;
5841    --       parm := P.param;
5842    --       ...
5843    --       if B then
5844    --          normal-statements
5845    --       else
5846    --          else-statements
5847    --       end if;
5848    --    end;
5849
5850    --  For a description of the use of P and the assignments after the call,
5851    --  see Expand_N_Entry_Call_Statement. Note that the entry call of the
5852    --  conditional entry call has already been expanded (by the Expand_N_Entry
5853    --  _Call_Statement procedure) as follows:
5854
5855    --    declare
5856    --       P : parms := (parm, parm, parm);
5857    --    begin
5858    --       ... info for in-out parameters
5859    --       Call_Simple (acceptor-task, entry-index, P'Address);
5860    --       parm := P.param;
5861    --       parm := P.param;
5862    --       ...
5863    --    end;
5864
5865    --  so the task at hand is to convert the latter expansion into the former
5866
5867    --  The conditional protected entry call is converted to a call to
5868    --  Protected_Entry_Call:
5869
5870    --    declare
5871    --       P : parms := (parm, parm, parm);
5872    --       Bnn : Communications_Block;
5873
5874    --    begin
5875    --       Protected_Entry_Call
5876    --         (po._object'Access,  --  Object
5877    --          <entry index>,      --  E
5878    --          P'Address,          --  Uninterpreted_Data
5879    --          Conditional_Call,   --  Mode
5880    --          Bnn);               --  Block
5881    --       parm := P.param;
5882    --       parm := P.param;
5883    --       ...
5884    --       if Cancelled (Bnn) then
5885    --          else-statements
5886    --       else
5887    --          normal-statements
5888    --       end if;
5889    --    end;
5890
5891    --  Ada 2005 (AI-345): A dispatching conditional entry call is converted
5892    --  into:
5893
5894    --    declare
5895    --       B : Boolean := False;
5896    --       C : Ada.Tags.Prim_Op_Kind;
5897    --       K : Ada.Tags.Tagged_Kind :=
5898    --             Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
5899    --       P : Parameters := (Param1 .. ParamN);
5900    --       S : Integer;
5901
5902    --    begin
5903    --       if K = Ada.Tags.TK_Limited_Tagged then
5904    --          <dispatching-call>;
5905    --          <triggering-statements>
5906
5907    --       else
5908    --          S :=
5909    --            Ada.Tags.Get_Offset_Index
5910    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
5911
5912    --          _Disp_Conditional_Select (<object>, S, P'Address, C, B);
5913
5914    --          if C = POK_Protected_Entry
5915    --            or else C = POK_Task_Entry
5916    --          then
5917    --             Param1 := P.Param1;
5918    --             ...
5919    --             ParamN := P.ParamN;
5920    --          end if;
5921
5922    --          if B then
5923    --             if C = POK_Procedure
5924    --               or else C = POK_Protected_Procedure
5925    --               or else C = POK_Task_Procedure
5926    --             then
5927    --                <dispatching-call>;
5928    --             end if;
5929
5930    --             <triggering-statements>
5931    --          else
5932    --             <else-statements>
5933    --          end if;
5934    --       end if;
5935    --    end;
5936
5937    procedure Expand_N_Conditional_Entry_Call (N : Node_Id) is
5938       Loc : constant Source_Ptr := Sloc (N);
5939       Alt : constant Node_Id    := Entry_Call_Alternative (N);
5940       Blk : Node_Id             := Entry_Call_Statement (Alt);
5941
5942       Actuals        : List_Id;
5943       Blk_Typ        : Entity_Id;
5944       Call           : Node_Id;
5945       Call_Ent       : Entity_Id;
5946       Conc_Typ_Stmts : List_Id;
5947       Decl           : Node_Id;
5948       Decls          : List_Id;
5949       Formals        : List_Id;
5950       Lim_Typ_Stmts  : List_Id;
5951       N_Stats        : List_Id;
5952       Obj            : Entity_Id;
5953       Param          : Node_Id;
5954       Params         : List_Id;
5955       Stmt           : Node_Id;
5956       Stmts          : List_Id;
5957       Transient_Blk  : Node_Id;
5958       Unpack         : List_Id;
5959
5960       B : Entity_Id;  --  Call status flag
5961       C : Entity_Id;  --  Call kind
5962       K : Entity_Id;  --  Tagged kind
5963       P : Entity_Id;  --  Parameter block
5964       S : Entity_Id;  --  Primitive operation slot
5965
5966    begin
5967       if Ada_Version >= Ada_05
5968         and then Nkind (Blk) = N_Procedure_Call_Statement
5969       then
5970          Extract_Dispatching_Call (Blk, Call_Ent, Obj, Actuals, Formals);
5971
5972          Decls := New_List;
5973          Stmts := New_List;
5974
5975          --  Call status flag processing, generate:
5976          --    B : Boolean := False;
5977
5978          B := Build_B (Loc, Decls);
5979
5980          --  Call kind processing, generate:
5981          --    C : Ada.Tags.Prim_Op_Kind;
5982
5983          C := Build_C (Loc, Decls);
5984
5985          --  Tagged kind processing, generate:
5986          --    K : Ada.Tags.Tagged_Kind :=
5987          --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
5988
5989          K := Build_K (Loc, Decls, Obj);
5990
5991          --  Parameter block processing
5992
5993          Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
5994          P       := Parameter_Block_Pack
5995                       (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
5996
5997          --  Dispatch table slot processing, generate:
5998          --    S : Integer;
5999
6000          S := Build_S (Loc, Decls);
6001
6002          --  Generate:
6003          --    S := Ada.Tags.Get_Offset_Index
6004          --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
6005
6006          Conc_Typ_Stmts :=
6007            New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
6008
6009          --  Generate:
6010          --    _Disp_Conditional_Select (<object>, S, P'Address, C, B);
6011
6012          Append_To (Conc_Typ_Stmts,
6013            Make_Procedure_Call_Statement (Loc,
6014              Name =>
6015                New_Reference_To (
6016                  Find_Prim_Op (Etype (Etype (Obj)),
6017                    Name_uDisp_Conditional_Select),
6018                  Loc),
6019              Parameter_Associations =>
6020                New_List (
6021                  New_Copy_Tree (Obj),            --  <object>
6022                  New_Reference_To (S, Loc),      --  S
6023                  Make_Attribute_Reference (Loc,  --  P'Address
6024                    Prefix =>
6025                      New_Reference_To (P, Loc),
6026                    Attribute_Name =>
6027                      Name_Address),
6028                  New_Reference_To (C, Loc),      --  C
6029                  New_Reference_To (B, Loc))));   --  B
6030
6031          --  Generate:
6032          --    if C = POK_Protected_Entry
6033          --      or else C = POK_Task_Entry
6034          --    then
6035          --       Param1 := P.Param1;
6036          --       ...
6037          --       ParamN := P.ParamN;
6038          --    end if;
6039
6040          Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
6041
6042          --  Generate the if statement only when the packed parameters need
6043          --  explicit assignments to their corresponding actuals.
6044
6045          if Present (Unpack) then
6046             Append_To (Conc_Typ_Stmts,
6047               Make_If_Statement (Loc,
6048
6049                 Condition =>
6050                   Make_Or_Else (Loc,
6051                     Left_Opnd =>
6052                       Make_Op_Eq (Loc,
6053                         Left_Opnd =>
6054                           New_Reference_To (C, Loc),
6055                         Right_Opnd =>
6056                           New_Reference_To (RTE (
6057                             RE_POK_Protected_Entry), Loc)),
6058                     Right_Opnd =>
6059                       Make_Op_Eq (Loc,
6060                         Left_Opnd =>
6061                           New_Reference_To (C, Loc),
6062                         Right_Opnd =>
6063                           New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
6064
6065                  Then_Statements =>
6066                    Unpack));
6067          end if;
6068
6069          --  Generate:
6070          --    if B then
6071          --       if C = POK_Procedure
6072          --         or else C = POK_Protected_Procedure
6073          --         or else C = POK_Task_Procedure
6074          --       then
6075          --          <dispatching-call>
6076          --       end if;
6077          --       <normal-statements>
6078          --    else
6079          --       <else-statements>
6080          --    end if;
6081
6082          N_Stats := New_Copy_List_Tree (Statements (Alt));
6083
6084          Prepend_To (N_Stats,
6085            Make_If_Statement (Loc,
6086              Condition =>
6087                Make_Or_Else (Loc,
6088                  Left_Opnd =>
6089                    Make_Op_Eq (Loc,
6090                      Left_Opnd =>
6091                        New_Reference_To (C, Loc),
6092                      Right_Opnd =>
6093                        New_Reference_To (RTE (RE_POK_Procedure), Loc)),
6094
6095                  Right_Opnd =>
6096                    Make_Or_Else (Loc,
6097                      Left_Opnd =>
6098                        Make_Op_Eq (Loc,
6099                          Left_Opnd =>
6100                            New_Reference_To (C, Loc),
6101                          Right_Opnd =>
6102                            New_Reference_To (RTE (
6103                              RE_POK_Protected_Procedure), Loc)),
6104
6105                      Right_Opnd =>
6106                        Make_Op_Eq (Loc,
6107                          Left_Opnd =>
6108                            New_Reference_To (C, Loc),
6109                          Right_Opnd =>
6110                            New_Reference_To (RTE (
6111                              RE_POK_Task_Procedure), Loc)))),
6112
6113              Then_Statements =>
6114                New_List (Blk)));
6115
6116          Append_To (Conc_Typ_Stmts,
6117            Make_If_Statement (Loc,
6118              Condition => New_Reference_To (B, Loc),
6119              Then_Statements => N_Stats,
6120              Else_Statements => Else_Statements (N)));
6121
6122          --  Generate:
6123          --    <dispatching-call>;
6124          --    <triggering-statements>
6125
6126          Lim_Typ_Stmts := New_Copy_List_Tree (Statements (Alt));
6127          Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (Blk));
6128
6129          --  Generate:
6130          --    if K = Ada.Tags.TK_Limited_Tagged then
6131          --       Lim_Typ_Stmts
6132          --    else
6133          --       Conc_Typ_Stmts
6134          --    end if;
6135
6136          Append_To (Stmts,
6137            Make_If_Statement (Loc,
6138              Condition =>
6139                Make_Op_Eq (Loc,
6140                  Left_Opnd =>
6141                    New_Reference_To (K, Loc),
6142                  Right_Opnd =>
6143                    New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc)),
6144
6145              Then_Statements =>
6146                Lim_Typ_Stmts,
6147
6148              Else_Statements =>
6149                Conc_Typ_Stmts));
6150
6151          Rewrite (N,
6152            Make_Block_Statement (Loc,
6153              Declarations =>
6154                Decls,
6155              Handled_Statement_Sequence =>
6156                Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
6157
6158       --  As described above, The entry alternative is transformed into a
6159       --  block that contains the gnulli call, and possibly assignment
6160       --  statements for in-out parameters. The gnulli call may itself be
6161       --  rewritten into a transient block if some unconstrained parameters
6162       --  require it. We need to retrieve the call to complete its parameter
6163       --  list.
6164
6165       else
6166          Transient_Blk :=
6167            First_Real_Statement (Handled_Statement_Sequence (Blk));
6168
6169          if Present (Transient_Blk)
6170            and then Nkind (Transient_Blk) = N_Block_Statement
6171          then
6172             Blk := Transient_Blk;
6173          end if;
6174
6175          Stmts := Statements (Handled_Statement_Sequence (Blk));
6176          Stmt  := First (Stmts);
6177          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
6178             Next (Stmt);
6179          end loop;
6180
6181          Call   := Stmt;
6182          Params := Parameter_Associations (Call);
6183
6184          if Is_RTE (Entity (Name (Call)), RE_Protected_Entry_Call) then
6185
6186             --  Substitute Conditional_Entry_Call for Simple_Call parameter
6187
6188             Param := First (Params);
6189             while Present (Param)
6190               and then not Is_RTE (Etype (Param), RE_Call_Modes)
6191             loop
6192                Next (Param);
6193             end loop;
6194
6195             pragma Assert (Present (Param));
6196             Rewrite (Param, New_Reference_To (RTE (RE_Conditional_Call), Loc));
6197
6198             Analyze (Param);
6199
6200             --  Find the Communication_Block parameter for the call to the
6201             --  Cancelled function.
6202
6203             Decl := First (Declarations (Blk));
6204             while Present (Decl)
6205               and then not Is_RTE (Etype (Object_Definition (Decl)),
6206                              RE_Communication_Block)
6207             loop
6208                Next (Decl);
6209             end loop;
6210
6211             --  Add an if statement to execute the else part if the call
6212             --  does not succeed (as indicated by the Cancelled predicate).
6213
6214             Append_To (Stmts,
6215               Make_Implicit_If_Statement (N,
6216                 Condition => Make_Function_Call (Loc,
6217                   Name => New_Reference_To (RTE (RE_Cancelled), Loc),
6218                   Parameter_Associations => New_List (
6219                     New_Reference_To (Defining_Identifier (Decl), Loc))),
6220                 Then_Statements => Else_Statements (N),
6221                 Else_Statements => Statements (Alt)));
6222
6223          else
6224             B := Make_Defining_Identifier (Loc, Name_uB);
6225
6226             --  Insert declaration of B in declarations of existing block
6227
6228             if No (Declarations (Blk)) then
6229                Set_Declarations (Blk, New_List);
6230             end if;
6231
6232             Prepend_To (Declarations (Blk),
6233               Make_Object_Declaration (Loc,
6234                 Defining_Identifier => B,
6235                 Object_Definition =>
6236                   New_Reference_To (Standard_Boolean, Loc)));
6237
6238             --  Create new call statement
6239
6240             Append_To (Params,
6241               New_Reference_To (RTE (RE_Conditional_Call), Loc));
6242             Append_To (Params, New_Reference_To (B, Loc));
6243
6244             Rewrite (Call,
6245               Make_Procedure_Call_Statement (Loc,
6246                 Name => New_Reference_To (RTE (RE_Task_Entry_Call), Loc),
6247                 Parameter_Associations => Params));
6248
6249             --  Construct statement sequence for new block
6250
6251             Append_To (Stmts,
6252               Make_Implicit_If_Statement (N,
6253                 Condition => New_Reference_To (B, Loc),
6254                 Then_Statements => Statements (Alt),
6255                 Else_Statements => Else_Statements (N)));
6256          end if;
6257
6258          --  The result is the new block
6259
6260          Rewrite (N,
6261            Make_Block_Statement (Loc,
6262              Declarations => Declarations (Blk),
6263              Handled_Statement_Sequence =>
6264                Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
6265       end if;
6266
6267       Analyze (N);
6268    end Expand_N_Conditional_Entry_Call;
6269
6270    ---------------------------------------
6271    -- Expand_N_Delay_Relative_Statement --
6272    ---------------------------------------
6273
6274    --  Delay statement is implemented as a procedure call to Delay_For
6275    --  defined in Ada.Calendar.Delays in order to reduce the overhead of
6276    --  simple delays imposed by the use of Protected Objects.
6277
6278    procedure Expand_N_Delay_Relative_Statement (N : Node_Id) is
6279       Loc : constant Source_Ptr := Sloc (N);
6280    begin
6281       Rewrite (N,
6282         Make_Procedure_Call_Statement (Loc,
6283           Name => New_Reference_To (RTE (RO_CA_Delay_For), Loc),
6284           Parameter_Associations => New_List (Expression (N))));
6285       Analyze (N);
6286    end Expand_N_Delay_Relative_Statement;
6287
6288    ------------------------------------
6289    -- Expand_N_Delay_Until_Statement --
6290    ------------------------------------
6291
6292    --  Delay Until statement is implemented as a procedure call to
6293    --  Delay_Until defined in Ada.Calendar.Delays and Ada.Real_Time.Delays.
6294
6295    procedure Expand_N_Delay_Until_Statement (N : Node_Id) is
6296       Loc : constant Source_Ptr := Sloc (N);
6297       Typ : Entity_Id;
6298
6299    begin
6300       if Is_RTE (Base_Type (Etype (Expression (N))), RO_CA_Time) then
6301          Typ := RTE (RO_CA_Delay_Until);
6302       else
6303          Typ := RTE (RO_RT_Delay_Until);
6304       end if;
6305
6306       Rewrite (N,
6307         Make_Procedure_Call_Statement (Loc,
6308           Name => New_Reference_To (Typ, Loc),
6309           Parameter_Associations => New_List (Expression (N))));
6310
6311       Analyze (N);
6312    end Expand_N_Delay_Until_Statement;
6313
6314    -------------------------
6315    -- Expand_N_Entry_Body --
6316    -------------------------
6317
6318    procedure Expand_N_Entry_Body (N : Node_Id) is
6319    begin
6320       --  Associate discriminals with the next protected operation body to be
6321       --  expanded.
6322
6323       if Present (Next_Protected_Operation (N)) then
6324          Set_Discriminals (Parent (Current_Scope));
6325       end if;
6326    end Expand_N_Entry_Body;
6327
6328    -----------------------------------
6329    -- Expand_N_Entry_Call_Statement --
6330    -----------------------------------
6331
6332    --  An entry call is expanded into GNARLI calls to implement a simple entry
6333    --  call (see Build_Simple_Entry_Call).
6334
6335    procedure Expand_N_Entry_Call_Statement (N : Node_Id) is
6336       Concval : Node_Id;
6337       Ename   : Node_Id;
6338       Index   : Node_Id;
6339
6340    begin
6341       if No_Run_Time_Mode then
6342          Error_Msg_CRT ("entry call", N);
6343          return;
6344       end if;
6345
6346       --  If this entry call is part of an asynchronous select, don't expand it
6347       --  here; it will be expanded with the select statement. Don't expand
6348       --  timed entry calls either, as they are translated into asynchronous
6349       --  entry calls.
6350
6351       --  ??? This whole approach is questionable; it may be better to go back
6352       --  to allowing the expansion to take place and then attempting to fix it
6353       --  up in Expand_N_Asynchronous_Select. The tricky part is figuring out
6354       --  whether the expanded call is on a task or protected entry.
6355
6356       if (Nkind (Parent (N)) /= N_Triggering_Alternative
6357            or else N /= Triggering_Statement (Parent (N)))
6358         and then (Nkind (Parent (N)) /= N_Entry_Call_Alternative
6359                    or else N /= Entry_Call_Statement (Parent (N))
6360                    or else Nkind (Parent (Parent (N))) /= N_Timed_Entry_Call)
6361       then
6362          Extract_Entry (N, Concval, Ename, Index);
6363          Build_Simple_Entry_Call (N, Concval, Ename, Index);
6364       end if;
6365    end Expand_N_Entry_Call_Statement;
6366
6367    --------------------------------
6368    -- Expand_N_Entry_Declaration --
6369    --------------------------------
6370
6371    --  If there are parameters, then first, each of the formals is marked by
6372    --  setting Is_Entry_Formal. Next a record type is built which is used to
6373    --  hold the parameter values. The name of this record type is entryP where
6374    --  entry is the name of the entry, with an additional corresponding access
6375    --  type called entryPA. The record type has matching components for each
6376    --  formal (the component names are the same as the formal names). For
6377    --  elementary types, the component type matches the formal type. For
6378    --  composite types, an access type is declared (with the name formalA)
6379    --  which designates the formal type, and the type of the component is this
6380    --  access type. Finally the Entry_Component of each formal is set to
6381    --  reference the corresponding record component.
6382
6383    procedure Expand_N_Entry_Declaration (N : Node_Id) is
6384       Loc        : constant Source_Ptr := Sloc (N);
6385       Entry_Ent  : constant Entity_Id  := Defining_Identifier (N);
6386       Components : List_Id;
6387       Formal     : Node_Id;
6388       Ftype      : Entity_Id;
6389       Last_Decl  : Node_Id;
6390       Component  : Entity_Id;
6391       Ctype      : Entity_Id;
6392       Decl       : Node_Id;
6393       Rec_Ent    : Entity_Id;
6394       Acc_Ent    : Entity_Id;
6395
6396    begin
6397       Formal := First_Formal (Entry_Ent);
6398       Last_Decl := N;
6399
6400       --  Most processing is done only if parameters are present
6401
6402       if Present (Formal) then
6403          Components := New_List;
6404
6405          --  Loop through formals
6406
6407          while Present (Formal) loop
6408             Set_Is_Entry_Formal (Formal);
6409             Component :=
6410               Make_Defining_Identifier (Sloc (Formal), Chars (Formal));
6411             Set_Entry_Component (Formal, Component);
6412             Set_Entry_Formal (Component, Formal);
6413             Ftype := Etype (Formal);
6414
6415             --  Declare new access type and then append
6416
6417             Ctype :=
6418               Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
6419
6420             Decl :=
6421               Make_Full_Type_Declaration (Loc,
6422                 Defining_Identifier => Ctype,
6423                 Type_Definition     =>
6424                   Make_Access_To_Object_Definition (Loc,
6425                     All_Present        => True,
6426                     Constant_Present   => Ekind (Formal) = E_In_Parameter,
6427                     Subtype_Indication => New_Reference_To (Ftype, Loc)));
6428
6429             Insert_After (Last_Decl, Decl);
6430             Last_Decl := Decl;
6431
6432             Append_To (Components,
6433               Make_Component_Declaration (Loc,
6434                 Defining_Identifier => Component,
6435                 Component_Definition =>
6436                   Make_Component_Definition (Loc,
6437                     Aliased_Present    => False,
6438                     Subtype_Indication => New_Reference_To (Ctype, Loc))));
6439
6440             Next_Formal_With_Extras (Formal);
6441          end loop;
6442
6443          --  Create the Entry_Parameter_Record declaration
6444
6445          Rec_Ent :=
6446            Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
6447
6448          Decl :=
6449            Make_Full_Type_Declaration (Loc,
6450              Defining_Identifier => Rec_Ent,
6451              Type_Definition     =>
6452                Make_Record_Definition (Loc,
6453                  Component_List =>
6454                    Make_Component_List (Loc,
6455                      Component_Items => Components)));
6456
6457          Insert_After (Last_Decl, Decl);
6458          Last_Decl := Decl;
6459
6460          --  Construct and link in the corresponding access type
6461
6462          Acc_Ent :=
6463            Make_Defining_Identifier (Loc, New_Internal_Name ('A'));
6464
6465          Set_Entry_Parameters_Type (Entry_Ent, Acc_Ent);
6466
6467          Decl :=
6468            Make_Full_Type_Declaration (Loc,
6469              Defining_Identifier => Acc_Ent,
6470              Type_Definition     =>
6471                Make_Access_To_Object_Definition (Loc,
6472                  All_Present        => True,
6473                  Subtype_Indication => New_Reference_To (Rec_Ent, Loc)));
6474
6475          Insert_After (Last_Decl, Decl);
6476          Last_Decl := Decl;
6477       end if;
6478    end Expand_N_Entry_Declaration;
6479
6480    -----------------------------
6481    -- Expand_N_Protected_Body --
6482    -----------------------------
6483
6484    --  Protected bodies are expanded to the completion of the subprograms
6485    --  created for the corresponding protected type. These are a protected and
6486    --  unprotected version of each protected subprogram in the object, a
6487    --  function to calculate each entry barrier, and a procedure to execute the
6488    --  sequence of statements of each protected entry body. For example, for
6489    --  protected type ptype:
6490
6491    --  function entB
6492    --    (O : System.Address;
6493    --     E : Protected_Entry_Index)
6494    --     return Boolean
6495    --  is
6496    --     <discriminant renamings>
6497    --     <private object renamings>
6498    --  begin
6499    --     return <barrier expression>;
6500    --  end entB;
6501
6502    --  procedure pprocN (_object : in out poV;...) is
6503    --     <discriminant renamings>
6504    --     <private object renamings>
6505    --  begin
6506    --     <sequence of statements>
6507    --  end pprocN;
6508
6509    --  procedure pprocP (_object : in out poV;...) is
6510    --     procedure _clean is
6511    --       Pn : Boolean;
6512    --     begin
6513    --       ptypeS (_object, Pn);
6514    --       Unlock (_object._object'Access);
6515    --       Abort_Undefer.all;
6516    --     end _clean;
6517
6518    --  begin
6519    --     Abort_Defer.all;
6520    --     Lock (_object._object'Access);
6521    --     pprocN (_object;...);
6522    --  at end
6523    --     _clean;
6524    --  end pproc;
6525
6526    --  function pfuncN (_object : poV;...) return Return_Type is
6527    --     <discriminant renamings>
6528    --     <private object renamings>
6529    --  begin
6530    --     <sequence of statements>
6531    --  end pfuncN;
6532
6533    --  function pfuncP (_object : poV) return Return_Type is
6534    --     procedure _clean is
6535    --     begin
6536    --        Unlock (_object._object'Access);
6537    --        Abort_Undefer.all;
6538    --     end _clean;
6539
6540    --  begin
6541    --     Abort_Defer.all;
6542    --     Lock (_object._object'Access);
6543    --     return pfuncN (_object);
6544
6545    --  at end
6546    --     _clean;
6547    --  end pfunc;
6548
6549    --  procedure entE
6550    --    (O : System.Address;
6551    --     P : System.Address;
6552    --     E : Protected_Entry_Index)
6553    --  is
6554    --     <discriminant renamings>
6555    --     <private object renamings>
6556    --     type poVP is access poV;
6557    --     _Object : ptVP := ptVP!(O);
6558
6559    --  begin
6560    --     begin
6561    --        <statement sequence>
6562    --        Complete_Entry_Body (_Object._Object);
6563    --     exception
6564    --        when all others =>
6565    --           Exceptional_Complete_Entry_Body (
6566    --             _Object._Object, Get_GNAT_Exception);
6567    --     end;
6568    --  end entE;
6569
6570    --  The type poV is the record created for the protected type to hold
6571    --  the state of the protected object.
6572
6573    procedure Expand_N_Protected_Body (N : Node_Id) is
6574       Loc          : constant Source_Ptr := Sloc (N);
6575       Pid          : constant Entity_Id  := Corresponding_Spec (N);
6576       Op_Body      : Node_Id;
6577       Op_Decl      : Node_Id;
6578       Op_Id        : Entity_Id;
6579       Disp_Op_Body : Node_Id;
6580       New_Op_Body  : Node_Id;
6581       Current_Node : Node_Id;
6582       Num_Entries  : Natural := 0;
6583
6584       function Build_Dispatching_Subprogram_Body
6585         (N        : Node_Id;
6586          Pid      : Node_Id;
6587          Prot_Bod : Node_Id) return Node_Id;
6588       --  Build a dispatching version of the protected subprogram body. The
6589       --  newly generated subprogram contains a call to the original protected
6590       --  body. The following code is generated:
6591       --
6592       --  function <protected-function-name> (Param1 .. ParamN) return
6593       --    <return-type> is
6594       --  begin
6595       --     return <protected-function-name>P (Param1 .. ParamN);
6596       --  end <protected-function-name>;
6597       --
6598       --  or
6599       --
6600       --  procedure <protected-procedure-name> (Param1 .. ParamN) is
6601       --  begin
6602       --     <protected-procedure-name>P (Param1 .. ParamN);
6603       --  end <protected-procedure-name>
6604
6605       ---------------------------------------
6606       -- Build_Dispatching_Subprogram_Body --
6607       ---------------------------------------
6608
6609       function Build_Dispatching_Subprogram_Body
6610         (N        : Node_Id;
6611          Pid      : Node_Id;
6612          Prot_Bod : Node_Id) return Node_Id
6613       is
6614          Loc     : constant Source_Ptr := Sloc (N);
6615          Actuals : List_Id;
6616          Formal  : Node_Id;
6617          Spec    : Node_Id;
6618          Stmts   : List_Id;
6619
6620       begin
6621          --  Generate a specification without a letter suffix in order to
6622          --  override an interface function or procedure.
6623
6624          Spec :=
6625            Build_Protected_Sub_Specification (N, Pid, Dispatching_Mode);
6626
6627          --  The formal parameters become the actuals of the protected
6628          --  function or procedure call.
6629
6630          Actuals := New_List;
6631          Formal  := First (Parameter_Specifications (Spec));
6632          while Present (Formal) loop
6633             Append_To (Actuals,
6634               Make_Identifier (Loc, Chars (Defining_Identifier (Formal))));
6635
6636             Next (Formal);
6637          end loop;
6638
6639          if Nkind (Spec) = N_Procedure_Specification then
6640             Stmts :=
6641               New_List (
6642                 Make_Procedure_Call_Statement (Loc,
6643                   Name =>
6644                     New_Reference_To (Corresponding_Spec (Prot_Bod), Loc),
6645                   Parameter_Associations => Actuals));
6646          else
6647             pragma Assert (Nkind (Spec) = N_Function_Specification);
6648
6649             Stmts :=
6650               New_List (
6651                 Make_Simple_Return_Statement (Loc,
6652                   Expression =>
6653                     Make_Function_Call (Loc,
6654                       Name =>
6655                         New_Reference_To (Corresponding_Spec (Prot_Bod), Loc),
6656                       Parameter_Associations => Actuals)));
6657          end if;
6658
6659          return
6660            Make_Subprogram_Body (Loc,
6661              Declarations  => Empty_List,
6662              Specification => Spec,
6663              Handled_Statement_Sequence =>
6664                Make_Handled_Sequence_Of_Statements (Loc, Stmts));
6665       end Build_Dispatching_Subprogram_Body;
6666
6667    --  Start of processing for Expand_N_Protected_Body
6668
6669    begin
6670       if No_Run_Time_Mode then
6671          Error_Msg_CRT ("protected body", N);
6672          return;
6673       end if;
6674
6675       if Nkind (Parent (N)) = N_Subunit then
6676
6677          --  This is the proper body corresponding to a stub. The declarations
6678          --  must be inserted at the point of the stub, which is in the decla-
6679          --  rative part of the parent unit.
6680
6681          Current_Node := Corresponding_Stub (Parent (N));
6682
6683       else
6684          Current_Node := N;
6685       end if;
6686
6687       Op_Body := First (Declarations (N));
6688
6689       --  The protected body is replaced with the bodies of its
6690       --  protected operations, and the declarations for internal objects
6691       --  that may have been created for entry family bounds.
6692
6693       Rewrite (N, Make_Null_Statement (Sloc (N)));
6694       Analyze (N);
6695
6696       while Present (Op_Body) loop
6697          case Nkind (Op_Body) is
6698             when N_Subprogram_Declaration =>
6699                null;
6700
6701             when N_Subprogram_Body =>
6702
6703                --  Exclude functions created to analyze defaults
6704
6705                if not Is_Eliminated (Defining_Entity (Op_Body))
6706                  and then not Is_Eliminated (Corresponding_Spec (Op_Body))
6707                then
6708                   New_Op_Body :=
6709                     Build_Unprotected_Subprogram_Body (Op_Body, Pid);
6710
6711                   --  Propagate the finalization chain to the new body.
6712                   --  In the unlikely event that the subprogram contains a
6713                   --  declaration or allocator for an object that requires
6714                   --  finalization, the corresponding chain is created when
6715                   --  analyzing the body, and attached to its entity. This
6716                   --  entity is not further elaborated, and so the chain
6717                   --  properly belongs to the newly created subprogram body.
6718
6719                   if Present
6720                     (Finalization_Chain_Entity (Defining_Entity (Op_Body)))
6721                   then
6722                      Set_Finalization_Chain_Entity
6723                        (Protected_Body_Subprogram
6724                          (Corresponding_Spec (Op_Body)),
6725                        Finalization_Chain_Entity (Defining_Entity (Op_Body)));
6726                      Set_Analyzed
6727                          (Handled_Statement_Sequence (New_Op_Body), False);
6728                   end if;
6729
6730                   Insert_After (Current_Node, New_Op_Body);
6731                   Current_Node := New_Op_Body;
6732                   Analyze (New_Op_Body);
6733
6734                   --  Build the corresponding protected operation. It may
6735                   --  appear that this is needed only if this is a visible
6736                   --  operation of the type, or if it is an interrupt handler,
6737                   --  and this was the strategy used previously in GNAT.
6738                   --  However, the operation may be exported through a
6739                   --  'Access to an external caller. This is the common idiom
6740                   --  in code that uses the Ada 2005 Timing_Events package
6741                   --  As a result we need to produce the protected body for
6742                   --  both visible and private operations.
6743
6744                   if Present (Corresponding_Spec (Op_Body)) then
6745                      Op_Decl :=
6746                        Unit_Declaration_Node (Corresponding_Spec (Op_Body));
6747
6748                      if Nkind (Parent (Op_Decl)) =
6749                           N_Protected_Definition
6750                      then
6751                         New_Op_Body :=
6752                           Build_Protected_Subprogram_Body (
6753                             Op_Body, Pid, Specification (New_Op_Body));
6754
6755                         Insert_After (Current_Node, New_Op_Body);
6756                         Analyze (New_Op_Body);
6757
6758                         Current_Node := New_Op_Body;
6759
6760                         --  Generate an overriding primitive operation body for
6761                         --  this subprogram if the protected type implements
6762                         --  an interface.
6763
6764                         if Ada_Version >= Ada_05
6765                           and then Present (Abstract_Interfaces (
6766                                      Corresponding_Record_Type (Pid)))
6767                         then
6768                            Disp_Op_Body :=
6769                              Build_Dispatching_Subprogram_Body (
6770                                Op_Body, Pid, New_Op_Body);
6771
6772                            Insert_After (Current_Node, Disp_Op_Body);
6773                            Analyze (Disp_Op_Body);
6774
6775                            Current_Node := Disp_Op_Body;
6776                         end if;
6777                      end if;
6778                   end if;
6779                end if;
6780
6781             when N_Entry_Body =>
6782                Op_Id := Defining_Identifier (Op_Body);
6783                Num_Entries := Num_Entries + 1;
6784
6785                New_Op_Body := Build_Protected_Entry (Op_Body, Op_Id, Pid);
6786
6787                Insert_After (Current_Node, New_Op_Body);
6788                Current_Node := New_Op_Body;
6789                Analyze (New_Op_Body);
6790
6791             when N_Implicit_Label_Declaration =>
6792                null;
6793
6794             when N_Itype_Reference =>
6795                Insert_After (Current_Node, New_Copy (Op_Body));
6796
6797             when N_Freeze_Entity =>
6798                New_Op_Body := New_Copy (Op_Body);
6799
6800                if Present (Entity (Op_Body))
6801                  and then Freeze_Node (Entity (Op_Body)) = Op_Body
6802                then
6803                   Set_Freeze_Node (Entity (Op_Body), New_Op_Body);
6804                end if;
6805
6806                Insert_After (Current_Node, New_Op_Body);
6807                Current_Node := New_Op_Body;
6808                Analyze (New_Op_Body);
6809
6810             when N_Pragma =>
6811                New_Op_Body := New_Copy (Op_Body);
6812                Insert_After (Current_Node, New_Op_Body);
6813                Current_Node := New_Op_Body;
6814                Analyze (New_Op_Body);
6815
6816             when N_Object_Declaration =>
6817                pragma Assert (not Comes_From_Source (Op_Body));
6818                New_Op_Body := New_Copy (Op_Body);
6819                Insert_After (Current_Node, New_Op_Body);
6820                Current_Node := New_Op_Body;
6821                Analyze (New_Op_Body);
6822
6823             when others =>
6824                raise Program_Error;
6825
6826          end case;
6827
6828          Next (Op_Body);
6829       end loop;
6830
6831       --  Finally, create the body of the function that maps an entry index
6832       --  into the corresponding body index, except when there is no entry,
6833       --  or in a ravenscar-like profile.
6834
6835       if Corresponding_Runtime_Package (Pid) =
6836            System_Tasking_Protected_Objects_Entries
6837       then
6838          New_Op_Body := Build_Find_Body_Index (Pid);
6839          Insert_After (Current_Node, New_Op_Body);
6840          Current_Node := New_Op_Body;
6841          Analyze (New_Op_Body);
6842       end if;
6843
6844       --  Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
6845       --  the protected body. At this point the entry specs have been created,
6846       --  frozen and included in the dispatch table for the protected type.
6847
6848       pragma Assert (Present (Corresponding_Record_Type (Pid)));
6849
6850       if Ada_Version >= Ada_05
6851         and then Present (Protected_Definition (Parent (Pid)))
6852         and then Present (Abstract_Interfaces
6853                            (Corresponding_Record_Type (Pid)))
6854       then
6855          declare
6856             Vis_Decl  : Node_Id :=
6857                           First (Visible_Declarations
6858                                   (Protected_Definition (Parent (Pid))));
6859             Wrap_Body : Node_Id;
6860
6861          begin
6862             --  Examine the visible declarations of the protected type, looking
6863             --  for an entry declaration. We do not consider entry families
6864             --  since they cannot have dispatching operations, thus they do not
6865             --  need entry wrappers.
6866
6867             while Present (Vis_Decl) loop
6868                if Nkind (Vis_Decl) = N_Entry_Declaration then
6869                   Wrap_Body :=
6870                     Build_Wrapper_Body (Loc,
6871                       Proc_Nam => Defining_Identifier (Vis_Decl),
6872                       Obj_Typ  => Corresponding_Record_Type (Pid),
6873                       Formals  => Parameter_Specifications (Vis_Decl));
6874
6875                   if Wrap_Body /= Empty then
6876                      Insert_After (Current_Node, Wrap_Body);
6877                      Current_Node := Wrap_Body;
6878
6879                      Analyze (Wrap_Body);
6880                   end if;
6881
6882                elsif Nkind (Vis_Decl) = N_Subprogram_Declaration then
6883                   Wrap_Body :=
6884                     Build_Wrapper_Body (Loc,
6885                       Proc_Nam => Defining_Unit_Name
6886                                         (Specification (Vis_Decl)),
6887                       Obj_Typ  => Corresponding_Record_Type (Pid),
6888                       Formals  => Parameter_Specifications
6889                                         (Specification (Vis_Decl)));
6890
6891                   if Wrap_Body /= Empty then
6892                      Insert_After (Current_Node, Wrap_Body);
6893                      Current_Node := Wrap_Body;
6894
6895                      Analyze (Wrap_Body);
6896                   end if;
6897                end if;
6898
6899                Next (Vis_Decl);
6900             end loop;
6901          end;
6902       end if;
6903    end Expand_N_Protected_Body;
6904
6905    -----------------------------------------
6906    -- Expand_N_Protected_Type_Declaration --
6907    -----------------------------------------
6908
6909    --  First we create a corresponding record type declaration used to
6910    --  represent values of this protected type.
6911    --  The general form of this type declaration is
6912
6913    --    type poV (discriminants) is record
6914    --      _Object       : aliased <kind>Protection
6915    --         [(<entry count> [, <handler count>])];
6916    --      [entry_family  : array (bounds) of Void;]
6917    --      <private data fields>
6918    --    end record;
6919
6920    --  The discriminants are present only if the corresponding protected type
6921    --  has discriminants, and they exactly mirror the protected type
6922    --  discriminants. The private data fields similarly mirror the private
6923    --  declarations of the protected type.
6924
6925    --  The Object field is always present. It contains RTS specific data used
6926    --  to control the protected object. It is declared as Aliased so that it
6927    --  can be passed as a pointer to the RTS. This allows the protected record
6928    --  to be referenced within RTS data structures. An appropriate Protection
6929    --  type and discriminant are generated.
6930
6931    --  The Service field is present for protected objects with entries. It
6932    --  contains sufficient information to allow the entry service procedure for
6933    --  this object to be called when the object is not known till runtime.
6934
6935    --  One entry_family component is present for each entry family in the
6936    --  task definition (see Expand_N_Task_Type_Declaration).
6937
6938    --  When a protected object is declared, an instance of the protected type
6939    --  value record is created. The elaboration of this declaration creates the
6940    --  correct bounds for the entry families, and also evaluates the priority
6941    --  expression if needed. The initialization routine for the protected type
6942    --  itself then calls Initialize_Protection with appropriate parameters to
6943    --  initialize the value of the Task_Id field. Install_Handlers may be also
6944    --  called if a pragma Attach_Handler applies.
6945
6946    --  Note: this record is passed to the subprograms created by the expansion
6947    --  of protected subprograms and entries. It is an in parameter to protected
6948    --  functions and an in out parameter to procedures and entry bodies. The
6949    --  Entity_Id for this created record type is placed in the
6950    --  Corresponding_Record_Type field of the associated protected type entity.
6951
6952    --  Next we create a procedure specifications for protected subprograms and
6953    --  entry bodies. For each protected subprograms two subprograms are
6954    --  created, an unprotected and a protected version. The unprotected version
6955    --  is called from within other operations of the same protected object.
6956
6957    --  We also build the call to register the procedure if a pragma
6958    --  Interrupt_Handler applies.
6959
6960    --  A single subprogram is created to service all entry bodies; it has an
6961    --  additional boolean out parameter indicating that the previous entry call
6962    --  made by the current task was serviced immediately, i.e. not by proxy.
6963    --  The O parameter contains a pointer to a record object of the type
6964    --  described above. An untyped interface is used here to allow this
6965    --  procedure to be called in places where the type of the object to be
6966    --  serviced is not known. This must be done, for example, when a call that
6967    --  may have been requeued is cancelled; the corresponding object must be
6968    --  serviced, but which object that is not known till runtime.
6969
6970    --  procedure ptypeS
6971    --    (O : System.Address; P : out Boolean);
6972    --  procedure pprocN (_object : in out poV);
6973    --  procedure pproc (_object : in out poV);
6974    --  function pfuncN (_object : poV);
6975    --  function pfunc (_object : poV);
6976    --  ...
6977
6978    --  Note that this must come after the record type declaration, since
6979    --  the specs refer to this type.
6980
6981    procedure Expand_N_Protected_Type_Declaration (N : Node_Id) is
6982       Loc      : constant Source_Ptr := Sloc (N);
6983       Prot_Typ : constant Entity_Id  := Defining_Identifier (N);
6984
6985       Pdef     : constant Node_Id    := Protected_Definition (N);
6986       --  This contains two lists; one for visible and one for private decls
6987
6988       Rec_Decl     : Node_Id;
6989       Cdecls       : List_Id;
6990       Discr_Map    : constant Elist_Id := New_Elmt_List;
6991       Priv         : Node_Id;
6992       New_Priv     : Node_Id;
6993       Comp         : Node_Id;
6994       Comp_Id      : Entity_Id;
6995       Sub          : Node_Id;
6996       Current_Node : Node_Id := N;
6997       Bdef         : Entity_Id := Empty; -- avoid uninit warning
6998       Edef         : Entity_Id := Empty; -- avoid uninit warning
6999       Entries_Aggr : Node_Id;
7000       Body_Id      : Entity_Id;
7001       Body_Arr     : Node_Id;
7002       E_Count      : Int;
7003       Object_Comp  : Node_Id;
7004
7005       procedure Register_Handler;
7006       --  For a protected operation that is an interrupt handler, add the
7007       --  freeze action that will register it as such.
7008
7009       ----------------------
7010       -- Register_Handler --
7011       ----------------------
7012
7013       procedure Register_Handler is
7014
7015          --  All semantic checks already done in Sem_Prag
7016
7017          Prot_Proc    : constant Entity_Id :=
7018                        Defining_Unit_Name
7019                          (Specification (Current_Node));
7020
7021          Proc_Address : constant Node_Id :=
7022                           Make_Attribute_Reference (Loc,
7023                           Prefix => New_Reference_To (Prot_Proc, Loc),
7024                           Attribute_Name => Name_Address);
7025
7026          RTS_Call     : constant Entity_Id :=
7027                           Make_Procedure_Call_Statement (Loc,
7028                             Name =>
7029                               New_Reference_To (
7030                                 RTE (RE_Register_Interrupt_Handler), Loc),
7031                             Parameter_Associations =>
7032                               New_List (Proc_Address));
7033       begin
7034          Append_Freeze_Action (Prot_Proc, RTS_Call);
7035       end Register_Handler;
7036
7037    --  Start of processing for Expand_N_Protected_Type_Declaration
7038
7039    begin
7040       if Present (Corresponding_Record_Type (Prot_Typ)) then
7041          return;
7042       else
7043          Rec_Decl := Build_Corresponding_Record (N, Prot_Typ, Loc);
7044       end if;
7045
7046       Cdecls := Component_Items (Component_List (Type_Definition (Rec_Decl)));
7047
7048       --  Ada 2005 (AI-345): Propagate the attribute that contains the list
7049       --  of implemented interfaces.
7050
7051       Set_Interface_List (Type_Definition (Rec_Decl), Interface_List (N));
7052
7053       Qualify_Entity_Names (N);
7054
7055       --  If the type has discriminants, their occurrences in the declaration
7056       --  have been replaced by the corresponding discriminals. For components
7057       --  that are constrained by discriminants, their homologues in the
7058       --  corresponding record type must refer to the discriminants of that
7059       --  record, so we must apply a new renaming to subtypes_indications:
7060
7061       --     protected discriminant => discriminal => record discriminant
7062
7063       --  This replacement is not applied to default expressions, for which
7064       --  the discriminal is correct.
7065
7066       if Has_Discriminants (Prot_Typ) then
7067          declare
7068             Disc : Entity_Id;
7069             Decl : Node_Id;
7070
7071          begin
7072             Disc := First_Discriminant (Prot_Typ);
7073             Decl := First (Discriminant_Specifications (Rec_Decl));
7074             while Present (Disc) loop
7075                Append_Elmt (Discriminal (Disc), Discr_Map);
7076                Append_Elmt (Defining_Identifier (Decl), Discr_Map);
7077                Next_Discriminant (Disc);
7078                Next (Decl);
7079             end loop;
7080          end;
7081       end if;
7082
7083       --  Fill in the component declarations
7084
7085       --  Add components for entry families. For each entry family, create an
7086       --  anonymous type declaration with the same size, and analyze the type.
7087
7088       Collect_Entry_Families (Loc, Cdecls, Current_Node, Prot_Typ);
7089
7090       --  Prepend the _Object field with the right type to the component list.
7091       --  We need to compute the number of entries, and in some cases the
7092       --  number of Attach_Handler pragmas.
7093
7094       declare
7095          Ritem              : Node_Id;
7096          Num_Attach_Handler : Int := 0;
7097          Protection_Subtype : Node_Id;
7098          Entry_Count_Expr   : constant Node_Id :=
7099                                 Build_Entry_Count_Expression
7100                                   (Prot_Typ, Cdecls, Loc);
7101
7102       begin
7103          --  Could this be simplified using Corresponding_Runtime_Package???
7104
7105          if Has_Attach_Handler (Prot_Typ) then
7106             Ritem := First_Rep_Item (Prot_Typ);
7107             while Present (Ritem) loop
7108                if Nkind (Ritem) = N_Pragma
7109                  and then Pragma_Name (Ritem) = Name_Attach_Handler
7110                then
7111                   Num_Attach_Handler := Num_Attach_Handler + 1;
7112                end if;
7113
7114                Next_Rep_Item (Ritem);
7115             end loop;
7116
7117             if Restricted_Profile then
7118                if Has_Entries (Prot_Typ) then
7119                   Protection_Subtype :=
7120                     New_Reference_To (RTE (RE_Protection_Entry), Loc);
7121                else
7122                   Protection_Subtype :=
7123                     New_Reference_To (RTE (RE_Protection), Loc);
7124                end if;
7125             else
7126                Protection_Subtype :=
7127                  Make_Subtype_Indication
7128                    (Sloc => Loc,
7129                     Subtype_Mark =>
7130                       New_Reference_To
7131                         (RTE (RE_Static_Interrupt_Protection), Loc),
7132                     Constraint =>
7133                       Make_Index_Or_Discriminant_Constraint (
7134                         Sloc => Loc,
7135                         Constraints => New_List (
7136                           Entry_Count_Expr,
7137                           Make_Integer_Literal (Loc, Num_Attach_Handler))));
7138             end if;
7139
7140          elsif Has_Interrupt_Handler (Prot_Typ) then
7141             Protection_Subtype :=
7142                Make_Subtype_Indication (
7143                  Sloc => Loc,
7144                  Subtype_Mark => New_Reference_To
7145                    (RTE (RE_Dynamic_Interrupt_Protection), Loc),
7146                  Constraint =>
7147                    Make_Index_Or_Discriminant_Constraint (
7148                      Sloc => Loc,
7149                      Constraints => New_List (Entry_Count_Expr)));
7150
7151          --  Type has explicit entries or generated primitive entry wrappers
7152
7153          elsif Has_Entries (Prot_Typ)
7154            or else (Ada_Version >= Ada_05
7155                       and then Present (Interface_List (N)))
7156          then
7157             case Corresponding_Runtime_Package (Prot_Typ) is
7158                when System_Tasking_Protected_Objects_Entries =>
7159                   Protection_Subtype :=
7160                      Make_Subtype_Indication (Loc,
7161                        Subtype_Mark =>
7162                          New_Reference_To (RTE (RE_Protection_Entries), Loc),
7163                        Constraint =>
7164                          Make_Index_Or_Discriminant_Constraint (
7165                            Sloc => Loc,
7166                            Constraints => New_List (Entry_Count_Expr)));
7167
7168                when System_Tasking_Protected_Objects_Single_Entry =>
7169                   Protection_Subtype :=
7170                     New_Reference_To (RTE (RE_Protection_Entry), Loc);
7171
7172                when others =>
7173                   raise Program_Error;
7174             end case;
7175
7176          else
7177             Protection_Subtype := New_Reference_To (RTE (RE_Protection), Loc);
7178          end if;
7179
7180          Object_Comp :=
7181            Make_Component_Declaration (Loc,
7182              Defining_Identifier =>
7183                Make_Defining_Identifier (Loc, Name_uObject),
7184              Component_Definition =>
7185                Make_Component_Definition (Loc,
7186                  Aliased_Present    => True,
7187                  Subtype_Indication => Protection_Subtype));
7188       end;
7189
7190       pragma Assert (Present (Pdef));
7191
7192       --  Add private field components
7193
7194       if Present (Private_Declarations (Pdef)) then
7195          Priv := First (Private_Declarations (Pdef));
7196
7197          while Present (Priv) loop
7198
7199             if Nkind (Priv) = N_Component_Declaration then
7200
7201                --  The component definition consists of a subtype indication,
7202                --  or (in Ada 2005) an access definition. Make a copy of the
7203                --  proper definition.
7204
7205                declare
7206                   Old_Comp : constant Node_Id   := Component_Definition (Priv);
7207                   Pent     : constant Entity_Id := Defining_Identifier (Priv);
7208                   New_Comp : Node_Id;
7209
7210                begin
7211                   if Present (Subtype_Indication (Old_Comp)) then
7212                      New_Comp :=
7213                        Make_Component_Definition (Sloc (Pent),
7214                          Aliased_Present    => False,
7215                          Subtype_Indication =>
7216                            New_Copy_Tree (Subtype_Indication (Old_Comp),
7217                                            Discr_Map));
7218                   else
7219                      New_Comp :=
7220                        Make_Component_Definition (Sloc (Pent),
7221                          Aliased_Present    => False,
7222                          Access_Definition  =>
7223                            New_Copy_Tree (Access_Definition (Old_Comp),
7224                                            Discr_Map));
7225                   end if;
7226
7227                   New_Priv :=
7228                     Make_Component_Declaration (Loc,
7229                       Defining_Identifier =>
7230                         Make_Defining_Identifier (Sloc (Pent), Chars (Pent)),
7231                       Component_Definition => New_Comp,
7232                       Expression => Expression (Priv));
7233
7234                   Append_To (Cdecls, New_Priv);
7235                end;
7236
7237             elsif Nkind (Priv) = N_Subprogram_Declaration then
7238
7239                --  Make the unprotected version of the subprogram available
7240                --  for expansion of intra object calls. There is need for
7241                --  a protected version only if the subprogram is an interrupt
7242                --  handler, otherwise  this operation can only be called from
7243                --  within the body.
7244
7245                Sub :=
7246                  Make_Subprogram_Declaration (Loc,
7247                    Specification =>
7248                      Build_Protected_Sub_Specification
7249                        (Priv, Prot_Typ, Unprotected_Mode));
7250
7251                Insert_After (Current_Node, Sub);
7252                Analyze (Sub);
7253
7254                Set_Protected_Body_Subprogram
7255                  (Defining_Unit_Name (Specification (Priv)),
7256                   Defining_Unit_Name (Specification (Sub)));
7257
7258                Current_Node := Sub;
7259
7260                Sub :=
7261                  Make_Subprogram_Declaration (Loc,
7262                    Specification =>
7263                      Build_Protected_Sub_Specification
7264                        (Priv, Prot_Typ, Protected_Mode));
7265
7266                Insert_After (Current_Node, Sub);
7267                Analyze (Sub);
7268                Current_Node := Sub;
7269
7270                if Is_Interrupt_Handler
7271                  (Defining_Unit_Name (Specification (Priv)))
7272                then
7273                   if not Restricted_Profile then
7274                      Register_Handler;
7275                   end if;
7276                end if;
7277             end if;
7278
7279             Next (Priv);
7280          end loop;
7281       end if;
7282
7283       --  Put the _Object component after the private component so that it
7284       --  be finalized early as required by 9.4 (20)
7285
7286       Append_To (Cdecls, Object_Comp);
7287
7288       Insert_After (Current_Node, Rec_Decl);
7289       Current_Node := Rec_Decl;
7290
7291       --  Analyze the record declaration immediately after construction,
7292       --  because the initialization procedure is needed for single object
7293       --  declarations before the next entity is analyzed (the freeze call
7294       --  that generates this initialization procedure is found below).
7295
7296       Analyze (Rec_Decl, Suppress => All_Checks);
7297
7298       --  Ada 2005 (AI-345): Construct the primitive entry wrappers before
7299       --  the corresponding record is frozen
7300
7301       if Ada_Version >= Ada_05
7302         and then Present (Visible_Declarations (Pdef))
7303         and then Present (Corresponding_Record_Type
7304                           (Defining_Identifier (Parent (Pdef))))
7305         and then Present (Abstract_Interfaces
7306                           (Corresponding_Record_Type
7307                            (Defining_Identifier (Parent (Pdef)))))
7308       then
7309          declare
7310             Current_Node : Node_Id := Rec_Decl;
7311             Vis_Decl     : Node_Id;
7312             Wrap_Spec    : Node_Id;
7313             New_N        : Node_Id;
7314
7315          begin
7316             --  Examine the visible declarations of the protected type, looking
7317             --  for declarations of entries, and subprograms. We do not
7318             --  consider entry families since they cannot have dispatching
7319             --  operations, thus they do not need entry wrappers.
7320
7321             Vis_Decl := First (Visible_Declarations (Pdef));
7322
7323             while Present (Vis_Decl) loop
7324
7325                Wrap_Spec := Empty;
7326
7327                if Nkind (Vis_Decl) = N_Entry_Declaration
7328                  and then No (Discrete_Subtype_Definition (Vis_Decl))
7329                then
7330                   Wrap_Spec :=
7331                     Build_Wrapper_Spec (Loc,
7332                       Proc_Nam => Defining_Identifier (Vis_Decl),
7333                       Obj_Typ  => Defining_Identifier (Rec_Decl),
7334                       Formals  => Parameter_Specifications (Vis_Decl));
7335
7336                elsif Nkind (Vis_Decl) = N_Subprogram_Declaration then
7337                   Wrap_Spec :=
7338                     Build_Wrapper_Spec (Loc,
7339                       Proc_Nam => Defining_Unit_Name
7340                                     (Specification (Vis_Decl)),
7341                       Obj_Typ  => Defining_Identifier (Rec_Decl),
7342                       Formals  => Parameter_Specifications
7343                                     (Specification (Vis_Decl)));
7344
7345                end if;
7346
7347                if Wrap_Spec /= Empty then
7348                   New_N := Make_Subprogram_Declaration (Loc,
7349                              Specification => Wrap_Spec);
7350
7351                   Insert_After (Current_Node, New_N);
7352                   Current_Node := New_N;
7353
7354                   Analyze (New_N);
7355                end if;
7356
7357                Next (Vis_Decl);
7358             end loop;
7359          end;
7360       end if;
7361
7362       --  Collect pointers to entry bodies and their barriers, to be placed
7363       --  in the Entry_Bodies_Array for the type. For each entry/family we
7364       --  add an expression to the aggregate which is the initial value of
7365       --  this array. The array is declared after all protected subprograms.
7366
7367       if Has_Entries (Prot_Typ) then
7368          Entries_Aggr :=
7369            Make_Aggregate (Loc, Expressions => New_List);
7370
7371       else
7372          Entries_Aggr := Empty;
7373       end if;
7374
7375       --  Build two new procedure specifications for each protected subprogram;
7376       --  one to call from outside the object and one to call from inside.
7377       --  Build a barrier function and an entry body action procedure
7378       --  specification for each protected entry. Initialize the entry body
7379       --  array. If subprogram is flagged as eliminated, do not generate any
7380       --  internal operations.
7381
7382       E_Count := 0;
7383
7384       Comp := First (Visible_Declarations (Pdef));
7385
7386       while Present (Comp) loop
7387          if Nkind (Comp) = N_Subprogram_Declaration
7388            and then not Is_Eliminated (Defining_Entity (Comp))
7389          then
7390             Sub :=
7391               Make_Subprogram_Declaration (Loc,
7392                 Specification =>
7393                   Build_Protected_Sub_Specification
7394                     (Comp, Prot_Typ, Unprotected_Mode));
7395
7396             Insert_After (Current_Node, Sub);
7397             Analyze (Sub);
7398
7399             Set_Protected_Body_Subprogram
7400               (Defining_Unit_Name (Specification (Comp)),
7401                Defining_Unit_Name (Specification (Sub)));
7402
7403             --  Make the protected version of the subprogram available for
7404             --  expansion of external calls.
7405
7406             Current_Node := Sub;
7407
7408             Sub :=
7409               Make_Subprogram_Declaration (Loc,
7410                 Specification =>
7411                   Build_Protected_Sub_Specification
7412                     (Comp, Prot_Typ, Protected_Mode));
7413
7414             Insert_After (Current_Node, Sub);
7415             Analyze (Sub);
7416
7417             Current_Node := Sub;
7418
7419             --  Generate an overriding primitive operation specification for
7420             --  this subprogram if the protected type implements an interface.
7421
7422             if Ada_Version >= Ada_05
7423               and then
7424                 Present (Abstract_Interfaces
7425                           (Corresponding_Record_Type (Prot_Typ)))
7426             then
7427                Sub :=
7428                  Make_Subprogram_Declaration (Loc,
7429                    Specification =>
7430                      Build_Protected_Sub_Specification
7431                        (Comp, Prot_Typ, Dispatching_Mode));
7432
7433                Insert_After (Current_Node, Sub);
7434                Analyze (Sub);
7435
7436                Current_Node := Sub;
7437             end if;
7438
7439             --  If a pragma Interrupt_Handler applies, build and add a call to
7440             --  Register_Interrupt_Handler to the freezing actions of the
7441             --  protected version (Current_Node) of the subprogram:
7442
7443             --    system.interrupts.register_interrupt_handler
7444             --       (prot_procP'address);
7445
7446             if not Restricted_Profile
7447               and then Is_Interrupt_Handler
7448                          (Defining_Unit_Name (Specification (Comp)))
7449             then
7450                Register_Handler;
7451             end if;
7452
7453          elsif Nkind (Comp) = N_Entry_Declaration then
7454             E_Count := E_Count + 1;
7455             Comp_Id := Defining_Identifier (Comp);
7456
7457             Edef :=
7458               Make_Defining_Identifier (Loc,
7459                 Build_Selected_Name (Prot_Typ, Comp_Id, 'E'));
7460             Sub :=
7461               Make_Subprogram_Declaration (Loc,
7462                 Specification =>
7463                   Build_Protected_Entry_Specification (Loc, Edef, Comp_Id));
7464
7465             Insert_After (Current_Node, Sub);
7466             Analyze (Sub);
7467
7468             Set_Protected_Body_Subprogram
7469               (Defining_Identifier (Comp),
7470                Defining_Unit_Name (Specification (Sub)));
7471
7472             Current_Node := Sub;
7473
7474             Bdef :=
7475               Make_Defining_Identifier (Loc,
7476                 Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'B'));
7477             Sub :=
7478               Make_Subprogram_Declaration (Loc,
7479                 Specification =>
7480                   Build_Barrier_Function_Specification (Loc, Bdef));
7481
7482             Insert_After (Current_Node, Sub);
7483             Analyze (Sub);
7484             Set_Protected_Body_Subprogram (Bdef, Bdef);
7485             Set_Barrier_Function (Comp_Id, Bdef);
7486             Set_Scope (Bdef, Scope (Comp_Id));
7487             Current_Node := Sub;
7488
7489             --  Collect pointers to the protected subprogram and the barrier
7490             --  of the current entry, for insertion into Entry_Bodies_Array.
7491
7492             Append (
7493               Make_Aggregate (Loc,
7494                 Expressions => New_List (
7495                   Make_Attribute_Reference (Loc,
7496                     Prefix => New_Reference_To (Bdef, Loc),
7497                     Attribute_Name => Name_Unrestricted_Access),
7498                   Make_Attribute_Reference (Loc,
7499                     Prefix => New_Reference_To (Edef, Loc),
7500                     Attribute_Name => Name_Unrestricted_Access))),
7501               Expressions (Entries_Aggr));
7502
7503          end if;
7504
7505          Next (Comp);
7506       end loop;
7507
7508       --  If there are some private entry declarations, expand it as if they
7509       --  were visible entries.
7510
7511       if Present (Private_Declarations (Pdef)) then
7512          Comp := First (Private_Declarations (Pdef));
7513          while Present (Comp) loop
7514             if Nkind (Comp) = N_Entry_Declaration then
7515                E_Count := E_Count + 1;
7516                Comp_Id := Defining_Identifier (Comp);
7517
7518                Edef :=
7519                  Make_Defining_Identifier (Loc,
7520                   Build_Selected_Name (Prot_Typ, Comp_Id, 'E'));
7521                Sub :=
7522                  Make_Subprogram_Declaration (Loc,
7523                    Specification =>
7524                      Build_Protected_Entry_Specification (Loc, Edef, Comp_Id));
7525
7526                Insert_After (Current_Node, Sub);
7527                Analyze (Sub);
7528
7529                Set_Protected_Body_Subprogram
7530                  (Defining_Identifier (Comp),
7531                   Defining_Unit_Name (Specification (Sub)));
7532
7533                Current_Node := Sub;
7534
7535                Bdef :=
7536                  Make_Defining_Identifier (Loc,
7537                    Chars => Build_Selected_Name (Prot_Typ, Comp_Id, 'E'));
7538
7539                Sub :=
7540                  Make_Subprogram_Declaration (Loc,
7541                    Specification =>
7542                      Build_Barrier_Function_Specification (Loc, Bdef));
7543
7544                Insert_After (Current_Node, Sub);
7545                Analyze (Sub);
7546                Set_Protected_Body_Subprogram (Bdef, Bdef);
7547                Set_Barrier_Function (Comp_Id, Bdef);
7548                Set_Scope (Bdef, Scope (Comp_Id));
7549                Current_Node := Sub;
7550
7551                --  Collect pointers to the protected subprogram and the barrier
7552                --  of the current entry, for insertion into Entry_Bodies_Array.
7553
7554                Append_To (Expressions (Entries_Aggr),
7555                  Make_Aggregate (Loc,
7556                    Expressions => New_List (
7557                      Make_Attribute_Reference (Loc,
7558                        Prefix => New_Reference_To (Bdef, Loc),
7559                        Attribute_Name => Name_Unrestricted_Access),
7560                      Make_Attribute_Reference (Loc,
7561                        Prefix => New_Reference_To (Edef, Loc),
7562                        Attribute_Name => Name_Unrestricted_Access))));
7563             end if;
7564
7565             Next (Comp);
7566          end loop;
7567       end if;
7568
7569       --  Emit declaration for Entry_Bodies_Array, now that the addresses of
7570       --  all protected subprograms have been collected.
7571
7572       if Has_Entries (Prot_Typ) then
7573          Body_Id :=
7574            Make_Defining_Identifier (Sloc (Prot_Typ),
7575              Chars => New_External_Name (Chars (Prot_Typ), 'A'));
7576
7577          case Corresponding_Runtime_Package (Prot_Typ) is
7578             when System_Tasking_Protected_Objects_Entries =>
7579                Body_Arr := Make_Object_Declaration (Loc,
7580                  Defining_Identifier => Body_Id,
7581                  Aliased_Present => True,
7582                  Object_Definition =>
7583                    Make_Subtype_Indication (Loc,
7584                      Subtype_Mark => New_Reference_To (
7585                        RTE (RE_Protected_Entry_Body_Array), Loc),
7586                      Constraint =>
7587                        Make_Index_Or_Discriminant_Constraint (Loc,
7588                          Constraints => New_List (
7589                             Make_Range (Loc,
7590                               Make_Integer_Literal (Loc, 1),
7591                               Make_Integer_Literal (Loc, E_Count))))),
7592                  Expression => Entries_Aggr);
7593
7594             when System_Tasking_Protected_Objects_Single_Entry =>
7595                Body_Arr := Make_Object_Declaration (Loc,
7596                  Defining_Identifier => Body_Id,
7597                  Aliased_Present => True,
7598                  Object_Definition => New_Reference_To
7599                                         (RTE (RE_Entry_Body), Loc),
7600                  Expression =>
7601                    Make_Aggregate (Loc,
7602                      Expressions => New_List (
7603                        Make_Attribute_Reference (Loc,
7604                          Prefix => New_Reference_To (Bdef, Loc),
7605                          Attribute_Name => Name_Unrestricted_Access),
7606                        Make_Attribute_Reference (Loc,
7607                          Prefix => New_Reference_To (Edef, Loc),
7608                          Attribute_Name => Name_Unrestricted_Access))));
7609
7610             when others =>
7611                raise Program_Error;
7612          end case;
7613
7614          --  A pointer to this array will be placed in the corresponding record
7615          --  by its initialization procedure so this needs to be analyzed here.
7616
7617          Insert_After (Current_Node, Body_Arr);
7618          Current_Node := Body_Arr;
7619          Analyze (Body_Arr);
7620
7621          Set_Entry_Bodies_Array (Prot_Typ, Body_Id);
7622
7623          --  Finally, build the function that maps an entry index into the
7624          --  corresponding body. A pointer to this function is placed in each
7625          --  object of the type. Except for a ravenscar-like profile (no abort,
7626          --  no entry queue, 1 entry)
7627
7628          if Corresponding_Runtime_Package (Prot_Typ) =
7629               System_Tasking_Protected_Objects_Entries
7630          then
7631             Sub :=
7632               Make_Subprogram_Declaration (Loc,
7633                 Specification => Build_Find_Body_Index_Spec (Prot_Typ));
7634             Insert_After (Current_Node, Sub);
7635             Analyze (Sub);
7636          end if;
7637       end if;
7638    end Expand_N_Protected_Type_Declaration;
7639
7640    --------------------------------
7641    -- Expand_N_Requeue_Statement --
7642    --------------------------------
7643
7644    --  A non-dispatching requeue statement is expanded into one of four GNARLI
7645    --  operations, depending on the source and destination (task or protected
7646    --  object). A dispatching requeue statement is expanded into a call to the
7647    --  predefined primitive _Disp_Requeue. In addition, code is generated to
7648    --  jump around the remainder of processing for the original entry and, if
7649    --  the destination is (different) protected object, to attempt to service
7650    --  it. The following illustrates the various cases:
7651
7652    --  procedure entE
7653    --    (O : System.Address;
7654    --     P : System.Address;
7655    --     E : Protected_Entry_Index)
7656    --  is
7657    --     <discriminant renamings>
7658    --     <private object renamings>
7659    --     type poVP is access poV;
7660    --     _object : ptVP := ptVP!(O);
7661
7662    --  begin
7663    --     begin
7664    --        <start of statement sequence for entry>
7665
7666    --        -- Requeue from one protected entry body to another protected
7667    --        -- entry.
7668
7669    --        Requeue_Protected_Entry (
7670    --          _object._object'Access,
7671    --          new._object'Access,
7672    --          E,
7673    --          Abort_Present);
7674    --        return;
7675
7676    --        <some more of the statement sequence for entry>
7677
7678    --        --  Requeue from an entry body to a task entry
7679
7680    --        Requeue_Protected_To_Task_Entry (
7681    --          New._task_id,
7682    --          E,
7683    --          Abort_Present);
7684    --        return;
7685
7686    --        <rest of statement sequence for entry>
7687    --        Complete_Entry_Body (_object._object);
7688
7689    --     exception
7690    --        when all others =>
7691    --           Exceptional_Complete_Entry_Body (
7692    --             _object._object, Get_GNAT_Exception);
7693    --     end;
7694    --  end entE;
7695
7696    --  Requeue of a task entry call to a task entry
7697
7698    --  Accept_Call (E, Ann);
7699    --     <start of statement sequence for accept statement>
7700    --     Requeue_Task_Entry (New._task_id, E, Abort_Present);
7701    --     goto Lnn;
7702    --     <rest of statement sequence for accept statement>
7703    --     <<Lnn>>
7704    --     Complete_Rendezvous;
7705
7706    --  exception
7707    --     when all others =>
7708    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
7709
7710    --  Requeue of a task entry call to a protected entry
7711
7712    --  Accept_Call (E, Ann);
7713    --     <start of statement sequence for accept statement>
7714    --     Requeue_Task_To_Protected_Entry (
7715    --       new._object'Access,
7716    --       E,
7717    --       Abort_Present);
7718    --     newS (new, Pnn);
7719    --     goto Lnn;
7720    --     <rest of statement sequence for accept statement>
7721    --     <<Lnn>>
7722    --     Complete_Rendezvous;
7723
7724    --  exception
7725    --     when all others =>
7726    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
7727
7728    --  Ada 2005 (AI05-0030): Dispatching requeue from protected to interface
7729    --  class-wide type:
7730
7731    --  procedure entE
7732    --    (O : System.Address;
7733    --     P : System.Address;
7734    --     E : Protected_Entry_Index)
7735    --  is
7736    --     <discriminant renamings>
7737    --     <private object renamings>
7738    --     type poVP is access poV;
7739    --     _object : ptVP := ptVP!(O);
7740
7741    --  begin
7742    --     begin
7743    --        <start of statement sequence for entry>
7744
7745    --        _Disp_Requeue
7746    --          (<interface class-wide object>,
7747    --           True,
7748    --           _object'Address,
7749    --           Ada.Tags.Get_Offset_Index
7750    --             (Tag (_object),
7751    --              <interface dispatch table index of target entry>),
7752    --           Abort_Present);
7753    --        return;
7754
7755    --        <rest of statement sequence for entry>
7756    --        Complete_Entry_Body (_object._object);
7757
7758    --     exception
7759    --        when all others =>
7760    --           Exceptional_Complete_Entry_Body (
7761    --             _object._object, Get_GNAT_Exception);
7762    --     end;
7763    --  end entE;
7764
7765    --  Ada 2005 (AI05-0030): Dispatching requeue from task to interface
7766    --  class-wide type:
7767
7768    --  Accept_Call (E, Ann);
7769    --     <start of statement sequence for accept statement>
7770    --     _Disp_Requeue
7771    --       (<interface class-wide object>,
7772    --        False,
7773    --        null,
7774    --        Ada.Tags.Get_Offset_Index
7775    --          (Tag (_object),
7776    --           <interface dispatch table index of target entrt>),
7777    --        Abort_Present);
7778    --     newS (new, Pnn);
7779    --     goto Lnn;
7780    --     <rest of statement sequence for accept statement>
7781    --     <<Lnn>>
7782    --     Complete_Rendezvous;
7783
7784    --  exception
7785    --     when all others =>
7786    --        Exceptional_Complete_Rendezvous (Get_GNAT_Exception);
7787
7788    --  Further details on these expansions can be found in Expand_N_Protected_
7789    --  Body and Expand_N_Accept_Statement.
7790
7791    procedure Expand_N_Requeue_Statement (N : Node_Id) is
7792       Loc        : constant Source_Ptr := Sloc (N);
7793       Abortable  : Node_Id;
7794       Acc_Stat   : Node_Id;
7795       Conc_Typ   : Entity_Id;
7796       Concval    : Node_Id;
7797       Ename      : Node_Id;
7798       Index      : Node_Id;
7799       Lab_Node   : Node_Id;
7800       New_Param  : Node_Id;
7801       Old_Typ    : Entity_Id;
7802       Params     : List_Id;
7803       Rcall      : Node_Id;
7804       RTS_Call   : Entity_Id;
7805       Self_Param : Node_Id;
7806       Skip_Stat  : Node_Id;
7807
7808    begin
7809       Abortable :=
7810         New_Occurrence_Of (Boolean_Literals (Abort_Present (N)), Loc);
7811
7812       --  Extract the components of the entry call
7813
7814       Extract_Entry (N, Concval, Ename, Index);
7815       Conc_Typ := Etype (Concval);
7816
7817       --  Examine the scope stack in order to find nearest enclosing protected
7818       --  or task type. This will constitute our invocation source.
7819
7820       Old_Typ := Current_Scope;
7821       while Present (Old_Typ)
7822         and then not Is_Protected_Type (Old_Typ)
7823         and then not Is_Task_Type (Old_Typ)
7824       loop
7825          Old_Typ := Scope (Old_Typ);
7826       end loop;
7827
7828       --  Generate the parameter list for all cases. The abortable flag is
7829       --  common among dispatching and regular requeue.
7830
7831       Params := New_List (Abortable);
7832
7833       --  Ada 2005 (AI05-0030): We have a dispatching requeue of the form
7834       --  Concval.Ename where the type of Concval is class-wide concurrent
7835       --  interface.
7836
7837       if Ada_Version >= Ada_05
7838         and then Present (Concval)
7839         and then Is_Class_Wide_Type (Conc_Typ)
7840         and then Is_Concurrent_Interface (Conc_Typ)
7841       then
7842          RTS_Call := Make_Identifier (Loc, Name_uDisp_Requeue);
7843
7844          --  Generate:
7845          --    Ada.Tags.Get_Offset_Index
7846          --      (Ada.Tags.Tag (Concval),
7847          --       <interface dispatch table position of Ename>)
7848
7849          Prepend_To (Params,
7850            Make_Function_Call (Loc,
7851              Name =>
7852                New_Reference_To (RTE (RE_Get_Offset_Index), Loc),
7853              Parameter_Associations =>
7854                New_List (
7855                  Unchecked_Convert_To (RTE (RE_Tag), Concval),
7856                  Make_Integer_Literal (Loc, DT_Position (Entity (Ename))))));
7857
7858          --  Specific actuals for protected to interface class-wide type
7859          --  requeue.
7860
7861          if Is_Protected_Type (Old_Typ) then
7862             Prepend_To (Params,
7863               Make_Attribute_Reference (Loc,        --  _object'Address
7864                 Prefix =>
7865                   Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
7866                 Attribute_Name =>
7867                   Name_Address));
7868             Prepend_To (Params,                     --  True
7869               New_Reference_To (Standard_True, Loc));
7870
7871          --  Specific actuals for task to interface class-wide type requeue
7872
7873          else
7874             pragma Assert (Is_Task_Type (Old_Typ));
7875
7876             Prepend_To (Params,                     --  null
7877               New_Reference_To (RTE (RE_Null_Address), Loc));
7878             Prepend_To (Params,                     --  False
7879               New_Reference_To (Standard_False, Loc));
7880          end if;
7881
7882          --  Finally, add the common object parameter
7883
7884          Prepend_To (Params, New_Copy_Tree (Concval));
7885
7886       --  Regular requeue processing
7887
7888       else
7889          New_Param := Concurrent_Ref (Concval);
7890
7891          --  The index expression is common among all four cases
7892
7893          Prepend_To (Params,
7894            Entry_Index_Expression (Loc, Entity (Ename), Index, Conc_Typ));
7895
7896          if Is_Protected_Type (Old_Typ) then
7897             Self_Param :=
7898               Make_Attribute_Reference (Loc,
7899                 Prefix =>
7900                   Concurrent_Ref (New_Occurrence_Of (Old_Typ, Loc)),
7901                 Attribute_Name =>
7902                   Name_Unchecked_Access);
7903
7904             --  Protected to protected requeue
7905
7906             if Is_Protected_Type (Conc_Typ) then
7907                RTS_Call :=
7908                  New_Reference_To (RTE (RE_Requeue_Protected_Entry), Loc);
7909
7910                New_Param :=
7911                  Make_Attribute_Reference (Loc,
7912                    Prefix =>
7913                      New_Param,
7914                    Attribute_Name =>
7915                      Name_Unchecked_Access);
7916
7917             --  Protected to task requeue
7918
7919             else
7920                pragma Assert (Is_Task_Type (Conc_Typ));
7921                RTS_Call :=
7922                  New_Reference_To (
7923                    RTE (RE_Requeue_Protected_To_Task_Entry), Loc);
7924             end if;
7925
7926             Prepend (New_Param, Params);
7927             Prepend (Self_Param, Params);
7928
7929          else
7930             pragma Assert (Is_Task_Type (Old_Typ));
7931
7932             --  Task to protected requeue
7933
7934             if Is_Protected_Type (Conc_Typ) then
7935                RTS_Call :=
7936                  New_Reference_To (
7937                    RTE (RE_Requeue_Task_To_Protected_Entry), Loc);
7938
7939                New_Param :=
7940                  Make_Attribute_Reference (Loc,
7941                    Prefix =>
7942                      New_Param,
7943                    Attribute_Name =>
7944                      Name_Unchecked_Access);
7945
7946             --  Task to task requeue
7947
7948             else
7949                pragma Assert (Is_Task_Type (Conc_Typ));
7950                RTS_Call :=
7951                  New_Reference_To (RTE (RE_Requeue_Task_Entry), Loc);
7952             end if;
7953
7954             Prepend (New_Param, Params);
7955          end if;
7956       end if;
7957
7958       --  Create the GNARLI or predefined primitive call
7959
7960       Rcall :=
7961         Make_Procedure_Call_Statement (Loc,
7962           Name => RTS_Call,
7963           Parameter_Associations => Params);
7964
7965       Rewrite (N, Rcall);
7966       Analyze (N);
7967
7968       if Is_Protected_Type (Old_Typ) then
7969
7970          --  Build the return statement to skip the rest of the entry body
7971
7972          Skip_Stat := Make_Simple_Return_Statement (Loc);
7973
7974       else
7975          --  If the requeue is within a task, find the end label of the
7976          --  enclosing accept statement.
7977
7978          Acc_Stat := Parent (N);
7979          while Nkind (Acc_Stat) /= N_Accept_Statement loop
7980             Acc_Stat := Parent (Acc_Stat);
7981          end loop;
7982
7983          --  The last statement is the second label, used for completing the
7984          --  rendezvous the usual way. The label we are looking for is right
7985          --  before it.
7986
7987          Lab_Node :=
7988            Prev (Last (Statements (Handled_Statement_Sequence (Acc_Stat))));
7989
7990          pragma Assert (Nkind (Lab_Node) = N_Label);
7991
7992          --  Build the goto statement to skip the rest of the accept
7993          --  statement.
7994
7995          Skip_Stat :=
7996            Make_Goto_Statement (Loc,
7997              Name => New_Occurrence_Of (Entity (Identifier (Lab_Node)), Loc));
7998       end if;
7999
8000       Set_Analyzed (Skip_Stat);
8001
8002       Insert_After (N, Skip_Stat);
8003    end Expand_N_Requeue_Statement;
8004
8005    -------------------------------
8006    -- Expand_N_Selective_Accept --
8007    -------------------------------
8008
8009    procedure Expand_N_Selective_Accept (N : Node_Id) is
8010       Loc            : constant Source_Ptr := Sloc (N);
8011       Alts           : constant List_Id    := Select_Alternatives (N);
8012
8013       --  Note: in the below declarations a lot of new lists are allocated
8014       --  unconditionally which may well not end up being used. That's
8015       --  not a good idea since it wastes space gratuitously ???
8016
8017       Accept_Case    : List_Id;
8018       Accept_List    : constant List_Id := New_List;
8019
8020       Alt            : Node_Id;
8021       Alt_List       : constant List_Id := New_List;
8022       Alt_Stats      : List_Id;
8023       Ann            : Entity_Id := Empty;
8024
8025       Block          : Node_Id;
8026       Check_Guard    : Boolean := True;
8027
8028       Decls          : constant List_Id := New_List;
8029       Stats          : constant List_Id := New_List;
8030       Body_List      : constant List_Id := New_List;
8031       Trailing_List  : constant List_Id := New_List;
8032
8033       Choices        : List_Id;
8034       Else_Present   : Boolean := False;
8035       Terminate_Alt  : Node_Id := Empty;
8036       Select_Mode    : Node_Id;
8037
8038       Delay_Case     : List_Id;
8039       Delay_Count    : Integer := 0;
8040       Delay_Val      : Entity_Id;
8041       Delay_Index    : Entity_Id;
8042       Delay_Min      : Entity_Id;
8043       Delay_Num      : Int := 1;
8044       Delay_Alt_List : List_Id := New_List;
8045       Delay_List     : constant List_Id := New_List;
8046       D              : Entity_Id;
8047       M              : Entity_Id;
8048
8049       First_Delay    : Boolean := True;
8050       Guard_Open     : Entity_Id;
8051
8052       End_Lab        : Node_Id;
8053       Index          : Int := 1;
8054       Lab            : Node_Id;
8055       Num_Alts       : Int;
8056       Num_Accept     : Nat := 0;
8057       Proc           : Node_Id;
8058       Q              : Node_Id;
8059       Time_Type      : Entity_Id;
8060       X              : Node_Id;
8061       Select_Call    : Node_Id;
8062
8063       Qnam : constant Entity_Id :=
8064                Make_Defining_Identifier (Loc, New_External_Name ('S', 0));
8065
8066       Xnam : constant Entity_Id :=
8067                Make_Defining_Identifier (Loc, New_External_Name ('J', 1));
8068
8069       -----------------------
8070       -- Local subprograms --
8071       -----------------------
8072
8073       function Accept_Or_Raise return List_Id;
8074       --  For the rare case where delay alternatives all have guards, and
8075       --  all of them are closed, it is still possible that there were open
8076       --  accept alternatives with no callers. We must reexamine the
8077       --  Accept_List, and execute a selective wait with no else if some
8078       --  accept is open. If none, we raise program_error.
8079
8080       procedure Add_Accept (Alt : Node_Id);
8081       --  Process a single accept statement in a select alternative. Build
8082       --  procedure for body of accept, and add entry to dispatch table with
8083       --  expression for guard, in preparation for call to run time select.
8084
8085       function Make_And_Declare_Label (Num : Int) return Node_Id;
8086       --  Manufacture a label using Num as a serial number and declare it.
8087       --  The declaration is appended to Decls. The label marks the trailing
8088       --  statements of an accept or delay alternative.
8089
8090       function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id;
8091       --  Build call to Selective_Wait runtime routine
8092
8093       procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int);
8094       --  Add code to compare value of delay with previous values, and
8095       --  generate case entry for trailing statements.
8096
8097       procedure Process_Accept_Alternative
8098         (Alt   : Node_Id;
8099          Index : Int;
8100          Proc  : Node_Id);
8101       --  Add code to call corresponding procedure, and branch to
8102       --  trailing statements, if any.
8103
8104       ---------------------
8105       -- Accept_Or_Raise --
8106       ---------------------
8107
8108       function Accept_Or_Raise return List_Id is
8109          Cond  : Node_Id;
8110          Stats : List_Id;
8111          J     : constant Entity_Id := Make_Defining_Identifier (Loc,
8112                                                   New_Internal_Name ('J'));
8113
8114       begin
8115          --  We generate the following:
8116
8117          --    for J in q'range loop
8118          --       if q(J).S /=null_task_entry then
8119          --          selective_wait (simple_mode,...);
8120          --          done := True;
8121          --          exit;
8122          --       end if;
8123          --    end loop;
8124          --
8125          --    if no rendez_vous then
8126          --       raise program_error;
8127          --    end if;
8128
8129          --    Note that the code needs to know that the selector name
8130          --    in an Accept_Alternative is named S.
8131
8132          Cond := Make_Op_Ne (Loc,
8133            Left_Opnd =>
8134              Make_Selected_Component (Loc,
8135                Prefix => Make_Indexed_Component (Loc,
8136                  Prefix => New_Reference_To (Qnam, Loc),
8137                    Expressions => New_List (New_Reference_To (J, Loc))),
8138              Selector_Name => Make_Identifier (Loc, Name_S)),
8139            Right_Opnd =>
8140              New_Reference_To (RTE (RE_Null_Task_Entry), Loc));
8141
8142          Stats := New_List (
8143            Make_Implicit_Loop_Statement (N,
8144              Identifier => Empty,
8145              Iteration_Scheme =>
8146                Make_Iteration_Scheme (Loc,
8147                  Loop_Parameter_Specification =>
8148                    Make_Loop_Parameter_Specification (Loc,
8149                      Defining_Identifier => J,
8150                      Discrete_Subtype_Definition =>
8151                        Make_Attribute_Reference (Loc,
8152                          Prefix => New_Reference_To (Qnam, Loc),
8153                          Attribute_Name => Name_Range,
8154                          Expressions => New_List (
8155                            Make_Integer_Literal (Loc, 1))))),
8156
8157              Statements => New_List (
8158                Make_Implicit_If_Statement (N,
8159                  Condition =>  Cond,
8160                  Then_Statements => New_List (
8161                    Make_Select_Call (
8162                     New_Reference_To (RTE (RE_Simple_Mode), Loc)),
8163                    Make_Exit_Statement (Loc))))));
8164
8165          Append_To (Stats,
8166            Make_Raise_Program_Error (Loc,
8167              Condition => Make_Op_Eq (Loc,
8168                Left_Opnd  => New_Reference_To (Xnam, Loc),
8169                Right_Opnd =>
8170                  New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
8171              Reason => PE_All_Guards_Closed));
8172
8173          return Stats;
8174       end Accept_Or_Raise;
8175
8176       ----------------
8177       -- Add_Accept --
8178       ----------------
8179
8180       procedure Add_Accept (Alt : Node_Id) is
8181          Acc_Stm   : constant Node_Id    := Accept_Statement (Alt);
8182          Ename     : constant Node_Id    := Entry_Direct_Name (Acc_Stm);
8183          Eent      : constant Entity_Id  := Entity (Ename);
8184          Index     : constant Node_Id    := Entry_Index (Acc_Stm);
8185          Null_Body : Node_Id;
8186          Proc_Body : Node_Id;
8187          PB_Ent    : Entity_Id;
8188          Expr      : Node_Id;
8189          Call      : Node_Id;
8190
8191       begin
8192          if No (Ann) then
8193             Ann := Node (Last_Elmt (Accept_Address (Eent)));
8194          end if;
8195
8196          if Present (Condition (Alt)) then
8197             Expr :=
8198               Make_Conditional_Expression (Loc, New_List (
8199                 Condition (Alt),
8200                 Entry_Index_Expression (Loc, Eent, Index, Scope (Eent)),
8201                 New_Reference_To (RTE (RE_Null_Task_Entry), Loc)));
8202          else
8203             Expr :=
8204               Entry_Index_Expression
8205                 (Loc, Eent, Index, Scope (Eent));
8206          end if;
8207
8208          if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
8209             Null_Body := New_Reference_To (Standard_False, Loc);
8210
8211             if Abort_Allowed then
8212                Call := Make_Procedure_Call_Statement (Loc,
8213                  Name => New_Reference_To (RTE (RE_Abort_Undefer), Loc));
8214                Insert_Before (First (Statements (Handled_Statement_Sequence (
8215                  Accept_Statement (Alt)))), Call);
8216                Analyze (Call);
8217             end if;
8218
8219             PB_Ent :=
8220               Make_Defining_Identifier (Sloc (Ename),
8221                 New_External_Name (Chars (Ename), 'A', Num_Accept));
8222
8223             if Comes_From_Source (Alt) then
8224                Set_Debug_Info_Needed (PB_Ent);
8225             end if;
8226
8227             Proc_Body :=
8228               Make_Subprogram_Body (Loc,
8229                 Specification =>
8230                   Make_Procedure_Specification (Loc,
8231                     Defining_Unit_Name => PB_Ent),
8232                Declarations => Declarations (Acc_Stm),
8233                Handled_Statement_Sequence =>
8234                  Build_Accept_Body (Accept_Statement (Alt)));
8235
8236             --  During the analysis of the body of the accept statement, any
8237             --  zero cost exception handler records were collected in the
8238             --  Accept_Handler_Records field of the N_Accept_Alternative node.
8239             --  This is where we move them to where they belong, namely the
8240             --  newly created procedure.
8241
8242             Set_Handler_Records (PB_Ent, Accept_Handler_Records (Alt));
8243             Append (Proc_Body, Body_List);
8244
8245          else
8246             Null_Body := New_Reference_To (Standard_True,  Loc);
8247
8248             --  if accept statement has declarations, insert above, given that
8249             --  we are not creating a body for the accept.
8250
8251             if Present (Declarations (Acc_Stm)) then
8252                Insert_Actions (N, Declarations (Acc_Stm));
8253             end if;
8254          end if;
8255
8256          Append_To (Accept_List,
8257            Make_Aggregate (Loc, Expressions => New_List (Null_Body, Expr)));
8258
8259          Num_Accept := Num_Accept + 1;
8260       end Add_Accept;
8261
8262       ----------------------------
8263       -- Make_And_Declare_Label --
8264       ----------------------------
8265
8266       function Make_And_Declare_Label (Num : Int) return Node_Id is
8267          Lab_Id : Node_Id;
8268
8269       begin
8270          Lab_Id := Make_Identifier (Loc, New_External_Name ('L', Num));
8271          Lab :=
8272            Make_Label (Loc, Lab_Id);
8273
8274          Append_To (Decls,
8275            Make_Implicit_Label_Declaration (Loc,
8276              Defining_Identifier  =>
8277                Make_Defining_Identifier (Loc, Chars (Lab_Id)),
8278              Label_Construct => Lab));
8279
8280          return Lab;
8281       end Make_And_Declare_Label;
8282
8283       ----------------------
8284       -- Make_Select_Call --
8285       ----------------------
8286
8287       function Make_Select_Call (Select_Mode : Entity_Id) return Node_Id is
8288          Params : constant List_Id := New_List;
8289
8290       begin
8291          Append (
8292            Make_Attribute_Reference (Loc,
8293              Prefix => New_Reference_To (Qnam, Loc),
8294              Attribute_Name => Name_Unchecked_Access),
8295            Params);
8296          Append (Select_Mode, Params);
8297          Append (New_Reference_To (Ann, Loc), Params);
8298          Append (New_Reference_To (Xnam, Loc), Params);
8299
8300          return
8301            Make_Procedure_Call_Statement (Loc,
8302              Name => New_Reference_To (RTE (RE_Selective_Wait), Loc),
8303              Parameter_Associations => Params);
8304       end Make_Select_Call;
8305
8306       --------------------------------
8307       -- Process_Accept_Alternative --
8308       --------------------------------
8309
8310       procedure Process_Accept_Alternative
8311         (Alt   : Node_Id;
8312          Index : Int;
8313          Proc  : Node_Id)
8314       is
8315          Choices   : List_Id := No_List;
8316          Alt_Stats : List_Id;
8317
8318       begin
8319          Adjust_Condition (Condition (Alt));
8320          Alt_Stats := No_List;
8321
8322          if Present (Handled_Statement_Sequence (Accept_Statement (Alt))) then
8323             Choices := New_List (
8324               Make_Integer_Literal (Loc, Index));
8325
8326             Alt_Stats := New_List (
8327               Make_Procedure_Call_Statement (Loc,
8328                 Name => New_Reference_To (
8329                   Defining_Unit_Name (Specification (Proc)), Loc)));
8330          end if;
8331
8332          if Statements (Alt) /= Empty_List then
8333
8334             if No (Alt_Stats) then
8335
8336                --  Accept with no body, followed by trailing statements
8337
8338                Choices := New_List (
8339                  Make_Integer_Literal (Loc, Index));
8340
8341                Alt_Stats := New_List;
8342             end if;
8343
8344             --  After the call, if any, branch to to trailing statements. We
8345             --  create a label for each, as well as the corresponding label
8346             --  declaration.
8347
8348             Lab := Make_And_Declare_Label (Index);
8349             Append_To (Alt_Stats,
8350               Make_Goto_Statement (Loc,
8351                 Name => New_Copy (Identifier (Lab))));
8352
8353             Append (Lab, Trailing_List);
8354             Append_List (Statements (Alt), Trailing_List);
8355             Append_To (Trailing_List,
8356               Make_Goto_Statement (Loc,
8357                 Name => New_Copy (Identifier (End_Lab))));
8358          end if;
8359
8360          if Present (Alt_Stats) then
8361
8362             --  Procedure call. and/or trailing statements
8363
8364             Append_To (Alt_List,
8365               Make_Case_Statement_Alternative (Loc,
8366                 Discrete_Choices => Choices,
8367                 Statements => Alt_Stats));
8368          end if;
8369       end Process_Accept_Alternative;
8370
8371       -------------------------------
8372       -- Process_Delay_Alternative --
8373       -------------------------------
8374
8375       procedure Process_Delay_Alternative (Alt : Node_Id; Index : Int) is
8376          Choices   : List_Id;
8377          Cond      : Node_Id;
8378          Delay_Alt : List_Id;
8379
8380       begin
8381          --  Deal with C/Fortran boolean as delay condition
8382
8383          Adjust_Condition (Condition (Alt));
8384
8385          --  Determine the smallest specified delay
8386
8387          --  for each delay alternative generate:
8388
8389          --    if guard-expression then
8390          --       Delay_Val  := delay-expression;
8391          --       Guard_Open := True;
8392          --       if Delay_Val < Delay_Min then
8393          --          Delay_Min   := Delay_Val;
8394          --          Delay_Index := Index;
8395          --       end if;
8396          --    end if;
8397
8398          --  The enclosing if-statement is omitted if there is no guard
8399
8400          if Delay_Count = 1
8401            or else First_Delay
8402          then
8403             First_Delay := False;
8404
8405             Delay_Alt := New_List (
8406               Make_Assignment_Statement (Loc,
8407                 Name => New_Reference_To (Delay_Min, Loc),
8408                 Expression => Expression (Delay_Statement (Alt))));
8409
8410             if Delay_Count > 1 then
8411                Append_To (Delay_Alt,
8412                  Make_Assignment_Statement (Loc,
8413                    Name       => New_Reference_To (Delay_Index, Loc),
8414                    Expression => Make_Integer_Literal (Loc, Index)));
8415             end if;
8416
8417          else
8418             Delay_Alt := New_List (
8419               Make_Assignment_Statement (Loc,
8420                 Name => New_Reference_To (Delay_Val, Loc),
8421                 Expression => Expression (Delay_Statement (Alt))));
8422
8423             if Time_Type = Standard_Duration then
8424                Cond :=
8425                   Make_Op_Lt (Loc,
8426                     Left_Opnd  => New_Reference_To (Delay_Val, Loc),
8427                     Right_Opnd => New_Reference_To (Delay_Min, Loc));
8428
8429             else
8430                --  The scope of the time type must define a comparison
8431                --  operator. The scope itself may not be visible, so we
8432                --  construct a node with entity information to insure that
8433                --  semantic analysis can find the proper operator.
8434
8435                Cond :=
8436                  Make_Function_Call (Loc,
8437                    Name => Make_Selected_Component (Loc,
8438                      Prefix => New_Reference_To (Scope (Time_Type), Loc),
8439                      Selector_Name =>
8440                        Make_Operator_Symbol (Loc,
8441                          Chars => Name_Op_Lt,
8442                          Strval => No_String)),
8443                     Parameter_Associations =>
8444                       New_List (
8445                         New_Reference_To (Delay_Val, Loc),
8446                         New_Reference_To (Delay_Min, Loc)));
8447
8448                Set_Entity (Prefix (Name (Cond)), Scope (Time_Type));
8449             end if;
8450
8451             Append_To (Delay_Alt,
8452               Make_Implicit_If_Statement (N,
8453                 Condition => Cond,
8454                 Then_Statements => New_List (
8455                   Make_Assignment_Statement (Loc,
8456                     Name       => New_Reference_To (Delay_Min, Loc),
8457                     Expression => New_Reference_To (Delay_Val, Loc)),
8458
8459                   Make_Assignment_Statement (Loc,
8460                     Name       => New_Reference_To (Delay_Index, Loc),
8461                     Expression => Make_Integer_Literal (Loc, Index)))));
8462          end if;
8463
8464          if Check_Guard then
8465             Append_To (Delay_Alt,
8466               Make_Assignment_Statement (Loc,
8467                 Name => New_Reference_To (Guard_Open, Loc),
8468                 Expression => New_Reference_To (Standard_True, Loc)));
8469          end if;
8470
8471          if Present (Condition (Alt)) then
8472             Delay_Alt := New_List (
8473               Make_Implicit_If_Statement (N,
8474                 Condition => Condition (Alt),
8475                 Then_Statements => Delay_Alt));
8476          end if;
8477
8478          Append_List (Delay_Alt, Delay_List);
8479
8480          --  If the delay alternative has a statement part, add choice to the
8481          --  case statements for delays.
8482
8483          if Present (Statements (Alt)) then
8484
8485             if Delay_Count = 1 then
8486                Append_List (Statements (Alt), Delay_Alt_List);
8487
8488             else
8489                Choices := New_List (
8490                  Make_Integer_Literal (Loc, Index));
8491
8492                Append_To (Delay_Alt_List,
8493                  Make_Case_Statement_Alternative (Loc,
8494                    Discrete_Choices => Choices,
8495                    Statements => Statements (Alt)));
8496             end if;
8497
8498          elsif Delay_Count = 1 then
8499
8500             --  If the single delay has no trailing statements, add a branch
8501             --  to the exit label to the selective wait.
8502
8503             Delay_Alt_List := New_List (
8504               Make_Goto_Statement (Loc,
8505                 Name => New_Copy (Identifier (End_Lab))));
8506
8507          end if;
8508       end Process_Delay_Alternative;
8509
8510    --  Start of processing for Expand_N_Selective_Accept
8511
8512    begin
8513       --  First insert some declarations before the select. The first is:
8514
8515       --    Ann : Address
8516
8517       --  This variable holds the parameters passed to the accept body. This
8518       --  declaration has already been inserted by the time we get here by
8519       --  a call to Expand_Accept_Declarations made from the semantics when
8520       --  processing the first accept statement contained in the select. We
8521       --  can find this entity as Accept_Address (E), where E is any of the
8522       --  entries references by contained accept statements.
8523
8524       --  The first step is to scan the list of Selective_Accept_Statements
8525       --  to find this entity, and also count the number of accepts, and
8526       --  determine if terminated, delay or else is present:
8527
8528       Num_Alts := 0;
8529
8530       Alt := First (Alts);
8531       while Present (Alt) loop
8532
8533          if Nkind (Alt) = N_Accept_Alternative then
8534             Add_Accept (Alt);
8535
8536          elsif Nkind (Alt) = N_Delay_Alternative then
8537             Delay_Count := Delay_Count + 1;
8538
8539             --  If the delays are relative delays, the delay expressions have
8540             --  type Standard_Duration. Otherwise they must have some time type
8541             --  recognized by GNAT.
8542
8543             if Nkind (Delay_Statement (Alt)) = N_Delay_Relative_Statement then
8544                Time_Type := Standard_Duration;
8545             else
8546                Time_Type := Etype (Expression (Delay_Statement (Alt)));
8547
8548                if Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time)
8549                  or else Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time)
8550                then
8551                   null;
8552                else
8553                   Error_Msg_NE (
8554                     "& is not a time type (RM 9.6(6))",
8555                        Expression (Delay_Statement (Alt)), Time_Type);
8556                   Time_Type := Standard_Duration;
8557                   Set_Etype (Expression (Delay_Statement (Alt)), Any_Type);
8558                end if;
8559             end if;
8560
8561             if No (Condition (Alt)) then
8562
8563                --  This guard will always be open
8564
8565                Check_Guard := False;
8566             end if;
8567
8568          elsif Nkind (Alt) = N_Terminate_Alternative then
8569             Adjust_Condition (Condition (Alt));
8570             Terminate_Alt := Alt;
8571          end if;
8572
8573          Num_Alts := Num_Alts + 1;
8574          Next (Alt);
8575       end loop;
8576
8577       Else_Present := Present (Else_Statements (N));
8578
8579       --  At the same time (see procedure Add_Accept) we build the accept list:
8580
8581       --    Qnn : Accept_List (1 .. num-select) := (
8582       --          (null-body, entry-index),
8583       --          (null-body, entry-index),
8584       --          ..
8585       --          (null_body, entry-index));
8586
8587       --  In the above declaration, null-body is True if the corresponding
8588       --  accept has no body, and false otherwise. The entry is either the
8589       --  entry index expression if there is no guard, or if a guard is
8590       --  present, then a conditional expression of the form:
8591
8592       --    (if guard then entry-index else Null_Task_Entry)
8593
8594       --  If a guard is statically known to be false, the entry can simply
8595       --  be omitted from the accept list.
8596
8597       Q :=
8598         Make_Object_Declaration (Loc,
8599           Defining_Identifier => Qnam,
8600           Object_Definition =>
8601             New_Reference_To (RTE (RE_Accept_List), Loc),
8602           Aliased_Present => True,
8603
8604           Expression =>
8605              Make_Qualified_Expression (Loc,
8606                Subtype_Mark =>
8607                  New_Reference_To (RTE (RE_Accept_List), Loc),
8608                Expression =>
8609                  Make_Aggregate (Loc, Expressions => Accept_List)));
8610
8611       Append (Q, Decls);
8612
8613       --  Then we declare the variable that holds the index for the accept
8614       --  that will be selected for service:
8615
8616       --    Xnn : Select_Index;
8617
8618       X :=
8619         Make_Object_Declaration (Loc,
8620           Defining_Identifier => Xnam,
8621           Object_Definition =>
8622             New_Reference_To (RTE (RE_Select_Index), Loc),
8623           Expression =>
8624             New_Reference_To (RTE (RE_No_Rendezvous), Loc));
8625
8626       Append (X, Decls);
8627
8628       --  After this follow procedure declarations for each accept body
8629
8630       --    procedure Pnn is
8631       --    begin
8632       --       ...
8633       --    end;
8634
8635       --  where the ... are statements from the corresponding procedure body.
8636       --  No parameters are involved, since the parameters are passed via Ann
8637       --  and the parameter references have already been expanded to be direct
8638       --  references to Ann (see Exp_Ch2.Expand_Entry_Parameter). Furthermore,
8639       --  any embedded tasking statements (which would normally be illegal in
8640       --  procedures), have been converted to calls to the tasking runtime so
8641       --  there is no problem in putting them into procedures.
8642
8643       --  The original accept statement has been expanded into a block in
8644       --  the same fashion as for simple accepts (see Build_Accept_Body).
8645
8646       --  Note: we don't really need to build these procedures for the case
8647       --  where no delay statement is present, but it is just as easy to
8648       --  build them unconditionally, and not significantly inefficient,
8649       --  since if they are short they will be inlined anyway.
8650
8651       --  The procedure declarations have been assembled in Body_List
8652
8653       --  If delays are present, we must compute the required delay.
8654       --  We first generate the declarations:
8655
8656       --    Delay_Index : Boolean := 0;
8657       --    Delay_Min   : Some_Time_Type.Time;
8658       --    Delay_Val   : Some_Time_Type.Time;
8659
8660       --  Delay_Index will be set to the index of the minimum delay, i.e. the
8661       --  active delay that is actually chosen as the basis for the possible
8662       --  delay if an immediate rendez-vous is not possible.
8663
8664       --  In the most common case there is a single delay statement, and this
8665       --  is handled specially.
8666
8667       if Delay_Count > 0 then
8668
8669          --  Generate the required declarations
8670
8671          Delay_Val :=
8672            Make_Defining_Identifier (Loc, New_External_Name ('D', 1));
8673          Delay_Index :=
8674            Make_Defining_Identifier (Loc, New_External_Name ('D', 2));
8675          Delay_Min :=
8676            Make_Defining_Identifier (Loc, New_External_Name ('D', 3));
8677
8678          Append_To (Decls,
8679            Make_Object_Declaration (Loc,
8680              Defining_Identifier => Delay_Val,
8681              Object_Definition   => New_Reference_To (Time_Type, Loc)));
8682
8683          Append_To (Decls,
8684            Make_Object_Declaration (Loc,
8685              Defining_Identifier => Delay_Index,
8686              Object_Definition   => New_Reference_To (Standard_Integer, Loc),
8687              Expression          => Make_Integer_Literal (Loc, 0)));
8688
8689          Append_To (Decls,
8690            Make_Object_Declaration (Loc,
8691              Defining_Identifier => Delay_Min,
8692              Object_Definition   => New_Reference_To (Time_Type, Loc),
8693              Expression          =>
8694                Unchecked_Convert_To (Time_Type,
8695                  Make_Attribute_Reference (Loc,
8696                    Prefix =>
8697                      New_Occurrence_Of (Underlying_Type (Time_Type), Loc),
8698                    Attribute_Name => Name_Last))));
8699
8700          --  Create Duration and Delay_Mode objects used for passing a delay
8701          --  value to RTS
8702
8703          D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
8704          M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
8705
8706          declare
8707             Discr : Entity_Id;
8708
8709          begin
8710             --  Note that these values are defined in s-osprim.ads and must
8711             --  be kept in sync:
8712             --
8713             --     Relative          : constant := 0;
8714             --     Absolute_Calendar : constant := 1;
8715             --     Absolute_RT       : constant := 2;
8716
8717             if Time_Type = Standard_Duration then
8718                Discr := Make_Integer_Literal (Loc, 0);
8719
8720             elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
8721                Discr := Make_Integer_Literal (Loc, 1);
8722
8723             else
8724                pragma Assert
8725                  (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
8726                Discr := Make_Integer_Literal (Loc, 2);
8727             end if;
8728
8729             Append_To (Decls,
8730               Make_Object_Declaration (Loc,
8731                 Defining_Identifier => D,
8732                 Object_Definition =>
8733                   New_Reference_To (Standard_Duration, Loc)));
8734
8735             Append_To (Decls,
8736               Make_Object_Declaration (Loc,
8737                 Defining_Identifier => M,
8738                 Object_Definition   =>
8739                   New_Reference_To (Standard_Integer, Loc),
8740                 Expression          => Discr));
8741          end;
8742
8743          if Check_Guard then
8744             Guard_Open :=
8745               Make_Defining_Identifier (Loc, New_External_Name ('G', 1));
8746
8747             Append_To (Decls,
8748               Make_Object_Declaration (Loc,
8749                  Defining_Identifier => Guard_Open,
8750                  Object_Definition => New_Reference_To (Standard_Boolean, Loc),
8751                  Expression        => New_Reference_To (Standard_False, Loc)));
8752          end if;
8753
8754       --  Delay_Count is zero, don't need M and D set (suppress warning)
8755
8756       else
8757          M := Empty;
8758          D := Empty;
8759       end if;
8760
8761       if Present (Terminate_Alt) then
8762
8763          --  If the terminate alternative guard is False, use
8764          --  Simple_Mode; otherwise use Terminate_Mode.
8765
8766          if Present (Condition (Terminate_Alt)) then
8767             Select_Mode := Make_Conditional_Expression (Loc,
8768               New_List (Condition (Terminate_Alt),
8769                         New_Reference_To (RTE (RE_Terminate_Mode), Loc),
8770                         New_Reference_To (RTE (RE_Simple_Mode), Loc)));
8771          else
8772             Select_Mode := New_Reference_To (RTE (RE_Terminate_Mode), Loc);
8773          end if;
8774
8775       elsif Else_Present or Delay_Count > 0 then
8776          Select_Mode := New_Reference_To (RTE (RE_Else_Mode), Loc);
8777
8778       else
8779          Select_Mode := New_Reference_To (RTE (RE_Simple_Mode), Loc);
8780       end if;
8781
8782       Select_Call := Make_Select_Call (Select_Mode);
8783       Append (Select_Call, Stats);
8784
8785       --  Now generate code to act on the result. There is an entry
8786       --  in this case for each accept statement with a non-null body,
8787       --  followed by a branch to the statements that follow the Accept.
8788       --  In the absence of delay alternatives, we generate:
8789
8790       --    case X is
8791       --      when No_Rendezvous =>  --  omitted if simple mode
8792       --         goto Lab0;
8793
8794       --      when 1 =>
8795       --         P1n;
8796       --         goto Lab1;
8797
8798       --      when 2 =>
8799       --         P2n;
8800       --         goto Lab2;
8801
8802       --      when others =>
8803       --         goto Exit;
8804       --    end case;
8805       --
8806       --    Lab0: Else_Statements;
8807       --    goto exit;
8808
8809       --    Lab1:  Trailing_Statements1;
8810       --    goto Exit;
8811       --
8812       --    Lab2:  Trailing_Statements2;
8813       --    goto Exit;
8814       --    ...
8815       --    Exit:
8816
8817       --  Generate label for common exit
8818
8819       End_Lab := Make_And_Declare_Label (Num_Alts + 1);
8820
8821       --  First entry is the default case, when no rendezvous is possible
8822
8823       Choices := New_List (New_Reference_To (RTE (RE_No_Rendezvous), Loc));
8824
8825       if Else_Present then
8826
8827          --  If no rendezvous is possible, the else part is executed
8828
8829          Lab := Make_And_Declare_Label (0);
8830          Alt_Stats := New_List (
8831            Make_Goto_Statement (Loc,
8832              Name => New_Copy (Identifier (Lab))));
8833
8834          Append (Lab, Trailing_List);
8835          Append_List (Else_Statements (N), Trailing_List);
8836          Append_To (Trailing_List,
8837            Make_Goto_Statement (Loc,
8838              Name => New_Copy (Identifier (End_Lab))));
8839       else
8840          Alt_Stats := New_List (
8841            Make_Goto_Statement (Loc,
8842              Name => New_Copy (Identifier (End_Lab))));
8843       end if;
8844
8845       Append_To (Alt_List,
8846         Make_Case_Statement_Alternative (Loc,
8847           Discrete_Choices => Choices,
8848           Statements => Alt_Stats));
8849
8850       --  We make use of the fact that Accept_Index is an integer type, and
8851       --  generate successive literals for entries for each accept. Only those
8852       --  for which there is a body or trailing statements get a case entry.
8853
8854       Alt := First (Select_Alternatives (N));
8855       Proc := First (Body_List);
8856       while Present (Alt) loop
8857
8858          if Nkind (Alt) = N_Accept_Alternative then
8859             Process_Accept_Alternative (Alt, Index, Proc);
8860             Index := Index + 1;
8861
8862             if Present
8863               (Handled_Statement_Sequence (Accept_Statement (Alt)))
8864             then
8865                Next (Proc);
8866             end if;
8867
8868          elsif Nkind (Alt) = N_Delay_Alternative then
8869             Process_Delay_Alternative (Alt, Delay_Num);
8870             Delay_Num := Delay_Num + 1;
8871          end if;
8872
8873          Next (Alt);
8874       end loop;
8875
8876       --  An others choice is always added to the main case, as well
8877       --  as the delay case (to satisfy the compiler).
8878
8879       Append_To (Alt_List,
8880         Make_Case_Statement_Alternative (Loc,
8881           Discrete_Choices =>
8882             New_List (Make_Others_Choice (Loc)),
8883           Statements       =>
8884             New_List (Make_Goto_Statement (Loc,
8885               Name => New_Copy (Identifier (End_Lab))))));
8886
8887       Accept_Case := New_List (
8888         Make_Case_Statement (Loc,
8889           Expression   => New_Reference_To (Xnam, Loc),
8890           Alternatives => Alt_List));
8891
8892       Append_List (Trailing_List, Accept_Case);
8893       Append (End_Lab, Accept_Case);
8894       Append_List (Body_List, Decls);
8895
8896       --  Construct case statement for trailing statements of delay
8897       --  alternatives, if there are several of them.
8898
8899       if Delay_Count > 1 then
8900          Append_To (Delay_Alt_List,
8901            Make_Case_Statement_Alternative (Loc,
8902              Discrete_Choices =>
8903                New_List (Make_Others_Choice (Loc)),
8904              Statements       =>
8905                New_List (Make_Null_Statement (Loc))));
8906
8907          Delay_Case := New_List (
8908            Make_Case_Statement (Loc,
8909              Expression   => New_Reference_To (Delay_Index, Loc),
8910              Alternatives => Delay_Alt_List));
8911       else
8912          Delay_Case := Delay_Alt_List;
8913       end if;
8914
8915       --  If there are no delay alternatives, we append the case statement
8916       --  to the statement list.
8917
8918       if Delay_Count = 0 then
8919          Append_List (Accept_Case, Stats);
8920
8921       --  Delay alternatives present
8922
8923       else
8924          --  If delay alternatives are present we generate:
8925
8926          --    find minimum delay.
8927          --    DX := minimum delay;
8928          --    M := <delay mode>;
8929          --    Timed_Selective_Wait (Q'Unchecked_Access, Delay_Mode, P,
8930          --      DX, MX, X);
8931          --
8932          --    if X = No_Rendezvous then
8933          --      case statement for delay statements.
8934          --    else
8935          --      case statement for accept alternatives.
8936          --    end if;
8937
8938          declare
8939             Cases : Node_Id;
8940             Stmt  : Node_Id;
8941             Parms : List_Id;
8942             Parm  : Node_Id;
8943             Conv  : Node_Id;
8944
8945          begin
8946             --  The type of the delay expression is known to be legal
8947
8948             if Time_Type = Standard_Duration then
8949                Conv := New_Reference_To (Delay_Min, Loc);
8950
8951             elsif Is_RTE (Base_Type (Etype (Time_Type)), RO_CA_Time) then
8952                Conv := Make_Function_Call (Loc,
8953                  New_Reference_To (RTE (RO_CA_To_Duration), Loc),
8954                  New_List (New_Reference_To (Delay_Min, Loc)));
8955
8956             else
8957                pragma Assert
8958                  (Is_RTE (Base_Type (Etype (Time_Type)), RO_RT_Time));
8959
8960                Conv := Make_Function_Call (Loc,
8961                  New_Reference_To (RTE (RO_RT_To_Duration), Loc),
8962                  New_List (New_Reference_To (Delay_Min, Loc)));
8963             end if;
8964
8965             Stmt := Make_Assignment_Statement (Loc,
8966               Name => New_Reference_To (D, Loc),
8967               Expression => Conv);
8968
8969             --  Change the value for Accept_Modes. (Else_Mode -> Delay_Mode)
8970
8971             Parms := Parameter_Associations (Select_Call);
8972             Parm := First (Parms);
8973
8974             while Present (Parm)
8975               and then Parm /= Select_Mode
8976             loop
8977                Next (Parm);
8978             end loop;
8979
8980             pragma Assert (Present (Parm));
8981             Rewrite (Parm, New_Reference_To (RTE (RE_Delay_Mode), Loc));
8982             Analyze (Parm);
8983
8984             --  Prepare two new parameters of Duration and Delay_Mode type
8985             --  which represent the value and the mode of the minimum delay.
8986
8987             Next (Parm);
8988             Insert_After (Parm, New_Reference_To (M, Loc));
8989             Insert_After (Parm, New_Reference_To (D, Loc));
8990
8991             --  Create a call to RTS
8992
8993             Rewrite (Select_Call,
8994               Make_Procedure_Call_Statement (Loc,
8995                 Name => New_Reference_To (RTE (RE_Timed_Selective_Wait), Loc),
8996                 Parameter_Associations => Parms));
8997
8998             --  This new call should follow the calculation of the minimum
8999             --  delay.
9000
9001             Insert_List_Before (Select_Call, Delay_List);
9002
9003             if Check_Guard then
9004                Stmt :=
9005                  Make_Implicit_If_Statement (N,
9006                    Condition => New_Reference_To (Guard_Open, Loc),
9007                    Then_Statements =>
9008                      New_List (New_Copy_Tree (Stmt),
9009                        New_Copy_Tree (Select_Call)),
9010                    Else_Statements => Accept_Or_Raise);
9011                Rewrite (Select_Call, Stmt);
9012             else
9013                Insert_Before (Select_Call, Stmt);
9014             end if;
9015
9016             Cases :=
9017               Make_Implicit_If_Statement (N,
9018                 Condition => Make_Op_Eq (Loc,
9019                   Left_Opnd  => New_Reference_To (Xnam, Loc),
9020                   Right_Opnd =>
9021                     New_Reference_To (RTE (RE_No_Rendezvous), Loc)),
9022
9023                 Then_Statements => Delay_Case,
9024                 Else_Statements => Accept_Case);
9025
9026             Append (Cases, Stats);
9027          end;
9028       end if;
9029
9030       --  Replace accept statement with appropriate block
9031
9032       Block :=
9033         Make_Block_Statement (Loc,
9034           Declarations => Decls,
9035           Handled_Statement_Sequence =>
9036             Make_Handled_Sequence_Of_Statements (Loc,
9037               Statements => Stats));
9038
9039       Rewrite (N, Block);
9040       Analyze (N);
9041
9042       --  Note: have to worry more about abort deferral in above code ???
9043
9044       --  Final step is to unstack the Accept_Address entries for all accept
9045       --  statements appearing in accept alternatives in the select statement
9046
9047       Alt := First (Alts);
9048       while Present (Alt) loop
9049          if Nkind (Alt) = N_Accept_Alternative then
9050             Remove_Last_Elmt (Accept_Address
9051               (Entity (Entry_Direct_Name (Accept_Statement (Alt)))));
9052          end if;
9053
9054          Next (Alt);
9055       end loop;
9056    end Expand_N_Selective_Accept;
9057
9058    --------------------------------------
9059    -- Expand_N_Single_Task_Declaration --
9060    --------------------------------------
9061
9062    --  Single task declarations should never be present after semantic
9063    --  analysis, since we expect them to be replaced by a declaration of an
9064    --  anonymous task type, followed by a declaration of the task object. We
9065    --  include this routine to make sure that is happening!
9066
9067    procedure Expand_N_Single_Task_Declaration (N : Node_Id) is
9068    begin
9069       raise Program_Error;
9070    end Expand_N_Single_Task_Declaration;
9071
9072    ------------------------
9073    -- Expand_N_Task_Body --
9074    ------------------------
9075
9076    --  Given a task body
9077
9078    --    task body tname is
9079    --       <declarations>
9080    --    begin
9081    --       <statements>
9082    --    end x;
9083
9084    --  This expansion routine converts it into a procedure and sets the
9085    --  elaboration flag for the procedure to true, to represent the fact
9086    --  that the task body is now elaborated:
9087
9088    --    procedure tnameB (_Task : access tnameV) is
9089    --       discriminal : dtype renames _Task.discriminant;
9090
9091    --       procedure _clean is
9092    --       begin
9093    --          Abort_Defer.all;
9094    --          Complete_Task;
9095    --          Abort_Undefer.all;
9096    --          return;
9097    --       end _clean;
9098
9099    --    begin
9100    --       Abort_Undefer.all;
9101    --       <declarations>
9102    --       System.Task_Stages.Complete_Activation;
9103    --       <statements>
9104    --    at end
9105    --       _clean;
9106    --    end tnameB;
9107
9108    --    tnameE := True;
9109
9110    --  In addition, if the task body is an activator, then a call to activate
9111    --  tasks is added at the start of the statements, before the call to
9112    --  Complete_Activation, and if in addition the task is a master then it
9113    --  must be established as a master. These calls are inserted and analyzed
9114    --  in Expand_Cleanup_Actions, when the Handled_Sequence_Of_Statements is
9115    --  expanded.
9116
9117    --  There is one discriminal declaration line generated for each
9118    --  discriminant that is present to provide an easy reference point for
9119    --  discriminant references inside the body (see Exp_Ch2.Expand_Name).
9120
9121    --  Note on relationship to GNARLI definition. In the GNARLI definition,
9122    --  task body procedures have a profile (Arg : System.Address). That is
9123    --  needed because GNARLI has to use the same access-to-subprogram type
9124    --  for all task types. We depend here on knowing that in GNAT, passing
9125    --  an address argument by value is identical to passing a record value
9126    --  by access (in either case a single pointer is passed), so even though
9127    --  this procedure has the wrong profile. In fact it's all OK, since the
9128    --  callings sequence is identical.
9129
9130    procedure Expand_N_Task_Body (N : Node_Id) is
9131       Loc   : constant Source_Ptr := Sloc (N);
9132       Ttyp  : constant Entity_Id  := Corresponding_Spec (N);
9133       Call  : Node_Id;
9134       New_N : Node_Id;
9135
9136    begin
9137       --  Add renaming declarations for discriminals and a declaration for the
9138       --  entry family index (if applicable).
9139
9140       Install_Private_Data_Declarations
9141         (Loc, Task_Body_Procedure (Ttyp), Ttyp, N, Declarations (N));
9142
9143       --  Add a call to Abort_Undefer at the very beginning of the task
9144       --  body since this body is called with abort still deferred.
9145
9146       if Abort_Allowed then
9147          Call := Build_Runtime_Call (Loc, RE_Abort_Undefer);
9148          Insert_Before
9149            (First (Statements (Handled_Statement_Sequence (N))), Call);
9150          Analyze (Call);
9151       end if;
9152
9153       --  The statement part has already been protected with an at_end and
9154       --  cleanup actions. The call to Complete_Activation must be placed
9155       --  at the head of the sequence of statements of that block. The
9156       --  declarations have been merged in this sequence of statements but
9157       --  the first real statement is accessible from the First_Real_Statement
9158       --  field (which was set for exactly this purpose).
9159
9160       if Restricted_Profile then
9161          Call := Build_Runtime_Call (Loc, RE_Complete_Restricted_Activation);
9162       else
9163          Call := Build_Runtime_Call (Loc, RE_Complete_Activation);
9164       end if;
9165
9166       Insert_Before
9167         (First_Real_Statement (Handled_Statement_Sequence (N)), Call);
9168       Analyze (Call);
9169
9170       New_N :=
9171         Make_Subprogram_Body (Loc,
9172           Specification              => Build_Task_Proc_Specification (Ttyp),
9173           Declarations               => Declarations (N),
9174           Handled_Statement_Sequence => Handled_Statement_Sequence (N));
9175
9176       --  If the task contains generic instantiations, cleanup actions are
9177       --  delayed until after instantiation. Transfer the activation chain to
9178       --  the subprogram, to insure that the activation call is properly
9179       --  generated. It the task body contains inner tasks, indicate that the
9180       --  subprogram is a task master.
9181
9182       if Delay_Cleanups (Ttyp) then
9183          Set_Activation_Chain_Entity (New_N, Activation_Chain_Entity (N));
9184          Set_Is_Task_Master  (New_N, Is_Task_Master (N));
9185       end if;
9186
9187       Rewrite (N, New_N);
9188       Analyze (N);
9189
9190       --  Set elaboration flag immediately after task body. If the body is a
9191       --  subunit, the flag is set in the declarative part containing the stub.
9192
9193       if Nkind (Parent (N)) /= N_Subunit then
9194          Insert_After (N,
9195            Make_Assignment_Statement (Loc,
9196              Name =>
9197                Make_Identifier (Loc, New_External_Name (Chars (Ttyp), 'E')),
9198              Expression => New_Reference_To (Standard_True, Loc)));
9199       end if;
9200
9201       --  Ada 2005 (AI-345): Construct the primitive entry wrapper bodies after
9202       --  the task body. At this point the entry specs have been created,
9203       --  frozen and included in the dispatch table for the task type.
9204
9205       pragma Assert (Present (Corresponding_Record_Type (Ttyp)));
9206
9207       if Ada_Version >= Ada_05
9208         and then Present (Task_Definition (Parent (Ttyp)))
9209         and then Present (Abstract_Interfaces
9210                           (Corresponding_Record_Type (Ttyp)))
9211       then
9212          declare
9213             Current_Node : Node_Id;
9214             Vis_Decl     : Node_Id :=
9215               First (Visible_Declarations (Task_Definition (Parent (Ttyp))));
9216             Wrap_Body    : Node_Id;
9217
9218          begin
9219             if Nkind (Parent (N)) = N_Subunit then
9220                Current_Node := Corresponding_Stub (Parent (N));
9221             else
9222                Current_Node := N;
9223             end if;
9224
9225             --  Examine the visible declarations of the task type, looking for
9226             --  an entry declaration. We do not consider entry families since
9227             --  they cannot have dispatching operations, thus they do not need
9228             --  entry wrappers.
9229
9230             while Present (Vis_Decl) loop
9231                if Nkind (Vis_Decl) = N_Entry_Declaration
9232                  and then Ekind (Defining_Identifier (Vis_Decl)) = E_Entry
9233                then
9234                   --  Create the specification of the wrapper
9235
9236                   Wrap_Body :=
9237                     Build_Wrapper_Body (Loc,
9238                       Proc_Nam => Defining_Identifier (Vis_Decl),
9239                       Obj_Typ  => Corresponding_Record_Type (Ttyp),
9240                       Formals  => Parameter_Specifications (Vis_Decl));
9241
9242                   if Wrap_Body /= Empty then
9243                      Insert_After (Current_Node, Wrap_Body);
9244                      Current_Node := Wrap_Body;
9245
9246                      Analyze (Wrap_Body);
9247                   end if;
9248                end if;
9249
9250                Next (Vis_Decl);
9251             end loop;
9252          end;
9253       end if;
9254    end Expand_N_Task_Body;
9255
9256    ------------------------------------
9257    -- Expand_N_Task_Type_Declaration --
9258    ------------------------------------
9259
9260    --  We have several things to do. First we must create a Boolean flag used
9261    --  to mark if the body is elaborated yet. This variable gets set to True
9262    --  when the body of the task is elaborated (we can't rely on the normal
9263    --  ABE mechanism for the task body, since we need to pass an access to
9264    --  this elaboration boolean to the runtime routines).
9265
9266    --    taskE : aliased Boolean := False;
9267
9268    --  Next a variable is declared to hold the task stack size (either the
9269    --  default : Unspecified_Size, or a value that is set by a pragma
9270    --  Storage_Size). If the value of the pragma Storage_Size is static, then
9271    --  the variable is initialized with this value:
9272
9273    --    taskZ : Size_Type := Unspecified_Size;
9274    --  or
9275    --    taskZ : Size_Type := Size_Type (size_expression);
9276
9277    --  Note: No variable is needed to hold the task relative deadline since
9278    --  its value would never be static because the parameter is of a private
9279    --  type (Ada.Real_Time.Time_Span).
9280
9281    --  Next we create a corresponding record type declaration used to represent
9282    --  values of this task. The general form of this type declaration is
9283
9284    --    type taskV (discriminants) is record
9285    --      _Task_Id     : Task_Id;
9286    --      entry_family : array (bounds) of Void;
9287    --      _Priority    : Integer         := priority_expression;
9288    --      _Size        : Size_Type       := Size_Type (size_expression);
9289    --      _Task_Info   : Task_Info_Type  := task_info_expression;
9290    --    end record;
9291
9292    --  The discriminants are present only if the corresponding task type has
9293    --  discriminants, and they exactly mirror the task type discriminants.
9294
9295    --  The Id field is always present. It contains the Task_Id value, as set by
9296    --  the call to Create_Task. Note that although the task is limited, the
9297    --  task value record type is not limited, so there is no problem in passing
9298    --  this field as an out parameter to Create_Task.
9299
9300    --  One entry_family component is present for each entry family in the task
9301    --  definition. The bounds correspond to the bounds of the entry family
9302    --  (which may depend on discriminants). The element type is void, since we
9303    --  only need the bounds information for determining the entry index. Note
9304    --  that the use of an anonymous array would normally be illegal in this
9305    --  context, but this is a parser check, and the semantics is quite prepared
9306    --  to handle such a case.
9307
9308    --  The _Size field is present only if a Storage_Size pragma appears in the
9309    --  task definition. The expression captures the argument that was present
9310    --  in the pragma, and is used to override the task stack size otherwise
9311    --  associated with the task type.
9312
9313    --  The _Priority field is present only if a Priority or Interrupt_Priority
9314    --  pragma appears in the task definition. The expression captures the
9315    --  argument that was present in the pragma, and is used to provide the Size
9316    --  parameter to the call to Create_Task.
9317
9318    --  The _Task_Info field is present only if a Task_Info pragma appears in
9319    --  the task definition. The expression captures the argument that was
9320    --  present in the pragma, and is used to provide the Task_Image parameter
9321    --  to the call to Create_Task.
9322
9323    --  The _Relative_Deadline field is present only if a Relative_Deadline
9324    --  pragma appears in the task definition. The expression captures the
9325    --  argument that was present in the pragma, and is used to provide the
9326    --  Relative_Deadline parameter to the call to Create_Task.
9327
9328    --  When a task is declared, an instance of the task value record is
9329    --  created. The elaboration of this declaration creates the correct bounds
9330    --  for the entry families, and also evaluates the size, priority, and
9331    --  task_Info expressions if needed. The initialization routine for the task
9332    --  type itself then calls Create_Task with appropriate parameters to
9333    --  initialize the value of the Task_Id field.
9334
9335    --  Note: the address of this record is passed as the "Discriminants"
9336    --  parameter for Create_Task. Since Create_Task merely passes this onto the
9337    --  body procedure, it does not matter that it does not quite match the
9338    --  GNARLI model of what is being passed (the record contains more than just
9339    --  the discriminants, but the discriminants can be found from the record
9340    --  value).
9341
9342    --  The Entity_Id for this created record type is placed in the
9343    --  Corresponding_Record_Type field of the associated task type entity.
9344
9345    --  Next we create a procedure specification for the task body procedure:
9346
9347    --    procedure taskB (_Task : access taskV);
9348
9349    --  Note that this must come after the record type declaration, since
9350    --  the spec refers to this type. It turns out that the initialization
9351    --  procedure for the value type references the task body spec, but that's
9352    --  fine, since it won't be generated till the freeze point for the type,
9353    --  which is certainly after the task body spec declaration.
9354
9355    --  Finally, we set the task index value field of the entry attribute in
9356    --  the case of a simple entry.
9357
9358    procedure Expand_N_Task_Type_Declaration (N : Node_Id) is
9359       Loc     : constant Source_Ptr := Sloc (N);
9360       Tasktyp : constant Entity_Id  := Etype (Defining_Identifier (N));
9361       Tasknm  : constant Name_Id    := Chars (Tasktyp);
9362       Taskdef : constant Node_Id    := Task_Definition (N);
9363
9364       Proc_Spec  : Node_Id;
9365       Rec_Decl   : Node_Id;
9366       Rec_Ent    : Entity_Id;
9367       Cdecls     : List_Id;
9368       Elab_Decl  : Node_Id;
9369       Size_Decl  : Node_Id;
9370       Body_Decl  : Node_Id;
9371       Task_Size  : Node_Id;
9372       Ent_Stack  : Entity_Id;
9373       Decl_Stack : Node_Id;
9374
9375    begin
9376       --  If already expanded, nothing to do
9377
9378       if Present (Corresponding_Record_Type (Tasktyp)) then
9379          return;
9380       end if;
9381
9382       --  Here we will do the expansion
9383
9384       Rec_Decl := Build_Corresponding_Record (N, Tasktyp, Loc);
9385
9386       --  Ada 2005 (AI-345): Propagate the attribute that contains the list
9387       --  of implemented interfaces.
9388
9389       Set_Interface_List (Type_Definition (Rec_Decl), Interface_List (N));
9390
9391       Rec_Ent  := Defining_Identifier (Rec_Decl);
9392       Cdecls   := Component_Items (Component_List
9393                                      (Type_Definition (Rec_Decl)));
9394
9395       Qualify_Entity_Names (N);
9396
9397       --  First create the elaboration variable
9398
9399       Elab_Decl :=
9400         Make_Object_Declaration (Loc,
9401           Defining_Identifier =>
9402             Make_Defining_Identifier (Sloc (Tasktyp),
9403               Chars => New_External_Name (Tasknm, 'E')),
9404           Aliased_Present      => True,
9405           Object_Definition    => New_Reference_To (Standard_Boolean, Loc),
9406           Expression           => New_Reference_To (Standard_False, Loc));
9407       Insert_After (N, Elab_Decl);
9408
9409       --  Next create the declaration of the size variable (tasknmZ)
9410
9411       Set_Storage_Size_Variable (Tasktyp,
9412         Make_Defining_Identifier (Sloc (Tasktyp),
9413           Chars => New_External_Name (Tasknm, 'Z')));
9414
9415       if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) and then
9416         Is_Static_Expression (Expression (First (
9417           Pragma_Argument_Associations (Find_Task_Or_Protected_Pragma (
9418             Taskdef, Name_Storage_Size)))))
9419       then
9420          Size_Decl :=
9421            Make_Object_Declaration (Loc,
9422              Defining_Identifier => Storage_Size_Variable (Tasktyp),
9423              Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
9424              Expression =>
9425                Convert_To (RTE (RE_Size_Type),
9426                  Relocate_Node (
9427                    Expression (First (
9428                      Pragma_Argument_Associations (
9429                        Find_Task_Or_Protected_Pragma
9430                          (Taskdef, Name_Storage_Size)))))));
9431
9432       else
9433          Size_Decl :=
9434            Make_Object_Declaration (Loc,
9435              Defining_Identifier => Storage_Size_Variable (Tasktyp),
9436              Object_Definition => New_Reference_To (RTE (RE_Size_Type), Loc),
9437              Expression => New_Reference_To (RTE (RE_Unspecified_Size), Loc));
9438       end if;
9439
9440       Insert_After (Elab_Decl, Size_Decl);
9441
9442       --  Next build the rest of the corresponding record declaration. This is
9443       --  done last, since the corresponding record initialization procedure
9444       --  will reference the previously created entities.
9445
9446       --  Fill in the component declarations -- first the _Task_Id field
9447
9448       Append_To (Cdecls,
9449         Make_Component_Declaration (Loc,
9450           Defining_Identifier =>
9451             Make_Defining_Identifier (Loc, Name_uTask_Id),
9452           Component_Definition =>
9453             Make_Component_Definition (Loc,
9454               Aliased_Present    => False,
9455               Subtype_Indication => New_Reference_To (RTE (RO_ST_Task_Id),
9456                                     Loc))));
9457
9458       --  Declare static ATCB (that is, created by the expander) if we are
9459       --  using the Restricted run time.
9460
9461       if Restricted_Profile then
9462          Append_To (Cdecls,
9463            Make_Component_Declaration (Loc,
9464              Defining_Identifier  =>
9465                Make_Defining_Identifier (Loc, Name_uATCB),
9466
9467              Component_Definition =>
9468                Make_Component_Definition (Loc,
9469                  Aliased_Present     => True,
9470                  Subtype_Indication  => Make_Subtype_Indication (Loc,
9471                    Subtype_Mark => New_Occurrence_Of
9472                      (RTE (RE_Ada_Task_Control_Block), Loc),
9473
9474                    Constraint   =>
9475                      Make_Index_Or_Discriminant_Constraint (Loc,
9476                        Constraints =>
9477                          New_List (Make_Integer_Literal (Loc, 0)))))));
9478
9479       end if;
9480
9481       --  Declare static stack (that is, created by the expander) if we are
9482       --  using the Restricted run time on a bare board configuration.
9483
9484       if Restricted_Profile
9485         and then Preallocated_Stacks_On_Target
9486       then
9487          --  First we need to extract the appropriate stack size
9488
9489          Ent_Stack := Make_Defining_Identifier (Loc, Name_uStack);
9490
9491          if Present (Taskdef) and then Has_Storage_Size_Pragma (Taskdef) then
9492             declare
9493                Expr_N : constant Node_Id :=
9494                           Expression (First (
9495                             Pragma_Argument_Associations (
9496                               Find_Task_Or_Protected_Pragma
9497                                 (Taskdef, Name_Storage_Size))));
9498                Etyp   : constant Entity_Id := Etype (Expr_N);
9499                P      : constant Node_Id   := Parent (Expr_N);
9500
9501             begin
9502                --  The stack is defined inside the corresponding record.
9503                --  Therefore if the size of the stack is set by means of
9504                --  a discriminant, we must reference the discriminant of the
9505                --  corresponding record type.
9506
9507                if Nkind (Expr_N) in N_Has_Entity
9508                  and then Present (Discriminal_Link (Entity (Expr_N)))
9509                then
9510                   Task_Size :=
9511                     New_Reference_To
9512                       (CR_Discriminant (Discriminal_Link (Entity (Expr_N))),
9513                        Loc);
9514                   Set_Parent   (Task_Size, P);
9515                   Set_Etype    (Task_Size, Etyp);
9516                   Set_Analyzed (Task_Size);
9517
9518                else
9519                   Task_Size := Relocate_Node (Expr_N);
9520                end if;
9521             end;
9522
9523          else
9524             Task_Size :=
9525               New_Reference_To (RTE (RE_Default_Stack_Size), Loc);
9526          end if;
9527
9528          Decl_Stack := Make_Component_Declaration (Loc,
9529            Defining_Identifier  => Ent_Stack,
9530
9531            Component_Definition =>
9532              Make_Component_Definition (Loc,
9533                Aliased_Present     => True,
9534                Subtype_Indication  => Make_Subtype_Indication (Loc,
9535                  Subtype_Mark =>
9536                    New_Occurrence_Of (RTE (RE_Storage_Array), Loc),
9537
9538                  Constraint   =>
9539                    Make_Index_Or_Discriminant_Constraint (Loc,
9540                      Constraints  => New_List (Make_Range (Loc,
9541                        Low_Bound  => Make_Integer_Literal (Loc, 1),
9542                        High_Bound => Convert_To (RTE (RE_Storage_Offset),
9543                          Task_Size)))))));
9544
9545          Append_To (Cdecls, Decl_Stack);
9546
9547          --  The appropriate alignment for the stack is ensured by the run-time
9548          --  code in charge of task creation.
9549
9550       end if;
9551
9552       --  Add components for entry families
9553
9554       Collect_Entry_Families (Loc, Cdecls, Size_Decl, Tasktyp);
9555
9556       --  Add the _Priority component if a Priority pragma is present
9557
9558       if Present (Taskdef) and then Has_Priority_Pragma (Taskdef) then
9559          declare
9560             Prag : constant Node_Id :=
9561                      Find_Task_Or_Protected_Pragma (Taskdef, Name_Priority);
9562             Expr : Node_Id;
9563
9564          begin
9565             Expr := First (Pragma_Argument_Associations (Prag));
9566
9567             if Nkind (Expr) = N_Pragma_Argument_Association then
9568                Expr := Expression (Expr);
9569             end if;
9570
9571             Expr := New_Copy_Tree (Expr);
9572
9573             --  Add conversion to proper type to do range check if required
9574             --  Note that for runtime units, we allow out of range interrupt
9575             --  priority values to be used in a priority pragma. This is for
9576             --  the benefit of some versions of System.Interrupts which use
9577             --  a special server task with maximum interrupt priority.
9578
9579             if Pragma_Name (Prag) = Name_Priority
9580               and then not GNAT_Mode
9581             then
9582                Rewrite (Expr, Convert_To (RTE (RE_Priority), Expr));
9583             else
9584                Rewrite (Expr, Convert_To (RTE (RE_Any_Priority), Expr));
9585             end if;
9586
9587             Append_To (Cdecls,
9588               Make_Component_Declaration (Loc,
9589                 Defining_Identifier =>
9590                   Make_Defining_Identifier (Loc, Name_uPriority),
9591                 Component_Definition =>
9592                   Make_Component_Definition (Loc,
9593                     Aliased_Present    => False,
9594                     Subtype_Indication => New_Reference_To (Standard_Integer,
9595                                                             Loc)),
9596                 Expression => Expr));
9597          end;
9598       end if;
9599
9600       --  Add the _Task_Size component if a Storage_Size pragma is present
9601
9602       if Present (Taskdef)
9603         and then Has_Storage_Size_Pragma (Taskdef)
9604       then
9605          Append_To (Cdecls,
9606            Make_Component_Declaration (Loc,
9607              Defining_Identifier =>
9608                Make_Defining_Identifier (Loc, Name_uSize),
9609
9610              Component_Definition =>
9611                Make_Component_Definition (Loc,
9612                  Aliased_Present    => False,
9613                  Subtype_Indication => New_Reference_To (RTE (RE_Size_Type),
9614                                                          Loc)),
9615
9616              Expression =>
9617                Convert_To (RTE (RE_Size_Type),
9618                  Relocate_Node (
9619                    Expression (First (
9620                      Pragma_Argument_Associations (
9621                        Find_Task_Or_Protected_Pragma
9622                          (Taskdef, Name_Storage_Size))))))));
9623       end if;
9624
9625       --  Add the _Task_Info component if a Task_Info pragma is present
9626
9627       if Present (Taskdef) and then Has_Task_Info_Pragma (Taskdef) then
9628          Append_To (Cdecls,
9629            Make_Component_Declaration (Loc,
9630              Defining_Identifier =>
9631                Make_Defining_Identifier (Loc, Name_uTask_Info),
9632
9633              Component_Definition =>
9634                Make_Component_Definition (Loc,
9635                  Aliased_Present    => False,
9636                  Subtype_Indication =>
9637                    New_Reference_To (RTE (RE_Task_Info_Type), Loc)),
9638
9639              Expression => New_Copy (
9640                Expression (First (
9641                  Pragma_Argument_Associations (
9642                    Find_Task_Or_Protected_Pragma
9643                      (Taskdef, Name_Task_Info)))))));
9644       end if;
9645
9646       --  Add the _Relative_Deadline component if a Relative_Deadline pragma is
9647       --  present. If we are using a restricted run time this component will
9648       --  not be added (deadlines are not allowed by the Ravenscar profile).
9649
9650       if not Restricted_Profile
9651         and then Present (Taskdef)
9652         and then Has_Relative_Deadline_Pragma (Taskdef)
9653       then
9654          Append_To (Cdecls,
9655            Make_Component_Declaration (Loc,
9656              Defining_Identifier =>
9657                Make_Defining_Identifier (Loc, Name_uRelative_Deadline),
9658
9659              Component_Definition =>
9660                Make_Component_Definition (Loc,
9661                  Aliased_Present    => False,
9662                  Subtype_Indication =>
9663                    New_Reference_To (RTE (RE_Time_Span), Loc)),
9664
9665              Expression =>
9666                Convert_To (RTE (RE_Time_Span),
9667                  Relocate_Node (
9668                    Expression (First (
9669                      Pragma_Argument_Associations (
9670                        Find_Task_Or_Protected_Pragma
9671                          (Taskdef, Name_Relative_Deadline))))))));
9672       end if;
9673
9674       Insert_After (Size_Decl, Rec_Decl);
9675
9676       --  Analyze the record declaration immediately after construction,
9677       --  because the initialization procedure is needed for single task
9678       --  declarations before the next entity is analyzed.
9679
9680       Analyze (Rec_Decl);
9681
9682       --  Create the declaration of the task body procedure
9683
9684       Proc_Spec := Build_Task_Proc_Specification (Tasktyp);
9685       Body_Decl :=
9686         Make_Subprogram_Declaration (Loc,
9687           Specification => Proc_Spec);
9688
9689       Insert_After (Rec_Decl, Body_Decl);
9690
9691       --  The subprogram does not comes from source, so we have to indicate the
9692       --  need for debugging information explicitly.
9693
9694       if Comes_From_Source (Original_Node (N)) then
9695          Set_Debug_Info_Needed (Defining_Entity (Proc_Spec));
9696       end if;
9697
9698       --  Ada 2005 (AI-345): Construct the primitive entry wrapper specs before
9699       --  the corresponding record has been frozen.
9700
9701       if Ada_Version >= Ada_05
9702         and then Present (Taskdef)
9703         and then Present (Corresponding_Record_Type
9704                           (Defining_Identifier (Parent (Taskdef))))
9705         and then Present (Abstract_Interfaces
9706                           (Corresponding_Record_Type
9707                            (Defining_Identifier (Parent (Taskdef)))))
9708       then
9709          declare
9710             Current_Node : Node_Id := Rec_Decl;
9711             Vis_Decl     : Node_Id := First (Visible_Declarations (Taskdef));
9712             Wrap_Spec    : Node_Id;
9713             New_N        : Node_Id;
9714
9715          begin
9716             --  Examine the visible declarations of the task type, looking for
9717             --  an entry declaration. We do not consider entry families since
9718             --  they cannot have dispatching operations, thus they do not need
9719             --  entry wrappers.
9720
9721             while Present (Vis_Decl) loop
9722                if Nkind (Vis_Decl) = N_Entry_Declaration
9723                  and then Ekind (Defining_Identifier (Vis_Decl)) = E_Entry
9724                then
9725                   Wrap_Spec :=
9726                     Build_Wrapper_Spec (Loc,
9727                       Proc_Nam => Defining_Identifier (Vis_Decl),
9728                       Obj_Typ  => Etype (Rec_Ent),
9729                       Formals  => Parameter_Specifications (Vis_Decl));
9730
9731                   if Wrap_Spec /= Empty then
9732                      New_N :=
9733                        Make_Subprogram_Declaration (Loc,
9734                          Specification => Wrap_Spec);
9735
9736                      Insert_After (Current_Node, New_N);
9737                      Current_Node := New_N;
9738
9739                      Analyze (New_N);
9740                   end if;
9741                end if;
9742
9743                Next (Vis_Decl);
9744             end loop;
9745          end;
9746       end if;
9747
9748       --  Ada 2005 (AI-345): We must defer freezing to allow further
9749       --  declaration of primitive subprograms covering task interfaces
9750
9751       if Ada_Version <= Ada_95 then
9752
9753          --  Now we can freeze the corresponding record. This needs manually
9754          --  freezing, since it is really part of the task type, and the task
9755          --  type is frozen at this stage. We of course need the initialization
9756          --  procedure for this corresponding record type and we won't get it
9757          --  in time if we don't freeze now.
9758
9759          declare
9760             L : constant List_Id := Freeze_Entity (Rec_Ent, Loc);
9761
9762          begin
9763             if Is_Non_Empty_List (L) then
9764                Insert_List_After (Body_Decl, L);
9765             end if;
9766          end;
9767       end if;
9768
9769       --  Complete the expansion of access types to the current task type, if
9770       --  any were declared.
9771
9772       Expand_Previous_Access_Type (Tasktyp);
9773    end Expand_N_Task_Type_Declaration;
9774
9775    -------------------------------
9776    -- Expand_N_Timed_Entry_Call --
9777    -------------------------------
9778
9779    --  A timed entry call in normal case is not implemented using ATC mechanism
9780    --  anymore for efficiency reason.
9781
9782    --     select
9783    --        T.E;
9784    --        S1;
9785    --     or
9786    --        Delay D;
9787    --        S2;
9788    --     end select;
9789
9790    --  is expanded as follow:
9791
9792    --  1) When T.E is a task entry_call;
9793
9794    --    declare
9795    --       B  : Boolean;
9796    --       X  : Task_Entry_Index := <entry index>;
9797    --       DX : Duration := To_Duration (D);
9798    --       M  : Delay_Mode := <discriminant>;
9799    --       P  : parms := (parm, parm, parm);
9800
9801    --    begin
9802    --       Timed_Protected_Entry_Call
9803    --         (<acceptor-task>, X, P'Address, DX, M, B);
9804    --       if B then
9805    --          S1;
9806    --       else
9807    --          S2;
9808    --       end if;
9809    --    end;
9810
9811    --  2) When T.E is a protected entry_call;
9812
9813    --    declare
9814    --       B  : Boolean;
9815    --       X  : Protected_Entry_Index := <entry index>;
9816    --       DX : Duration := To_Duration (D);
9817    --       M  : Delay_Mode := <discriminant>;
9818    --       P  : parms := (parm, parm, parm);
9819
9820    --    begin
9821    --       Timed_Protected_Entry_Call
9822    --         (<object>'unchecked_access, X, P'Address, DX, M, B);
9823    --       if B then
9824    --          S1;
9825    --       else
9826    --          S2;
9827    --       end if;
9828    --    end;
9829
9830    --  3) Ada 2005 (AI-345): When T.E is a dispatching procedure call;
9831
9832    --    declare
9833    --       B  : Boolean := False;
9834    --       C  : Ada.Tags.Prim_Op_Kind;
9835    --       DX : Duration := To_Duration (D)
9836    --       K  : Ada.Tags.Tagged_Kind :=
9837    --              Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag (<object>));
9838    --       M  : Integer :=...;
9839    --       P  : Parameters := (Param1 .. ParamN);
9840    --       S  : Iteger;
9841
9842    --    begin
9843    --       if K = Ada.Tags.TK_Limited_Tagged then
9844    --          <dispatching-call>;
9845    --          <triggering-statements>
9846
9847    --       else
9848    --          S :=
9849    --            Ada.Tags.Get_Offset_Index
9850    --              (Ada.Tags.Tag (<object>), DT_Position (<dispatching-call>));
9851
9852    --          _Disp_Timed_Select (<object>, S, P'Address, DX, M, C, B);
9853
9854    --          if C = POK_Protected_Entry
9855    --            or else C = POK_Task_Entry
9856    --          then
9857    --             Param1 := P.Param1;
9858    --             ...
9859    --             ParamN := P.ParamN;
9860    --          end if;
9861
9862    --          if B then
9863    --             if C = POK_Procedure
9864    --               or else C = POK_Protected_Procedure
9865    --               or else C = POK_Task_Procedure
9866    --             then
9867    --                <dispatching-call>;
9868    --             end if;
9869
9870    --             <triggering-statements>
9871    --          else
9872    --             <timed-statements>
9873    --          end if;
9874    --       end if;
9875    --    end;
9876
9877    procedure Expand_N_Timed_Entry_Call (N : Node_Id) is
9878       Loc : constant Source_Ptr := Sloc (N);
9879
9880       E_Call  : Node_Id :=
9881                   Entry_Call_Statement (Entry_Call_Alternative (N));
9882       E_Stats : constant List_Id :=
9883                   Statements (Entry_Call_Alternative (N));
9884       D_Stat  : Node_Id :=
9885                   Delay_Statement (Delay_Alternative (N));
9886       D_Stats : constant List_Id :=
9887                   Statements (Delay_Alternative (N));
9888
9889       Actuals        : List_Id;
9890       Blk_Typ        : Entity_Id;
9891       Call           : Node_Id;
9892       Call_Ent       : Entity_Id;
9893       Conc_Typ_Stmts : List_Id;
9894       Concval        : Node_Id;
9895       D_Conv         : Node_Id;
9896       D_Disc         : Node_Id;
9897       D_Type         : Entity_Id;
9898       Decls          : List_Id;
9899       Dummy          : Node_Id;
9900       Ename          : Node_Id;
9901       Formals        : List_Id;
9902       Index          : Node_Id;
9903       Is_Disp_Select : Boolean;
9904       Lim_Typ_Stmts  : List_Id;
9905       N_Stats        : List_Id;
9906       Obj            : Entity_Id;
9907       Param          : Node_Id;
9908       Params         : List_Id;
9909       Stmt           : Node_Id;
9910       Stmts          : List_Id;
9911       Unpack         : List_Id;
9912
9913       B : Entity_Id;  --  Call status flag
9914       C : Entity_Id;  --  Call kind
9915       D : Entity_Id;  --  Delay
9916       K : Entity_Id;  --  Tagged kind
9917       M : Entity_Id;  --  Delay mode
9918       P : Entity_Id;  --  Parameter block
9919       S : Entity_Id;  --  Primitive operation slot
9920
9921    begin
9922       --  The arguments in the call may require dynamic allocation, and the
9923       --  call statement may have been transformed into a block. The block
9924       --  may contain additional declarations for internal entities, and the
9925       --  original call is found by sequential search.
9926
9927       if Nkind (E_Call) = N_Block_Statement then
9928          E_Call := First (Statements (Handled_Statement_Sequence (E_Call)));
9929          while not Nkind_In (E_Call, N_Procedure_Call_Statement,
9930                                      N_Entry_Call_Statement)
9931          loop
9932             Next (E_Call);
9933          end loop;
9934       end if;
9935
9936       Is_Disp_Select :=
9937         Ada_Version >= Ada_05
9938           and then Nkind (E_Call) = N_Procedure_Call_Statement;
9939
9940       if Is_Disp_Select then
9941          Extract_Dispatching_Call (E_Call, Call_Ent, Obj, Actuals, Formals);
9942
9943          Decls := New_List;
9944          Stmts := New_List;
9945
9946          --  Generate:
9947          --    B : Boolean := False;
9948
9949          B := Build_B (Loc, Decls);
9950
9951          --  Generate:
9952          --    C : Ada.Tags.Prim_Op_Kind;
9953
9954          C := Build_C (Loc, Decls);
9955
9956          --  Because the analysis of all statements was disabled, manually
9957          --  analyze the delay statement.
9958
9959          Analyze (D_Stat);
9960          D_Stat := Original_Node (D_Stat);
9961
9962       else
9963          --  Build an entry call using Simple_Entry_Call
9964
9965          Extract_Entry (E_Call, Concval, Ename, Index);
9966          Build_Simple_Entry_Call (E_Call, Concval, Ename, Index);
9967
9968          Decls := Declarations (E_Call);
9969          Stmts := Statements (Handled_Statement_Sequence (E_Call));
9970
9971          if No (Decls) then
9972             Decls := New_List;
9973          end if;
9974
9975          --  Generate:
9976          --    B : Boolean;
9977
9978          B := Make_Defining_Identifier (Loc, Name_uB);
9979
9980          Prepend_To (Decls,
9981            Make_Object_Declaration (Loc,
9982              Defining_Identifier =>
9983                B,
9984              Object_Definition =>
9985                New_Reference_To (Standard_Boolean, Loc)));
9986       end if;
9987
9988       --  Duration and mode processing
9989
9990       D_Type := Base_Type (Etype (Expression (D_Stat)));
9991
9992       --  Use the type of the delay expression (Calendar or Real_Time) to
9993       --  generate the appropriate conversion.
9994
9995       if Nkind (D_Stat) = N_Delay_Relative_Statement then
9996          D_Disc := Make_Integer_Literal (Loc, 0);
9997          D_Conv := Relocate_Node (Expression (D_Stat));
9998
9999       elsif Is_RTE (D_Type, RO_CA_Time) then
10000          D_Disc := Make_Integer_Literal (Loc, 1);
10001          D_Conv := Make_Function_Call (Loc,
10002            New_Reference_To (RTE (RO_CA_To_Duration), Loc),
10003            New_List (New_Copy (Expression (D_Stat))));
10004
10005       else pragma Assert (Is_RTE (D_Type, RO_RT_Time));
10006          D_Disc := Make_Integer_Literal (Loc, 2);
10007          D_Conv := Make_Function_Call (Loc,
10008            New_Reference_To (RTE (RO_RT_To_Duration), Loc),
10009            New_List (New_Copy (Expression (D_Stat))));
10010       end if;
10011
10012       D := Make_Defining_Identifier (Loc, New_Internal_Name ('D'));
10013
10014       --  Generate:
10015       --    D : Duration;
10016
10017       Append_To (Decls,
10018         Make_Object_Declaration (Loc,
10019           Defining_Identifier =>
10020             D,
10021           Object_Definition =>
10022             New_Reference_To (Standard_Duration, Loc)));
10023
10024       M := Make_Defining_Identifier (Loc, New_Internal_Name ('M'));
10025
10026       --  Generate:
10027       --    M : Integer := (0 | 1 | 2);
10028
10029       Append_To (Decls,
10030         Make_Object_Declaration (Loc,
10031           Defining_Identifier =>
10032             M,
10033           Object_Definition =>
10034             New_Reference_To (Standard_Integer, Loc),
10035           Expression =>
10036             D_Disc));
10037
10038       --  Do the assignment at this stage only because the evaluation of the
10039       --  expression must not occur before (see ACVC C97302A).
10040
10041       Append_To (Stmts,
10042         Make_Assignment_Statement (Loc,
10043           Name =>
10044             New_Reference_To (D, Loc),
10045           Expression =>
10046             D_Conv));
10047
10048       --  Parameter block processing
10049
10050       --  Manually create the parameter block for dispatching calls. In the
10051       --  case of entries, the block has already been created during the call
10052       --  to Build_Simple_Entry_Call.
10053
10054       if Is_Disp_Select then
10055
10056          --  Tagged kind processing, generate:
10057          --    K : Ada.Tags.Tagged_Kind :=
10058          --          Ada.Tags.Get_Tagged_Kind (Ada.Tags.Tag <object>));
10059
10060          K := Build_K (Loc, Decls, Obj);
10061
10062          Blk_Typ := Build_Parameter_Block (Loc, Actuals, Formals, Decls);
10063          P := Parameter_Block_Pack
10064                 (Loc, Blk_Typ, Actuals, Formals, Decls, Stmts);
10065
10066          --  Dispatch table slot processing, generate:
10067          --    S : Integer;
10068
10069          S := Build_S (Loc, Decls);
10070
10071          --  Generate:
10072          --    S := Ada.Tags.Get_Offset_Index
10073          --           (Ada.Tags.Tag (<object>), DT_Position (Call_Ent));
10074
10075          Conc_Typ_Stmts :=
10076            New_List (Build_S_Assignment (Loc, S, Obj, Call_Ent));
10077
10078          --  Generate:
10079          --    _Disp_Timed_Select (<object>, S, P'Address, D, M, C, B);
10080
10081          --  where Obj is the controlling formal parameter, S is the dispatch
10082          --  table slot number of the dispatching operation, P is the wrapped
10083          --  parameter block, D is the duration, M is the duration mode, C is
10084          --  the call kind and B is the call status.
10085
10086          Params := New_List;
10087
10088          Append_To (Params, New_Copy_Tree (Obj));
10089          Append_To (Params, New_Reference_To (S, Loc));
10090          Append_To (Params, Make_Attribute_Reference (Loc,
10091                               Prefix => New_Reference_To (P, Loc),
10092                               Attribute_Name => Name_Address));
10093          Append_To (Params, New_Reference_To (D, Loc));
10094          Append_To (Params, New_Reference_To (M, Loc));
10095          Append_To (Params, New_Reference_To (C, Loc));
10096          Append_To (Params, New_Reference_To (B, Loc));
10097
10098          Append_To (Conc_Typ_Stmts,
10099            Make_Procedure_Call_Statement (Loc,
10100              Name =>
10101                New_Reference_To (
10102                  Find_Prim_Op (Etype (Etype (Obj)),
10103                    Name_uDisp_Timed_Select),
10104                  Loc),
10105              Parameter_Associations =>
10106                Params));
10107
10108          --  Generate:
10109          --    if C = POK_Protected_Entry
10110          --      or else C = POK_Task_Entry
10111          --    then
10112          --       Param1 := P.Param1;
10113          --       ...
10114          --       ParamN := P.ParamN;
10115          --    end if;
10116
10117          Unpack := Parameter_Block_Unpack (Loc, P, Actuals, Formals);
10118
10119          --  Generate the if statement only when the packed parameters need
10120          --  explicit assignments to their corresponding actuals.
10121
10122          if Present (Unpack) then
10123             Append_To (Conc_Typ_Stmts,
10124               Make_If_Statement (Loc,
10125
10126                 Condition =>
10127                   Make_Or_Else (Loc,
10128                     Left_Opnd =>
10129                       Make_Op_Eq (Loc,
10130                         Left_Opnd =>
10131                           New_Reference_To (C, Loc),
10132                         Right_Opnd =>
10133                           New_Reference_To (RTE (
10134                             RE_POK_Protected_Entry), Loc)),
10135                     Right_Opnd =>
10136                       Make_Op_Eq (Loc,
10137                         Left_Opnd =>
10138                           New_Reference_To (C, Loc),
10139                         Right_Opnd =>
10140                           New_Reference_To (RTE (RE_POK_Task_Entry), Loc))),
10141
10142                 Then_Statements =>
10143                   Unpack));
10144          end if;
10145
10146          --  Generate:
10147
10148          --    if B then
10149          --       if C = POK_Procedure
10150          --         or else C = POK_Protected_Procedure
10151          --         or else C = POK_Task_Procedure
10152          --       then
10153          --          <dispatching-call>
10154          --       end if;
10155          --       <triggering-statements>
10156          --    else
10157          --       <timed-statements>
10158          --    end if;
10159
10160          N_Stats := New_Copy_List_Tree (E_Stats);
10161
10162          Prepend_To (N_Stats,
10163            Make_If_Statement (Loc,
10164
10165              Condition =>
10166                Make_Or_Else (Loc,
10167                  Left_Opnd =>
10168                    Make_Op_Eq (Loc,
10169                      Left_Opnd =>
10170                        New_Reference_To (C, Loc),
10171                      Right_Opnd =>
10172                        New_Reference_To (RTE (RE_POK_Procedure), Loc)),
10173                  Right_Opnd =>
10174                    Make_Or_Else (Loc,
10175                      Left_Opnd =>
10176                        Make_Op_Eq (Loc,
10177                          Left_Opnd =>
10178                            New_Reference_To (C, Loc),
10179                          Right_Opnd =>
10180                            New_Reference_To (RTE (
10181                              RE_POK_Protected_Procedure), Loc)),
10182                      Right_Opnd =>
10183                        Make_Op_Eq (Loc,
10184                          Left_Opnd =>
10185                            New_Reference_To (C, Loc),
10186                          Right_Opnd =>
10187                            New_Reference_To (RTE (
10188                              RE_POK_Task_Procedure), Loc)))),
10189
10190              Then_Statements =>
10191                New_List (E_Call)));
10192
10193          Append_To (Conc_Typ_Stmts,
10194            Make_If_Statement (Loc,
10195              Condition => New_Reference_To (B, Loc),
10196              Then_Statements => N_Stats,
10197              Else_Statements => D_Stats));
10198
10199          --  Generate:
10200          --    <dispatching-call>;
10201          --    <triggering-statements>
10202
10203          Lim_Typ_Stmts := New_Copy_List_Tree (E_Stats);
10204          Prepend_To (Lim_Typ_Stmts, New_Copy_Tree (E_Call));
10205
10206          --  Generate:
10207          --    if K = Ada.Tags.TK_Limited_Tagged then
10208          --       Lim_Typ_Stmts
10209          --    else
10210          --       Conc_Typ_Stmts
10211          --    end if;
10212
10213          Append_To (Stmts,
10214            Make_If_Statement (Loc,
10215              Condition =>
10216                Make_Op_Eq (Loc,
10217                  Left_Opnd =>
10218                    New_Reference_To (K, Loc),
10219                  Right_Opnd =>
10220                    New_Reference_To (RTE (RE_TK_Limited_Tagged), Loc)),
10221
10222              Then_Statements =>
10223                Lim_Typ_Stmts,
10224
10225              Else_Statements =>
10226                Conc_Typ_Stmts));
10227
10228       else
10229          --  Skip assignments to temporaries created for in-out parameters.
10230          --  This makes unwarranted assumptions about the shape of the expanded
10231          --  tree for the call, and should be cleaned up ???
10232
10233          Stmt := First (Stmts);
10234          while Nkind (Stmt) /= N_Procedure_Call_Statement loop
10235             Next (Stmt);
10236          end loop;
10237
10238          --  Do the assignment at this stage only because the evaluation
10239          --  of the expression must not occur before (see ACVC C97302A).
10240
10241          Insert_Before (Stmt,
10242            Make_Assignment_Statement (Loc,
10243              Name => New_Reference_To (D, Loc),
10244              Expression => D_Conv));
10245
10246          Call   := Stmt;
10247          Params := Parameter_Associations (Call);
10248
10249          --  For a protected type, we build a Timed_Protected_Entry_Call
10250
10251          if Is_Protected_Type (Etype (Concval)) then
10252
10253             --  Create a new call statement
10254
10255             Param := First (Params);
10256             while Present (Param)
10257               and then not Is_RTE (Etype (Param), RE_Call_Modes)
10258             loop
10259                Next (Param);
10260             end loop;
10261
10262             Dummy := Remove_Next (Next (Param));
10263
10264             --  Remove garbage is following the Cancel_Param if present
10265
10266             Dummy := Next (Param);
10267
10268             --  Remove the mode of the Protected_Entry_Call call, then remove
10269             --  the Communication_Block of the Protected_Entry_Call call, and
10270             --  finally add Duration and a Delay_Mode parameter
10271
10272             pragma Assert (Present (Param));
10273             Rewrite (Param, New_Reference_To (D, Loc));
10274
10275             Rewrite (Dummy, New_Reference_To (M, Loc));
10276
10277             --  Add a Boolean flag for successful entry call
10278
10279             Append_To (Params, New_Reference_To (B, Loc));
10280
10281             case Corresponding_Runtime_Package (Etype (Concval)) is
10282                when System_Tasking_Protected_Objects_Entries =>
10283                   Rewrite (Call,
10284                     Make_Procedure_Call_Statement (Loc,
10285                       Name =>
10286                         New_Reference_To
10287                           (RTE (RE_Timed_Protected_Entry_Call), Loc),
10288                       Parameter_Associations => Params));
10289
10290                when System_Tasking_Protected_Objects_Single_Entry =>
10291                   Param := First (Params);
10292                   while Present (Param)
10293                     and then not
10294                       Is_RTE (Etype (Param), RE_Protected_Entry_Index)
10295                   loop
10296                      Next (Param);
10297                   end loop;
10298
10299                   Remove (Param);
10300
10301                   Rewrite (Call,
10302                     Make_Procedure_Call_Statement (Loc,
10303                       Name => New_Reference_To (
10304                         RTE (RE_Timed_Protected_Single_Entry_Call), Loc),
10305                       Parameter_Associations => Params));
10306
10307                when others =>
10308                   raise Program_Error;
10309             end case;
10310
10311          --  For the task case, build a Timed_Task_Entry_Call
10312
10313          else
10314             --  Create a new call statement
10315
10316             Append_To (Params, New_Reference_To (D, Loc));
10317             Append_To (Params, New_Reference_To (M, Loc));
10318             Append_To (Params, New_Reference_To (B, Loc));
10319
10320             Rewrite (Call,
10321               Make_Procedure_Call_Statement (Loc,
10322                 Name =>
10323                   New_Reference_To (RTE (RE_Timed_Task_Entry_Call), Loc),
10324                 Parameter_Associations => Params));
10325          end if;
10326
10327          Append_To (Stmts,
10328            Make_Implicit_If_Statement (N,
10329              Condition => New_Reference_To (B, Loc),
10330              Then_Statements => E_Stats,
10331              Else_Statements => D_Stats));
10332       end if;
10333
10334       Rewrite (N,
10335         Make_Block_Statement (Loc,
10336           Declarations => Decls,
10337           Handled_Statement_Sequence =>
10338             Make_Handled_Sequence_Of_Statements (Loc, Stmts)));
10339
10340       Analyze (N);
10341    end Expand_N_Timed_Entry_Call;
10342
10343    ----------------------------------------
10344    -- Expand_Protected_Body_Declarations --
10345    ----------------------------------------
10346
10347    procedure Expand_Protected_Body_Declarations
10348      (N       : Node_Id;
10349       Spec_Id : Entity_Id)
10350    is
10351    begin
10352       if No_Run_Time_Mode then
10353          Error_Msg_CRT ("protected body", N);
10354          return;
10355
10356       elsif Expander_Active then
10357
10358          --  Associate discriminals with the first subprogram or entry body to
10359          --  be expanded.
10360
10361          if Present (First_Protected_Operation (Declarations (N))) then
10362             Set_Discriminals (Parent (Spec_Id));
10363          end if;
10364       end if;
10365    end Expand_Protected_Body_Declarations;
10366
10367    -------------------------
10368    -- External_Subprogram --
10369    -------------------------
10370
10371    function External_Subprogram (E : Entity_Id) return Entity_Id is
10372       Subp : constant Entity_Id := Protected_Body_Subprogram (E);
10373
10374    begin
10375       --  The internal and external subprograms follow each other on the entity
10376       --  chain. Note that previously private operations had no separate
10377       --  external subprogram. We now create one in all cases, because a
10378       --  private operation may actually appear in an external call, through
10379       --  a 'Access reference used for a callback.
10380
10381       --  If the operation is a function that returns an anonymous access type,
10382       --  the corresponding itype appears before the operation, and must be
10383       --  skipped.
10384
10385       --  This mechanism is fragile, there should be a real link between the
10386       --  two versions of the operation, but there is no place to put it ???
10387
10388       if Is_Access_Type (Next_Entity (Subp)) then
10389          return Next_Entity (Next_Entity (Subp));
10390       else
10391          return Next_Entity (Subp);
10392       end if;
10393    end External_Subprogram;
10394
10395    ------------------------------
10396    -- Extract_Dispatching_Call --
10397    ------------------------------
10398
10399    procedure Extract_Dispatching_Call
10400      (N        : Node_Id;
10401       Call_Ent : out Entity_Id;
10402       Object   : out Entity_Id;
10403       Actuals  : out List_Id;
10404       Formals  : out List_Id)
10405    is
10406       Call_Nam : Node_Id;
10407
10408    begin
10409       pragma Assert (Nkind (N) = N_Procedure_Call_Statement);
10410
10411       if Present (Original_Node (N)) then
10412          Call_Nam := Name (Original_Node (N));
10413       else
10414          Call_Nam := Name (N);
10415       end if;
10416
10417       --  Retrieve the name of the dispatching procedure. It contains the
10418       --  dispatch table slot number.
10419
10420       loop
10421          case Nkind (Call_Nam) is
10422             when N_Identifier =>
10423                exit;
10424
10425             when N_Selected_Component =>
10426                Call_Nam := Selector_Name (Call_Nam);
10427
10428             when others =>
10429                raise Program_Error;
10430
10431          end case;
10432       end loop;
10433
10434       Actuals  := Parameter_Associations (N);
10435       Call_Ent := Entity (Call_Nam);
10436       Formals  := Parameter_Specifications (Parent (Call_Ent));
10437       Object   := First (Actuals);
10438
10439       if Present (Original_Node (Object)) then
10440          Object := Original_Node (Object);
10441       end if;
10442    end Extract_Dispatching_Call;
10443
10444    -------------------
10445    -- Extract_Entry --
10446    -------------------
10447
10448    procedure Extract_Entry
10449      (N       : Node_Id;
10450       Concval : out Node_Id;
10451       Ename   : out Node_Id;
10452       Index   : out Node_Id)
10453    is
10454       Nam : constant Node_Id := Name (N);
10455
10456    begin
10457       --  For a simple entry, the name is a selected component, with the
10458       --  prefix being the task value, and the selector being the entry.
10459
10460       if Nkind (Nam) = N_Selected_Component then
10461          Concval := Prefix (Nam);
10462          Ename   := Selector_Name (Nam);
10463          Index   := Empty;
10464
10465       --  For a member of an entry family, the name is an indexed component
10466       --  where the prefix is a selected component, whose prefix in turn is
10467       --  the task value, and whose selector is the entry family. The single
10468       --  expression in the expressions list of the indexed component is the
10469       --  subscript for the family.
10470
10471       else pragma Assert (Nkind (Nam) = N_Indexed_Component);
10472          Concval := Prefix (Prefix (Nam));
10473          Ename   := Selector_Name (Prefix (Nam));
10474          Index   := First (Expressions (Nam));
10475       end if;
10476    end Extract_Entry;
10477
10478    -------------------
10479    -- Family_Offset --
10480    -------------------
10481
10482    function Family_Offset
10483      (Loc  : Source_Ptr;
10484       Hi   : Node_Id;
10485       Lo   : Node_Id;
10486       Ttyp : Entity_Id;
10487       Cap  : Boolean) return Node_Id
10488    is
10489       Ityp : Entity_Id;
10490       Real_Hi : Node_Id;
10491       Real_Lo : Node_Id;
10492
10493       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id;
10494       --  If one of the bounds is a reference to a discriminant, replace with
10495       --  corresponding discriminal of type. Within the body of a task retrieve
10496       --  the renamed discriminant by simple visibility, using its generated
10497       --  name. Within a protected object, find the original discriminant and
10498       --  replace it with the discriminal of the current protected operation.
10499
10500       ------------------------------
10501       -- Convert_Discriminant_Ref --
10502       ------------------------------
10503
10504       function Convert_Discriminant_Ref (Bound : Node_Id) return Node_Id is
10505          Loc : constant Source_Ptr := Sloc (Bound);
10506          B   : Node_Id;
10507          D   : Entity_Id;
10508
10509       begin
10510          if Is_Entity_Name (Bound)
10511            and then Ekind (Entity (Bound)) = E_Discriminant
10512          then
10513             if Is_Task_Type (Ttyp)
10514               and then Has_Completion (Ttyp)
10515             then
10516                B := Make_Identifier (Loc, Chars (Entity (Bound)));
10517                Find_Direct_Name (B);
10518
10519             elsif Is_Protected_Type (Ttyp) then
10520                D := First_Discriminant (Ttyp);
10521                while Chars (D) /= Chars (Entity (Bound)) loop
10522                   Next_Discriminant (D);
10523                end loop;
10524
10525                B := New_Reference_To  (Discriminal (D), Loc);
10526
10527             else
10528                B := New_Reference_To (Discriminal (Entity (Bound)), Loc);
10529             end if;
10530
10531          elsif Nkind (Bound) = N_Attribute_Reference then
10532             return Bound;
10533
10534          else
10535             B := New_Copy_Tree (Bound);
10536          end if;
10537
10538          return
10539            Make_Attribute_Reference (Loc,
10540              Attribute_Name => Name_Pos,
10541              Prefix => New_Occurrence_Of (Etype (Bound), Loc),
10542              Expressions    => New_List (B));
10543       end Convert_Discriminant_Ref;
10544
10545    --  Start of processing for Family_Offset
10546
10547    begin
10548       Real_Hi := Convert_Discriminant_Ref (Hi);
10549       Real_Lo := Convert_Discriminant_Ref (Lo);
10550
10551       if Cap then
10552          if Is_Task_Type (Ttyp) then
10553             Ityp := RTE (RE_Task_Entry_Index);
10554          else
10555             Ityp := RTE (RE_Protected_Entry_Index);
10556          end if;
10557
10558          Real_Hi :=
10559            Make_Attribute_Reference (Loc,
10560              Prefix         => New_Reference_To (Ityp, Loc),
10561              Attribute_Name => Name_Min,
10562              Expressions    => New_List (
10563                Real_Hi,
10564                Make_Integer_Literal (Loc, Entry_Family_Bound - 1)));
10565
10566          Real_Lo :=
10567            Make_Attribute_Reference (Loc,
10568              Prefix         => New_Reference_To (Ityp, Loc),
10569              Attribute_Name => Name_Max,
10570              Expressions    => New_List (
10571                Real_Lo,
10572                Make_Integer_Literal (Loc, -Entry_Family_Bound)));
10573       end if;
10574
10575       return Make_Op_Subtract (Loc, Real_Hi, Real_Lo);
10576    end Family_Offset;
10577
10578    -----------------
10579    -- Family_Size --
10580    -----------------
10581
10582    function Family_Size
10583      (Loc  : Source_Ptr;
10584       Hi   : Node_Id;
10585       Lo   : Node_Id;
10586       Ttyp : Entity_Id;
10587       Cap  : Boolean) return Node_Id
10588    is
10589       Ityp : Entity_Id;
10590
10591    begin
10592       if Is_Task_Type (Ttyp) then
10593          Ityp := RTE (RE_Task_Entry_Index);
10594       else
10595          Ityp := RTE (RE_Protected_Entry_Index);
10596       end if;
10597
10598       return
10599         Make_Attribute_Reference (Loc,
10600           Prefix         => New_Reference_To (Ityp, Loc),
10601           Attribute_Name => Name_Max,
10602           Expressions    => New_List (
10603             Make_Op_Add (Loc,
10604               Left_Opnd  =>
10605                 Family_Offset (Loc, Hi, Lo, Ttyp, Cap),
10606               Right_Opnd =>
10607                 Make_Integer_Literal (Loc, 1)),
10608             Make_Integer_Literal (Loc, 0)));
10609    end Family_Size;
10610
10611    -----------------------------------
10612    -- Find_Task_Or_Protected_Pragma --
10613    -----------------------------------
10614
10615    function Find_Task_Or_Protected_Pragma
10616      (T : Node_Id;
10617       P : Name_Id) return Node_Id
10618    is
10619       N : Node_Id;
10620
10621    begin
10622       N := First (Visible_Declarations (T));
10623       while Present (N) loop
10624          if Nkind (N) = N_Pragma then
10625             if Pragma_Name (N) = P then
10626                return N;
10627
10628             elsif P = Name_Priority
10629               and then Pragma_Name (N) = Name_Interrupt_Priority
10630             then
10631                return N;
10632
10633             else
10634                Next (N);
10635             end if;
10636
10637          else
10638             Next (N);
10639          end if;
10640       end loop;
10641
10642       N := First (Private_Declarations (T));
10643       while Present (N) loop
10644          if Nkind (N) = N_Pragma then
10645             if Pragma_Name (N) = P then
10646                return N;
10647
10648             elsif P = Name_Priority
10649               and then Pragma_Name (N) = Name_Interrupt_Priority
10650             then
10651                return N;
10652
10653             else
10654                Next (N);
10655             end if;
10656
10657          else
10658             Next (N);
10659          end if;
10660       end loop;
10661
10662       raise Program_Error;
10663    end Find_Task_Or_Protected_Pragma;
10664
10665    -------------------------------
10666    -- First_Protected_Operation --
10667    -------------------------------
10668
10669    function First_Protected_Operation (D : List_Id) return Node_Id is
10670       First_Op : Node_Id;
10671
10672    begin
10673       First_Op := First (D);
10674       while Present (First_Op)
10675         and then not Nkind_In (First_Op, N_Subprogram_Body, N_Entry_Body)
10676       loop
10677          Next (First_Op);
10678       end loop;
10679
10680       return First_Op;
10681    end First_Protected_Operation;
10682
10683    ---------------------------------------
10684    -- Install_Private_Data_Declarations --
10685    ---------------------------------------
10686
10687    procedure Install_Private_Data_Declarations
10688      (Loc      : Source_Ptr;
10689       Spec_Id  : Entity_Id;
10690       Conc_Typ : Entity_Id;
10691       Body_Nod : Node_Id;
10692       Decls    : List_Id;
10693       Barrier  : Boolean := False;
10694       Family   : Boolean := False)
10695    is
10696       Is_Protected : constant Boolean := Is_Protected_Type (Conc_Typ);
10697       Decl         : Node_Id;
10698       Def          : Node_Id;
10699       Insert_Node  : Node_Id := Empty;
10700       Obj_Ent      : Entity_Id;
10701
10702       procedure Add (Decl : Node_Id);
10703       --  Add a single declaration after Insert_Node. If this is the first
10704       --  addition, Decl is added to the front of Decls and it becomes the
10705       --  insertion node.
10706
10707       function Replace_Bound (Bound : Node_Id) return Node_Id;
10708       --  The bounds of an entry index may depend on discriminants, create a
10709       --  reference to the corresponding prival. Otherwise return a duplicate
10710       --  of the original bound.
10711
10712       ---------
10713       -- Add --
10714       ---------
10715
10716       procedure Add (Decl : Node_Id) is
10717       begin
10718          if No (Insert_Node) then
10719             Prepend_To (Decls, Decl);
10720          else
10721             Insert_After (Insert_Node, Decl);
10722          end if;
10723
10724          Insert_Node := Decl;
10725       end Add;
10726
10727       --------------------------
10728       -- Replace_Discriminant --
10729       --------------------------
10730
10731       function Replace_Bound (Bound : Node_Id) return Node_Id is
10732       begin
10733          if Nkind (Bound) = N_Identifier
10734            and then Is_Discriminal (Entity (Bound))
10735          then
10736             return Make_Identifier (Loc, Chars (Entity (Bound)));
10737          else
10738             return Duplicate_Subexpr (Bound);
10739          end if;
10740       end Replace_Bound;
10741
10742    --  Start of processing for Install_Private_Data_Declarations
10743
10744    begin
10745       --  Step 1: Retrieve the concurrent object entity. Obj_Ent can denote
10746       --  formal parameter _O, _object or _task depending on the context.
10747
10748       Obj_Ent := Concurrent_Object (Spec_Id, Conc_Typ);
10749
10750       --  Special processing of _O for barrier functions, protected entries
10751       --  and families.
10752
10753       if Barrier
10754         or else
10755           (Is_Protected
10756              and then
10757                (Ekind (Spec_Id) = E_Entry
10758                   or else Ekind (Spec_Id) = E_Entry_Family))
10759       then
10760          declare
10761             Conc_Rec : constant Entity_Id :=
10762                          Corresponding_Record_Type (Conc_Typ);
10763             Typ_Id   : constant Entity_Id :=
10764                          Make_Defining_Identifier (Loc,
10765                            New_External_Name (Chars (Conc_Rec), 'P'));
10766          begin
10767             --  Generate:
10768             --    type prot_typVP is access prot_typV;
10769
10770             Decl :=
10771               Make_Full_Type_Declaration (Loc,
10772                 Defining_Identifier => Typ_Id,
10773                 Type_Definition     =>
10774                   Make_Access_To_Object_Definition (Loc,
10775                     Subtype_Indication =>
10776                       New_Reference_To (Conc_Rec, Loc)));
10777             Add (Decl);
10778
10779             --  Generate:
10780             --    _object : prot_typVP := prot_typV (_O);
10781
10782             Decl :=
10783               Make_Object_Declaration (Loc,
10784                 Defining_Identifier =>
10785                   Make_Defining_Identifier (Loc, Name_uObject),
10786                 Object_Definition   => New_Reference_To (Typ_Id, Loc),
10787                 Expression          =>
10788                   Unchecked_Convert_To (Typ_Id,
10789                     New_Reference_To (Obj_Ent, Loc)));
10790             Add (Decl);
10791
10792             --  Set the reference to the concurrent object
10793
10794             Obj_Ent := Defining_Identifier (Decl);
10795          end;
10796       end if;
10797
10798       --  Step 2: Create the Protection object and build its declaration for
10799       --  any protected entry (family) of subprogram.
10800
10801       if Is_Protected then
10802          declare
10803             Prot_Ent : constant Entity_Id :=
10804                          Make_Defining_Identifier (Loc,
10805                            New_Internal_Name ('R'));
10806             Prot_Typ : RE_Id;
10807
10808          begin
10809             Set_Protection_Object (Spec_Id, Prot_Ent);
10810
10811             --  Determine the proper protection type
10812
10813             if Has_Attach_Handler (Conc_Typ)
10814               and then not Restricted_Profile
10815             then
10816                Prot_Typ := RE_Static_Interrupt_Protection;
10817
10818             elsif Has_Interrupt_Handler (Conc_Typ) then
10819                Prot_Typ := RE_Dynamic_Interrupt_Protection;
10820
10821             --  The type has explicit entries or generated primitive entry
10822             --  wrappers.
10823
10824             elsif Has_Entries (Conc_Typ)
10825               or else
10826                 (Ada_Version >= Ada_05
10827                    and then Present (Interface_List (Parent (Conc_Typ))))
10828             then
10829                case Corresponding_Runtime_Package (Conc_Typ) is
10830                   when System_Tasking_Protected_Objects_Entries =>
10831                      Prot_Typ := RE_Protection_Entries;
10832
10833                   when System_Tasking_Protected_Objects_Single_Entry =>
10834                      Prot_Typ := RE_Protection_Entry;
10835
10836                   when others =>
10837                      raise Program_Error;
10838                end case;
10839
10840             else
10841                Prot_Typ := RE_Protection;
10842             end if;
10843
10844             --  Generate:
10845             --    conc_typR : protection_typ renames _object._object;
10846
10847             Decl :=
10848               Make_Object_Renaming_Declaration (Loc,
10849                 Defining_Identifier => Prot_Ent,
10850                 Subtype_Mark =>
10851                   New_Reference_To (RTE (Prot_Typ), Loc),
10852                 Name =>
10853                   Make_Selected_Component (Loc,
10854                     Prefix =>
10855                       New_Reference_To (Obj_Ent, Loc),
10856                     Selector_Name =>
10857                       Make_Identifier (Loc, Name_uObject)));
10858             Add (Decl);
10859          end;
10860       end if;
10861
10862       --  Step 3: Add discriminant renamings (if any)
10863
10864       if Has_Discriminants (Conc_Typ) then
10865          declare
10866             D : Entity_Id;
10867
10868          begin
10869             D := First_Discriminant (Conc_Typ);
10870             while Present (D) loop
10871
10872                --  Adjust the source location
10873
10874                Set_Sloc (Discriminal (D), Loc);
10875
10876                --  Generate:
10877                --    discr_name : discr_typ renames _object.discr_name;
10878                --      or
10879                --    discr_name : discr_typ renames _task.discr_name;
10880
10881                Decl :=
10882                  Make_Object_Renaming_Declaration (Loc,
10883                    Defining_Identifier => Discriminal (D),
10884                    Subtype_Mark        => New_Reference_To (Etype (D), Loc),
10885                    Name                =>
10886                      Make_Selected_Component (Loc,
10887                        Prefix        => New_Reference_To (Obj_Ent, Loc),
10888                        Selector_Name => Make_Identifier (Loc, Chars (D))));
10889                Add (Decl);
10890
10891                Next_Discriminant (D);
10892             end loop;
10893          end;
10894       end if;
10895
10896       --  Step 4: Add private component renamings (if any)
10897
10898       if Is_Protected then
10899          Def := Protected_Definition (Parent (Conc_Typ));
10900
10901          if Present (Private_Declarations (Def)) then
10902             declare
10903                Comp    : Node_Id;
10904                Comp_Id : Entity_Id;
10905                Decl_Id : Entity_Id;
10906
10907             begin
10908                Comp := First (Private_Declarations (Def));
10909                while Present (Comp) loop
10910                   if Nkind (Comp) = N_Component_Declaration then
10911                      Comp_Id := Defining_Identifier (Comp);
10912                      Decl_Id :=
10913                        Make_Defining_Identifier (Loc, Chars (Comp_Id));
10914
10915                      --  Minimal decoration
10916
10917                      if Ekind (Spec_Id) = E_Function then
10918                         Set_Ekind (Decl_Id, E_Constant);
10919                      else
10920                         Set_Ekind (Decl_Id, E_Variable);
10921                      end if;
10922
10923                      Set_Prival      (Comp_Id, Decl_Id);
10924                      Set_Prival_Link (Decl_Id, Comp_Id);
10925                      Set_Is_Aliased  (Decl_Id, Is_Aliased (Comp_Id));
10926
10927                      --  Generate:
10928                      --    comp_name : comp_typ renames _object.comp_name;
10929
10930                      Decl :=
10931                        Make_Object_Renaming_Declaration (Loc,
10932                          Defining_Identifier => Decl_Id,
10933                          Subtype_Mark =>
10934                            New_Reference_To (Etype (Comp_Id), Loc),
10935                          Name =>
10936                            Make_Selected_Component (Loc,
10937                              Prefix =>
10938                                New_Reference_To (Obj_Ent, Loc),
10939                              Selector_Name =>
10940                                Make_Identifier (Loc, Chars (Comp_Id))));
10941                      Add (Decl);
10942                   end if;
10943
10944                   Next (Comp);
10945                end loop;
10946             end;
10947          end if;
10948       end if;
10949
10950       --  Step 5: Add the declaration of the entry index and the associated
10951       --  type for barrier functions and entry families.
10952
10953       if (Barrier and then Family)
10954         or else Ekind (Spec_Id) = E_Entry_Family
10955       then
10956          declare
10957             E         : constant Entity_Id := Index_Object (Spec_Id);
10958             Index     : constant Entity_Id :=
10959                           Defining_Identifier (
10960                             Entry_Index_Specification (
10961                               Entry_Body_Formal_Part (Body_Nod)));
10962             Index_Con : constant Entity_Id :=
10963                           Make_Defining_Identifier (Loc, Chars (Index));
10964             High      : Node_Id;
10965             Index_Typ : Entity_Id;
10966             Low       : Node_Id;
10967
10968          begin
10969             --  Minimal decoration
10970
10971             Set_Ekind                (Index_Con, E_Constant);
10972             Set_Entry_Index_Constant (Index, Index_Con);
10973             Set_Discriminal_Link     (Index_Con, Index);
10974
10975             --  Retrieve the bounds of the entry family
10976
10977             High := Type_High_Bound (Etype (Index));
10978             Low  := Type_Low_Bound  (Etype (Index));
10979
10980             --  In the simple case the entry family is given by a subtype
10981             --  mark and the index constant has the same type.
10982
10983             if Is_Entity_Name (Original_Node (
10984                  Discrete_Subtype_Definition (Parent (Index))))
10985             then
10986                Index_Typ := Etype (Index);
10987
10988             --  Otherwise a new subtype declaration is required
10989
10990             else
10991                High := Replace_Bound (High);
10992                Low  := Replace_Bound (Low);
10993
10994                Index_Typ :=
10995                  Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
10996
10997                --  Generate:
10998                --    subtype Jnn is <Etype of Index> range Low .. High;
10999
11000                Decl :=
11001                  Make_Subtype_Declaration (Loc,
11002                    Defining_Identifier => Index_Typ,
11003                    Subtype_Indication =>
11004                      Make_Subtype_Indication (Loc,
11005                        Subtype_Mark =>
11006                          New_Reference_To (Base_Type (Etype (Index)), Loc),
11007                        Constraint =>
11008                          Make_Range_Constraint (Loc,
11009                            Range_Expression =>
11010                              Make_Range (Loc, Low, High))));
11011                Add (Decl);
11012             end if;
11013
11014             Set_Etype (Index_Con, Index_Typ);
11015
11016             --  Create the object which designates the index:
11017             --    J : constant Jnn :=
11018             --          Jnn'Val (_E - <index expr> + Jnn'Pos (Jnn'First));
11019             --
11020             --  where Jnn is the subtype created above or the original type of
11021             --  the index, _E is a formal of the protected body subprogram and
11022             --  <index expr> is the index of the first family member.
11023
11024             Decl :=
11025               Make_Object_Declaration (Loc,
11026                 Defining_Identifier => Index_Con,
11027                 Constant_Present => True,
11028                 Object_Definition =>
11029                   New_Reference_To (Index_Typ, Loc),
11030
11031                 Expression =>
11032                   Make_Attribute_Reference (Loc,
11033                     Prefix =>
11034                       New_Reference_To (Index_Typ, Loc),
11035                     Attribute_Name => Name_Val,
11036
11037                     Expressions => New_List (
11038
11039                       Make_Op_Add (Loc,
11040                         Left_Opnd =>
11041                           Make_Op_Subtract (Loc,
11042                             Left_Opnd =>
11043                               New_Reference_To (E, Loc),
11044                             Right_Opnd =>
11045                               Entry_Index_Expression (Loc,
11046                                 Defining_Identifier (Body_Nod),
11047                                 Empty, Conc_Typ)),
11048
11049                         Right_Opnd =>
11050                           Make_Attribute_Reference (Loc,
11051                             Prefix =>
11052                               New_Reference_To (Index_Typ, Loc),
11053                             Attribute_Name => Name_Pos,
11054                             Expressions => New_List (
11055                               Make_Attribute_Reference (Loc,
11056                                 Prefix =>
11057                                   New_Reference_To (Index_Typ, Loc),
11058                                 Attribute_Name => Name_First)))))));
11059             Add (Decl);
11060          end;
11061       end if;
11062    end Install_Private_Data_Declarations;
11063
11064    ---------------------------------
11065    -- Is_Potentially_Large_Family --
11066    ---------------------------------
11067
11068    function Is_Potentially_Large_Family
11069      (Base_Index : Entity_Id;
11070       Conctyp    : Entity_Id;
11071       Lo         : Node_Id;
11072       Hi         : Node_Id) return Boolean
11073    is
11074    begin
11075       return Scope (Base_Index) = Standard_Standard
11076         and then Base_Index = Base_Type (Standard_Integer)
11077         and then Has_Discriminants (Conctyp)
11078         and then Present
11079           (Discriminant_Default_Value (First_Discriminant (Conctyp)))
11080         and then
11081           (Denotes_Discriminant (Lo, True)
11082             or else Denotes_Discriminant (Hi, True));
11083    end Is_Potentially_Large_Family;
11084
11085    ------------------
11086    -- Index_Object --
11087    ------------------
11088
11089    function Index_Object (Spec_Id : Entity_Id) return Entity_Id is
11090       Bod_Subp : constant Entity_Id := Protected_Body_Subprogram (Spec_Id);
11091       Formal   : Entity_Id;
11092
11093    begin
11094       Formal := First_Formal (Bod_Subp);
11095       while Present (Formal) loop
11096
11097          --  Look for formal parameter _E
11098
11099          if Chars (Formal) = Name_uE then
11100             return Formal;
11101          end if;
11102
11103          Next_Formal (Formal);
11104       end loop;
11105
11106       --  A protected body subprogram should always have the parameter in
11107       --  question.
11108
11109       raise Program_Error;
11110    end Index_Object;
11111
11112    --------------------------------
11113    -- Make_Initialize_Protection --
11114    --------------------------------
11115
11116    function Make_Initialize_Protection
11117      (Protect_Rec : Entity_Id) return List_Id
11118    is
11119       Loc         : constant Source_Ptr := Sloc (Protect_Rec);
11120       P_Arr       : Entity_Id;
11121       Pdef        : Node_Id;
11122       Pdec        : Node_Id;
11123       Ptyp        : constant Node_Id :=
11124                       Corresponding_Concurrent_Type (Protect_Rec);
11125       Args        : List_Id;
11126       L           : constant List_Id := New_List;
11127       Has_Entry   : constant Boolean := Has_Entries (Ptyp);
11128       Restricted  : constant Boolean := Restricted_Profile;
11129
11130    begin
11131       --  We may need two calls to properly initialize the object, one to
11132       --  Initialize_Protection, and possibly one to Install_Handlers if we
11133       --  have a pragma Attach_Handler.
11134
11135       --  Get protected declaration. In the case of a task type declaration,
11136       --  this is simply the parent of the protected type entity. In the single
11137       --  protected object declaration, this parent will be the implicit type,
11138       --  and we can find the corresponding single protected object declaration
11139       --  by searching forward in the declaration list in the tree.
11140
11141       --  Is the test for N_Single_Protected_Declaration needed here??? Nodes
11142       --  of this type should have been removed during semantic analysis.
11143
11144       Pdec := Parent (Ptyp);
11145       while not Nkind_In (Pdec, N_Protected_Type_Declaration,
11146                                 N_Single_Protected_Declaration)
11147       loop
11148          Next (Pdec);
11149       end loop;
11150
11151       --  Now we can find the object definition from this declaration
11152
11153       Pdef := Protected_Definition (Pdec);
11154
11155       --  Build the parameter list for the call. Note that _Init is the name
11156       --  of the formal for the object to be initialized, which is the task
11157       --  value record itself.
11158
11159       Args := New_List;
11160
11161       --  Object parameter. This is a pointer to the object of type
11162       --  Protection used by the GNARL to control the protected object.
11163
11164       Append_To (Args,
11165         Make_Attribute_Reference (Loc,
11166           Prefix =>
11167             Make_Selected_Component (Loc,
11168               Prefix => Make_Identifier (Loc, Name_uInit),
11169               Selector_Name => Make_Identifier (Loc, Name_uObject)),
11170           Attribute_Name => Name_Unchecked_Access));
11171
11172       --  Priority parameter. Set to Unspecified_Priority unless there is a
11173       --  priority pragma, in which case we take the value from the pragma,
11174       --  or there is an interrupt pragma and no priority pragma, and we
11175       --  set the ceiling to Interrupt_Priority'Last, an implementation-
11176       --  defined value, see D.3(10).
11177
11178       if Present (Pdef)
11179         and then Has_Priority_Pragma (Pdef)
11180       then
11181          declare
11182             Prio : constant Node_Id :=
11183                      Expression
11184                        (First
11185                           (Pragma_Argument_Associations
11186                              (Find_Task_Or_Protected_Pragma
11187                                 (Pdef, Name_Priority))));
11188             Temp : Entity_Id;
11189
11190          begin
11191             --  If priority is a static expression, then we can duplicate it
11192             --  with no problem and simply append it to the argument list.
11193
11194             if Is_Static_Expression (Prio) then
11195                Append_To (Args,
11196                           Duplicate_Subexpr_No_Checks (Prio));
11197
11198             --  Otherwise, the priority may be a per-object expression, if it
11199             --  depends on a discriminant of the type. In this case, create
11200             --  local variable to capture the expression. Note that it is
11201             --  really necessary to create this variable explicitly. It might
11202             --  be thought that removing side effects would the appropriate
11203             --  approach, but that could generate declarations improperly
11204             --  placed in the enclosing scope.
11205
11206             --  Note: Use System.Any_Priority as the expected type for the
11207             --  non-static priority expression, in case the expression has not
11208             --  been analyzed yet (as occurs for example with pragma
11209             --  Interrupt_Priority).
11210
11211             else
11212                Temp :=
11213                  Make_Defining_Identifier (Loc, New_Internal_Name ('R'));
11214
11215                Append_To (L,
11216                   Make_Object_Declaration (Loc,
11217                      Defining_Identifier => Temp,
11218                      Object_Definition   =>
11219                        New_Occurrence_Of (RTE (RE_Any_Priority), Loc),
11220                      Expression          => Relocate_Node (Prio)));
11221
11222                   Append_To (Args, New_Occurrence_Of (Temp, Loc));
11223             end if;
11224          end;
11225
11226       --  When no priority is specified but an xx_Handler pragma is, we default
11227       --  to System.Interrupts.Default_Interrupt_Priority, see D.3(10).
11228
11229       elsif Has_Interrupt_Handler (Ptyp)
11230         or else Has_Attach_Handler (Ptyp)
11231       then
11232          Append_To (Args,
11233            New_Reference_To (RTE (RE_Default_Interrupt_Priority), Loc));
11234
11235       --  Normal case, no priority or xx_Handler specified, default priority
11236
11237       else
11238          Append_To (Args,
11239            New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
11240       end if;
11241
11242       --  Test for Compiler_Info parameter. This parameter allows entry body
11243       --  procedures and barrier functions to be called from the runtime. It
11244       --  is a pointer to the record generated by the compiler to represent
11245       --  the protected object.
11246
11247       if Has_Entry
11248         or else Has_Interrupt_Handler (Ptyp)
11249         or else Has_Attach_Handler (Ptyp)
11250         or else Has_Abstract_Interfaces (Protect_Rec)
11251       then
11252          declare
11253             Pkg_Id : constant RTU_Id := Corresponding_Runtime_Package (Ptyp);
11254
11255             Called_Subp : RE_Id;
11256
11257          begin
11258             case Pkg_Id is
11259                when System_Tasking_Protected_Objects_Entries =>
11260                   Called_Subp := RE_Initialize_Protection_Entries;
11261
11262                when System_Tasking_Protected_Objects =>
11263                   Called_Subp := RE_Initialize_Protection;
11264
11265                when System_Tasking_Protected_Objects_Single_Entry =>
11266                   Called_Subp := RE_Initialize_Protection_Entry;
11267
11268                when others =>
11269                   raise Program_Error;
11270             end case;
11271
11272             if Has_Entry or else not Restricted then
11273                Append_To (Args,
11274                  Make_Attribute_Reference (Loc,
11275                    Prefix => Make_Identifier (Loc, Name_uInit),
11276                    Attribute_Name => Name_Address));
11277             end if;
11278
11279             --  Entry_Bodies parameter. This is a pointer to an array of
11280             --  pointers to the entry body procedures and barrier functions of
11281             --  the object. If the protected type has no entries this object
11282             --  will not exist, in this case, pass a null.
11283
11284             if Has_Entry then
11285                P_Arr := Entry_Bodies_Array (Ptyp);
11286
11287                Append_To (Args,
11288                  Make_Attribute_Reference (Loc,
11289                    Prefix => New_Reference_To (P_Arr, Loc),
11290                    Attribute_Name => Name_Unrestricted_Access));
11291
11292                if Pkg_Id = System_Tasking_Protected_Objects_Entries then
11293
11294                   --  Find index mapping function (clumsy but ok for now)
11295
11296                   while Ekind (P_Arr) /= E_Function loop
11297                      Next_Entity (P_Arr);
11298                   end loop;
11299
11300                   Append_To (Args,
11301                     Make_Attribute_Reference (Loc,
11302                       Prefix =>
11303                         New_Reference_To (P_Arr, Loc),
11304                       Attribute_Name => Name_Unrestricted_Access));
11305                end if;
11306
11307             elsif Pkg_Id = System_Tasking_Protected_Objects_Single_Entry then
11308                Append_To (Args, Make_Null (Loc));
11309
11310             elsif Pkg_Id = System_Tasking_Protected_Objects_Entries then
11311                Append_To (Args, Make_Null (Loc));
11312                Append_To (Args, Make_Null (Loc));
11313             end if;
11314
11315             Append_To (L,
11316               Make_Procedure_Call_Statement (Loc,
11317                 Name => New_Reference_To (RTE (Called_Subp), Loc),
11318                 Parameter_Associations => Args));
11319          end;
11320       else
11321          Append_To (L,
11322            Make_Procedure_Call_Statement (Loc,
11323              Name => New_Reference_To (RTE (RE_Initialize_Protection), Loc),
11324              Parameter_Associations => Args));
11325       end if;
11326
11327       if Has_Attach_Handler (Ptyp) then
11328
11329          --  We have a list of N Attach_Handler (ProcI, ExprI), and we have to
11330          --  make the following call:
11331
11332          --  Install_Handlers (_object,
11333          --    ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
11334
11335          --  or, in the case of Ravenscar:
11336
11337          --  Install_Restricted_Handlers
11338          --    ((Expr1, Proc1'access), ...., (ExprN, ProcN'access));
11339
11340          declare
11341             Args  : constant List_Id := New_List;
11342             Table : constant List_Id := New_List;
11343             Ritem : Node_Id          := First_Rep_Item (Ptyp);
11344
11345          begin
11346             --  Build the Attach_Handler table argument
11347
11348             while Present (Ritem) loop
11349                if Nkind (Ritem) = N_Pragma
11350                  and then Pragma_Name (Ritem) = Name_Attach_Handler
11351                then
11352                   declare
11353                      Handler : constant Node_Id :=
11354                                  First (Pragma_Argument_Associations (Ritem));
11355
11356                      Interrupt : constant Node_Id := Next (Handler);
11357                      Expr      : constant Node_Id := Expression (Interrupt);
11358
11359                   begin
11360                      Append_To (Table,
11361                        Make_Aggregate (Loc, Expressions => New_List (
11362                          Unchecked_Convert_To
11363                           (RTE (RE_System_Interrupt_Id), Expr),
11364                          Make_Attribute_Reference (Loc,
11365                            Prefix => Make_Selected_Component (Loc,
11366                               Make_Identifier (Loc, Name_uInit),
11367                               Duplicate_Subexpr_No_Checks
11368                                 (Expression (Handler))),
11369                            Attribute_Name => Name_Access))));
11370                   end;
11371                end if;
11372
11373                Next_Rep_Item (Ritem);
11374             end loop;
11375
11376             --  Append the table argument we just built
11377
11378             Append_To (Args, Make_Aggregate (Loc, Table));
11379
11380             --  Append the Install_Handlers (or Install_Restricted_Handlers)
11381             --  call to the statements.
11382
11383             if Restricted then
11384                --  Call a simplified version of Install_Handlers to be used
11385                --  when the Ravenscar restrictions are in effect
11386                --  (Install_Restricted_Handlers).
11387
11388                Append_To (L,
11389                  Make_Procedure_Call_Statement (Loc,
11390                    Name =>
11391                      New_Reference_To
11392                         (RTE (RE_Install_Restricted_Handlers), Loc),
11393                    Parameter_Associations => Args));
11394
11395             else
11396                --  First, prepends the _object argument
11397
11398                Prepend_To (Args,
11399                  Make_Attribute_Reference (Loc,
11400                    Prefix =>
11401                      Make_Selected_Component (Loc,
11402                        Prefix => Make_Identifier (Loc, Name_uInit),
11403                        Selector_Name => Make_Identifier (Loc, Name_uObject)),
11404                    Attribute_Name => Name_Unchecked_Access));
11405
11406                --  Then, insert call to Install_Handlers
11407
11408                Append_To (L,
11409                  Make_Procedure_Call_Statement (Loc,
11410                    Name => New_Reference_To (RTE (RE_Install_Handlers), Loc),
11411                    Parameter_Associations => Args));
11412             end if;
11413          end;
11414       end if;
11415
11416       return L;
11417    end Make_Initialize_Protection;
11418
11419    ---------------------------
11420    -- Make_Task_Create_Call --
11421    ---------------------------
11422
11423    function Make_Task_Create_Call (Task_Rec : Entity_Id) return Node_Id is
11424       Loc    : constant Source_Ptr := Sloc (Task_Rec);
11425       Name   : Node_Id;
11426       Tdef   : Node_Id;
11427       Tdec   : Node_Id;
11428       Ttyp   : Node_Id;
11429       Tnam   : Name_Id;
11430       Args   : List_Id;
11431       Ecount : Node_Id;
11432
11433    begin
11434       Ttyp := Corresponding_Concurrent_Type (Task_Rec);
11435       Tnam := Chars (Ttyp);
11436
11437       --  Get task declaration. In the case of a task type declaration, this is
11438       --  simply the parent of the task type entity. In the single task
11439       --  declaration, this parent will be the implicit type, and we can find
11440       --  the corresponding single task declaration by searching forward in the
11441       --  declaration list in the tree.
11442
11443       --  Is the test for N_Single_Task_Declaration needed here??? Nodes of
11444       --  this type should have been removed during semantic analysis.
11445
11446       Tdec := Parent (Ttyp);
11447       while not Nkind_In (Tdec, N_Task_Type_Declaration,
11448                                 N_Single_Task_Declaration)
11449       loop
11450          Next (Tdec);
11451       end loop;
11452
11453       --  Now we can find the task definition from this declaration
11454
11455       Tdef := Task_Definition (Tdec);
11456
11457       --  Build the parameter list for the call. Note that _Init is the name
11458       --  of the formal for the object to be initialized, which is the task
11459       --  value record itself.
11460
11461       Args := New_List;
11462
11463       --  Priority parameter. Set to Unspecified_Priority unless there is a
11464       --  priority pragma, in which case we take the value from the pragma.
11465
11466       if Present (Tdef) and then Has_Priority_Pragma (Tdef) then
11467          Append_To (Args,
11468            Make_Selected_Component (Loc,
11469              Prefix => Make_Identifier (Loc, Name_uInit),
11470              Selector_Name => Make_Identifier (Loc, Name_uPriority)));
11471       else
11472          Append_To (Args,
11473            New_Reference_To (RTE (RE_Unspecified_Priority), Loc));
11474       end if;
11475
11476       --  Optional Stack parameter
11477
11478       if Restricted_Profile then
11479
11480          --  If the stack has been preallocated by the expander then
11481          --  pass its address. Otherwise, pass a null address.
11482
11483          if Preallocated_Stacks_On_Target then
11484             Append_To (Args,
11485               Make_Attribute_Reference (Loc,
11486                 Prefix         => Make_Selected_Component (Loc,
11487                   Prefix        => Make_Identifier (Loc, Name_uInit),
11488                   Selector_Name =>
11489                     Make_Identifier (Loc, Name_uStack)),
11490                 Attribute_Name => Name_Address));
11491
11492          else
11493             Append_To (Args,
11494               New_Reference_To (RTE (RE_Null_Address), Loc));
11495          end if;
11496       end if;
11497
11498       --  Size parameter. If no Storage_Size pragma is present, then
11499       --  the size is taken from the taskZ variable for the type, which
11500       --  is either Unspecified_Size, or has been reset by the use of
11501       --  a Storage_Size attribute definition clause. If a pragma is
11502       --  present, then the size is taken from the _Size field of the
11503       --  task value record, which was set from the pragma value.
11504
11505       if Present (Tdef)
11506         and then Has_Storage_Size_Pragma (Tdef)
11507       then
11508          Append_To (Args,
11509            Make_Selected_Component (Loc,
11510              Prefix => Make_Identifier (Loc, Name_uInit),
11511              Selector_Name => Make_Identifier (Loc, Name_uSize)));
11512
11513       else
11514          Append_To (Args,
11515            New_Reference_To (Storage_Size_Variable (Ttyp), Loc));
11516       end if;
11517
11518       --  Task_Info parameter. Set to Unspecified_Task_Info unless there is a
11519       --  Task_Info pragma, in which case we take the value from the pragma.
11520
11521       if Present (Tdef)
11522         and then Has_Task_Info_Pragma (Tdef)
11523       then
11524          Append_To (Args,
11525            Make_Selected_Component (Loc,
11526              Prefix => Make_Identifier (Loc, Name_uInit),
11527              Selector_Name => Make_Identifier (Loc, Name_uTask_Info)));
11528
11529       else
11530          Append_To (Args,
11531            New_Reference_To (RTE (RE_Unspecified_Task_Info), Loc));
11532       end if;
11533
11534       if not Restricted_Profile then
11535
11536          --  Deadline parameter. If no Relative_Deadline pragma is present,
11537          --  then the deadline is Time_Span_Zero. If a pragma is present, then
11538          --  the deadline is taken from the _Relative_Deadline field of the
11539          --  task value record, which was set from the pragma value. Note that
11540          --  this parameter must not be generated for the restricted profiles
11541          --  since Ravenscar does not allow deadlines.
11542
11543          --  Case where pragma Relative_Deadline applies: use given value
11544
11545          if Present (Tdef) and then Has_Relative_Deadline_Pragma (Tdef) then
11546             Append_To (Args,
11547               Make_Selected_Component (Loc,
11548                 Prefix => Make_Identifier (Loc, Name_uInit),
11549                 Selector_Name =>
11550                   Make_Identifier (Loc, Name_uRelative_Deadline)));
11551
11552          --  No pragma Relative_Deadline apply to the task
11553
11554          else
11555             Append_To (Args,
11556               New_Reference_To (RTE (RE_Time_Span_Zero), Loc));
11557          end if;
11558
11559          --  Number of entries. This is an expression of the form:
11560
11561          --    n + _Init.a'Length + _Init.a'B'Length + ...
11562
11563          --  where a,b... are the entry family names for the task definition
11564
11565          Ecount :=
11566            Build_Entry_Count_Expression
11567              (Ttyp,
11568               Component_Items
11569                 (Component_List
11570                    (Type_Definition
11571                       (Parent (Corresponding_Record_Type (Ttyp))))),
11572               Loc);
11573          Append_To (Args, Ecount);
11574
11575          --  Master parameter. This is a reference to the _Master parameter of
11576          --  the initialization procedure, except in the case of the pragma
11577          --  Restrictions (No_Task_Hierarchy) where the value is fixed to 3.
11578          --  See comments in System.Tasking.Initialization.Init_RTS for the
11579          --  value 3.
11580
11581          if Restriction_Active (No_Task_Hierarchy) = False then
11582             Append_To (Args, Make_Identifier (Loc, Name_uMaster));
11583          else
11584             Append_To (Args, Make_Integer_Literal (Loc, 3));
11585          end if;
11586       end if;
11587
11588       --  State parameter. This is a pointer to the task body procedure. The
11589       --  required value is obtained by taking 'Unrestricted_Access of the task
11590       --  body procedure and converting it (with an unchecked conversion) to
11591       --  the type required by the task kernel. For further details, see the
11592       --  description of Expand_N_Task_Body. We use 'Unrestricted_Access rather
11593       --  than 'Address in order to avoid creating trampolines.
11594
11595       declare
11596          Body_Proc    : constant Node_Id := Get_Task_Body_Procedure (Ttyp);
11597          Subp_Ptr_Typ : constant Node_Id :=
11598                           Create_Itype (E_Access_Subprogram_Type, Tdec);
11599          Ref          : constant Node_Id := Make_Itype_Reference (Loc);
11600
11601       begin
11602          Set_Directly_Designated_Type (Subp_Ptr_Typ, Body_Proc);
11603          Set_Etype (Subp_Ptr_Typ, Subp_Ptr_Typ);
11604
11605          --  Be sure to freeze a reference to the access-to-subprogram type,
11606          --  otherwise gigi will complain that it's in the wrong scope, because
11607          --  it's actually inside the init procedure for the record type that
11608          --  corresponds to the task type.
11609
11610          --  This processing is causing a crash in the .NET/JVM back ends that
11611          --  is not yet understood, so skip it in these cases ???
11612
11613          if VM_Target = No_VM then
11614             Set_Itype (Ref, Subp_Ptr_Typ);
11615             Append_Freeze_Action (Task_Rec, Ref);
11616
11617             Append_To (Args,
11618               Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
11619                 Make_Qualified_Expression (Loc,
11620                   Subtype_Mark => New_Reference_To (Subp_Ptr_Typ, Loc),
11621                   Expression   =>
11622                     Make_Attribute_Reference (Loc,
11623                       Prefix =>
11624                         New_Occurrence_Of (Body_Proc, Loc),
11625                       Attribute_Name => Name_Unrestricted_Access))));
11626
11627          --  For the .NET/JVM cases revert to the original code below ???
11628
11629          else
11630             Append_To (Args,
11631               Unchecked_Convert_To (RTE (RE_Task_Procedure_Access),
11632                 Make_Attribute_Reference (Loc,
11633                   Prefix =>
11634                     New_Occurrence_Of (Body_Proc, Loc),
11635                   Attribute_Name => Name_Address)));
11636          end if;
11637       end;
11638
11639       --  Discriminants parameter. This is just the address of the task
11640       --  value record itself (which contains the discriminant values
11641
11642       Append_To (Args,
11643         Make_Attribute_Reference (Loc,
11644           Prefix => Make_Identifier (Loc, Name_uInit),
11645           Attribute_Name => Name_Address));
11646
11647       --  Elaborated parameter. This is an access to the elaboration Boolean
11648
11649       Append_To (Args,
11650         Make_Attribute_Reference (Loc,
11651           Prefix => Make_Identifier (Loc, New_External_Name (Tnam, 'E')),
11652           Attribute_Name => Name_Unchecked_Access));
11653
11654       --  Chain parameter. This is a reference to the _Chain parameter of
11655       --  the initialization procedure.
11656
11657       Append_To (Args, Make_Identifier (Loc, Name_uChain));
11658
11659       --  Task name parameter. Take this from the _Task_Id parameter to the
11660       --  init call unless there is a Task_Name pragma, in which case we take
11661       --  the value from the pragma.
11662
11663       if Present (Tdef)
11664         and then Has_Task_Name_Pragma (Tdef)
11665       then
11666          Append_To (Args,
11667            New_Copy (
11668              Expression (First (
11669                Pragma_Argument_Associations (
11670                  Find_Task_Or_Protected_Pragma
11671                    (Tdef, Name_Task_Name))))));
11672
11673       else
11674          Append_To (Args, Make_Identifier (Loc, Name_uTask_Name));
11675       end if;
11676
11677       --  Created_Task parameter. This is the _Task_Id field of the task
11678       --  record value
11679
11680       Append_To (Args,
11681         Make_Selected_Component (Loc,
11682           Prefix => Make_Identifier (Loc, Name_uInit),
11683           Selector_Name => Make_Identifier (Loc, Name_uTask_Id)));
11684
11685       if Restricted_Profile then
11686          Name := New_Reference_To (RTE (RE_Create_Restricted_Task), Loc);
11687       else
11688          Name := New_Reference_To (RTE (RE_Create_Task), Loc);
11689       end if;
11690
11691       return Make_Procedure_Call_Statement (Loc,
11692         Name => Name, Parameter_Associations => Args);
11693    end Make_Task_Create_Call;
11694
11695    ------------------------------
11696    -- Next_Protected_Operation --
11697    ------------------------------
11698
11699    function Next_Protected_Operation (N : Node_Id) return Node_Id is
11700       Next_Op : Node_Id;
11701
11702    begin
11703       Next_Op := Next (N);
11704       while Present (Next_Op)
11705         and then not Nkind_In (Next_Op, N_Subprogram_Body, N_Entry_Body)
11706       loop
11707          Next (Next_Op);
11708       end loop;
11709
11710       return Next_Op;
11711    end Next_Protected_Operation;
11712
11713    ---------------------
11714    -- Null_Statements --
11715    ---------------------
11716
11717    function Null_Statements (Stats : List_Id) return Boolean is
11718       Stmt : Node_Id;
11719
11720    begin
11721       Stmt := First (Stats);
11722       while Nkind (Stmt) /= N_Empty
11723         and then (Nkind_In (Stmt, N_Null_Statement, N_Label)
11724                     or else
11725                       (Nkind (Stmt) = N_Pragma
11726                          and then (Pragma_Name (Stmt) = Name_Unreferenced
11727                                      or else
11728                                    Pragma_Name (Stmt) = Name_Unmodified
11729                                      or else
11730                                    Pragma_Name (Stmt) = Name_Warnings)))
11731       loop
11732          Next (Stmt);
11733       end loop;
11734
11735       return Nkind (Stmt) = N_Empty;
11736    end Null_Statements;
11737
11738    --------------------------
11739    -- Parameter_Block_Pack --
11740    --------------------------
11741
11742    function Parameter_Block_Pack
11743      (Loc     : Source_Ptr;
11744       Blk_Typ : Entity_Id;
11745       Actuals : List_Id;
11746       Formals : List_Id;
11747       Decls   : List_Id;
11748       Stmts   : List_Id) return Node_Id
11749    is
11750       Actual    : Entity_Id;
11751       Expr      : Node_Id := Empty;
11752       Formal    : Entity_Id;
11753       Has_Param : Boolean := False;
11754       P         : Entity_Id;
11755       Params    : List_Id;
11756       Temp_Asn  : Node_Id;
11757       Temp_Nam  : Node_Id;
11758
11759    begin
11760       Actual := First (Actuals);
11761       Formal := Defining_Identifier (First (Formals));
11762       Params := New_List;
11763
11764       while Present (Actual) loop
11765          if Is_By_Copy_Type (Etype (Actual)) then
11766             --  Generate:
11767             --    Jnn : aliased <formal-type>
11768
11769             Temp_Nam :=
11770               Make_Defining_Identifier (Loc, New_Internal_Name ('J'));
11771
11772             Append_To (Decls,
11773               Make_Object_Declaration (Loc,
11774                 Aliased_Present =>
11775                   True,
11776                 Defining_Identifier =>
11777                   Temp_Nam,
11778                 Object_Definition =>
11779                   New_Reference_To (Etype (Formal), Loc)));
11780
11781             if Ekind (Formal) /= E_Out_Parameter then
11782
11783                --  Generate:
11784                --    Jnn := <actual>
11785
11786                Temp_Asn :=
11787                  New_Reference_To (Temp_Nam, Loc);
11788
11789                Set_Assignment_OK (Temp_Asn);
11790
11791                Append_To (Stmts,
11792                  Make_Assignment_Statement (Loc,
11793                    Name =>
11794                      Temp_Asn,
11795                    Expression =>
11796                      New_Copy_Tree (Actual)));
11797             end if;
11798
11799             --  Generate:
11800             --    Jnn'unchecked_access
11801
11802             Append_To (Params,
11803               Make_Attribute_Reference (Loc,
11804                 Attribute_Name =>
11805                   Name_Unchecked_Access,
11806                 Prefix =>
11807                   New_Reference_To (Temp_Nam, Loc)));
11808
11809             Has_Param := True;
11810
11811          --  The controlling parameter is omitted
11812
11813          else
11814             if not Is_Controlling_Actual (Actual) then
11815                Append_To (Params,
11816                  Make_Reference (Loc, New_Copy_Tree (Actual)));
11817
11818                Has_Param := True;
11819             end if;
11820          end if;
11821
11822          Next_Actual (Actual);
11823          Next_Formal_With_Extras (Formal);
11824       end loop;
11825
11826       if Has_Param then
11827          Expr := Make_Aggregate (Loc, Params);
11828       end if;
11829
11830       --  Generate:
11831       --    P : Ann := (
11832       --      J1'unchecked_access;
11833       --      <actual2>'reference;
11834       --      ...);
11835
11836       P := Make_Defining_Identifier (Loc, New_Internal_Name ('P'));
11837
11838       Append_To (Decls,
11839         Make_Object_Declaration (Loc,
11840           Defining_Identifier =>
11841             P,
11842           Object_Definition =>
11843             New_Reference_To (Blk_Typ, Loc),
11844           Expression =>
11845             Expr));
11846
11847       return P;
11848    end Parameter_Block_Pack;
11849
11850    ----------------------------
11851    -- Parameter_Block_Unpack --
11852    ----------------------------
11853
11854    function Parameter_Block_Unpack
11855      (Loc     : Source_Ptr;
11856       P       : Entity_Id;
11857       Actuals : List_Id;
11858       Formals : List_Id) return List_Id
11859    is
11860       Actual    : Entity_Id;
11861       Asnmt     : Node_Id;
11862       Formal    : Entity_Id;
11863       Has_Asnmt : Boolean := False;
11864       Result    : constant List_Id := New_List;
11865
11866    begin
11867       Actual := First (Actuals);
11868       Formal := Defining_Identifier (First (Formals));
11869       while Present (Actual) loop
11870          if Is_By_Copy_Type (Etype (Actual))
11871            and then Ekind (Formal) /= E_In_Parameter
11872          then
11873             --  Generate:
11874             --    <actual> := P.<formal>;
11875
11876             Asnmt :=
11877               Make_Assignment_Statement (Loc,
11878                 Name =>
11879                   New_Copy (Actual),
11880                 Expression =>
11881                   Make_Explicit_Dereference (Loc,
11882                     Make_Selected_Component (Loc,
11883                       Prefix =>
11884                         New_Reference_To (P, Loc),
11885                       Selector_Name =>
11886                         Make_Identifier (Loc, Chars (Formal)))));
11887
11888             Set_Assignment_OK (Name (Asnmt));
11889             Append_To (Result, Asnmt);
11890
11891             Has_Asnmt := True;
11892          end if;
11893
11894          Next_Actual (Actual);
11895          Next_Formal_With_Extras (Formal);
11896       end loop;
11897
11898       if Has_Asnmt then
11899          return Result;
11900       else
11901          return New_List (Make_Null_Statement (Loc));
11902       end if;
11903    end Parameter_Block_Unpack;
11904
11905    ----------------------
11906    -- Set_Discriminals --
11907    ----------------------
11908
11909    procedure Set_Discriminals (Dec : Node_Id) is
11910       D       : Entity_Id;
11911       Pdef    : Entity_Id;
11912       D_Minal : Entity_Id;
11913
11914    begin
11915       pragma Assert (Nkind (Dec) = N_Protected_Type_Declaration);
11916       Pdef := Defining_Identifier (Dec);
11917
11918       if Has_Discriminants (Pdef) then
11919          D := First_Discriminant (Pdef);
11920          while Present (D) loop
11921             D_Minal :=
11922               Make_Defining_Identifier (Sloc (D),
11923                 Chars => New_External_Name (Chars (D), 'D'));
11924
11925             Set_Ekind (D_Minal, E_Constant);
11926             Set_Etype (D_Minal, Etype (D));
11927             Set_Scope (D_Minal, Pdef);
11928             Set_Discriminal (D, D_Minal);
11929             Set_Discriminal_Link (D_Minal, D);
11930
11931             Next_Discriminant (D);
11932          end loop;
11933       end if;
11934    end Set_Discriminals;
11935
11936    -----------------------
11937    -- Trivial_Accept_OK --
11938    -----------------------
11939
11940    function Trivial_Accept_OK return Boolean is
11941    begin
11942       case Opt.Task_Dispatching_Policy is
11943
11944          --  If we have the default task dispatching policy in effect, we can
11945          --  definitely do the optimization (one way of looking at this is to
11946          --  think of the formal definition of the default policy being allowed
11947          --  to run any task it likes after a rendezvous, so even if notionally
11948          --  a full rescheduling occurs, we can say that our dispatching policy
11949          --  (i.e. the default dispatching policy) reorders the queue to be the
11950          --  same as just before the call.
11951
11952          when ' ' =>
11953             return True;
11954
11955          --  FIFO_Within_Priorities certainly certainly does not permit this
11956          --  optimization since the Rendezvous is a scheduling action that may
11957          --  require some other task to be run.
11958
11959          when 'F' =>
11960             return False;
11961
11962          --  For now, disallow the optimization for all other policies. This
11963          --  may be over-conservative, but it is certainly not incorrect.
11964
11965          when others =>
11966             return False;
11967
11968       end case;
11969    end Trivial_Accept_OK;
11970
11971 end Exp_Ch9;