OSDN Git Service

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