OSDN Git Service

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