OSDN Git Service

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