OSDN Git Service

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