OSDN Git Service

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