OSDN Git Service

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